<commit_before>const path = require('path');
const log = require('./utils/log');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const npmSass = require('npm-sass');
const autoprefixer = require('autoprefixer');
const postcssDiscardDuplicates = require('postcss-discard-duplicates');
const ManifestPlugin = require('webpack-manifest-plugin');
const sassImportGlobbing = require('@theme-tools/sass-import-globbing');
const { getBoltManifest, createComponentsManifest } = require('./utils/manifest');
const { promisify } = require('util');
const fs = require('fs');
const readFile = promisify(fs.readFile);
const deepmerge = require('deepmerge');

function createConfig(config) {
  // @TODO: move this setting to .boltrc config
  const sassExportData = require('@theme-tools/sass-export-data')({
    path: path.resolve(process.cwd(), config.dataDir),
  });

  // filename suffix to tack on based on lang being compiled for
  const langSuffix = `${config.lang && config.lang.length > 1 ? '-' + config.lang : ''}`;

  // Default global Sass data defined
  let globalSassData = [
    `$bolt-namespace: ${config.namespace};`,

    // output $bolt-lang variable in Sass even if not specified so things fall back accordingly.
    `${config.lang && config.lang.length > 1 ?
      `$bolt-lang: ${config.lang};` :
      '$bolt-lang: null;'
    }`,
  ];

  // Default global JS data defined
  let globalJsData = {
    'process.env.NODE_ENV': config.prod ?
      JSON.stringify('production') :
      JSON.stringify('development'),
    bolt: {
      namespace: JSON.stringify(config.namespace),
    },
  };

  // Merge together global Sass data overrides specified in a .boltrc config
  if (config.globalData.scss && config.globalData.scss.length !== 0){
    const overrideItems = [];
    config.globalData.scss.forEach((item) => {
      try {
        const file = fs.readFileSync(item, 'utf8');
        file
          .split('\n')
          .filter(x => x)
          .forEach(x => overrideItems.push(x));
      } catch(err) {
        log.errorAndExit(`Could not find ${item}`, err);
      }
    });

    globalSassData = [...globalSassData, ...overrideItems];
  }

  // Merge together any global JS data overrides
  if (config.globalData.js && config.globalData.js.length !== 0){
    const overrideJsItems = [];
    config.globalData.js.forEach((item) => {
      try {
        const overrideFile = require(path.resolve(process.cwd(), item));
        overrideJsItems.push(overrideFile);
      } catch(err) {
        log.errorAndExit(`Could not find ${item} file`, err);
      }
    });

    globalJsData = deepmerge(globalJsData, ...overrideJsItems);
  }

  /**
   * Build WebPack config's `entry` object
   * @link https://webpack.js.org/configuration/entry-context/#entry
   * @returns {object} entry - WebPack config `entry`
   */
  function buildWebpackEntry() {
    const { components } = getBoltManifest();
    const entry = {};
    const globalEntryName = 'bolt-global';

    if (components.global) {
      entry[globalEntryName] = [];

      components.global.forEach((component) => {
        if (component.assets.style) {
          entry[globalEntryName].push(component.assets.style);
        }

        if (component.assets.main) {
          entry[globalEntryName].push(component.assets.main);
        }
      });
    }
    if (components.individual) {
      components.individual.forEach((component) => {
        const files = [];
        if (component.assets.style) files.push(component.assets.style);
        if (component.assets.main) files.push(component.assets.main);
        if (files) {
          entry[component.basicName] = files;
        }
      });
    }
    if (config.verbosity > 4) {
      log.info('WebPack `entry`:');
      console.log(entry);
    }
    return entry;
  }

  // Map out the global config verbosity setting to the 6 preset levels of Webpack stats: https://webpack.js.org/configuration/stats/#stats + https://github.com/webpack/webpack/blob/b059e07cf90db871fe9497f5c14b9383fc71d2ad/lib/Stats.js#L906

  const webpackStats = {
    0: 'none', // Output nothing
    1: 'errors-only', // only output when errors happen
    2: 'minimal', // only output when errors or new compilation happen
    3: 'normal', // standard output
    4: 'detailed',
    5: 'verbose', // output everything
  };

  function statsPreset(name) {
    /**
     * Accepted values: none, errors-only, minimal, normal, detailed,
     * verbose. Any other falsy value will behave as 'none', truthy
     * values as 'normal'
     */
    const pn = (typeof name === 'string') && name.toLowerCase() || name || 'none';

    switch (pn) {
      case 'none':
        return {
          all: false,
        };
      case 'verbose':
        return {
          entrypoints: true,
          modules: false,
          colors: true,
          chunks: true,
          chunkModules: true,
          chunkOrigins: true,
          depth: true,
          env: true,
          reasons: true,
          usedExports: true,
          providedExports: true,
          optimizationBailout: true,
          errorDetails: true,
          publicPath: true,
          exclude: () => false,
          maxModules: Infinity,
        };
      case 'detailed':
        return {
          entrypoints: true,
          chunks: true,
          colors: true,
          chunkModules: false,
          chunkOrigins: true,
          depth: true,
          usedExports: true,
          providedExports: true,
          optimizationBailout: true,
          errorDetails: true,
          publicPath: true,
          exclude: () => false,
          maxModules: Infinity,
        };
      case 'minimal':
        return {
          all: false,
          colors: true,
          modules: true,
          maxModules: 0,
          errors: true,
          warnings: true,
        };
      case 'errors-only':
        return {
          all: false,
          colors: true,
          errors: true,
          moduleTrace: true,
        };
      default:
        return {
          colors: true,
        };
    }
  }

  // Output CSS module data as JSON.
  // @todo: enable when ready for CSS Modules
  // function getJSONFromCssModules(cssFileName, json) {
  //   const cssName = path.basename(cssFileName, '.css');
  //   const jsonFileName = path.resolve(process.cwd(), config.buildDir, `${cssName}.json`);
  //   fs.writeFileSync(jsonFileName, JSON.stringify(json));
  // }

  /** This workaround has been disabled for now as setting
    * `modules: false` on `css-loader` fixes it; see https://github.com/bolt-design-system/bolt/pull/410
    * Workaround for getting classes with `\@` to compile correctly
    * CSS Classes like `.u-hide\@large` were getting compiled like `.u-hide-large`.
    * Due to this bug: https://github.com/webpack-contrib/css-loader/issues/578
    * Workaround: using the `string-replace-loader` to
    * change `\@` to our `workaroundAtValue` before
    * passing to `css-loader`, then turning it back
    * afterwards.
    */
  const workaroundAtValue = '-theSlashSymbol-';

  const scssLoaders = [
    // {
    //   loader: 'string-replace-loader',
    //   query: {
    //     search: workaroundAtValue,
    //     replace: String.raw`\\`, // needed to ensure `\` comes through
    //     flags: 'g',
    //   },
    // },
    {
      loader: 'css-loader',
      options: {
        sourceMap: true,
        modules: false, // needed for JS referencing classNames directly, such as critical fonts
        importLoaders: 4,
      },
    },
    // {
    //   loader: 'string-replace-loader',
    //   query: {
    //     search: /\\/,
    //     replace: workaroundAtValue,
    //     flags: 'g',
    //   },
    // },
    {
      loader: 'postcss-loader',
      options: {
        sourceMap: true,
        plugins: () => [
          postcssDiscardDuplicates,
          autoprefixer,
        ],
      },
    },
    {
      loader: 'clean-css-loader',
      options: {
        skipWarn: true,
        compatibility: 'ie9',
        level: config.prod ? 1 : 0,
        inline: ['remote'],
        format: 'beautify',
      },
    },
    {
      loader: 'resolve-url-loader',
    },
    {
      loader: 'sass-loader',
      options: {
        sourceMap: true,
        importer: [
          sassImportGlobbing,
          npmSass.importer,
        ],
        functions: sassExportData,
        outputStyle: 'expanded',
        precision: 2,
        data: globalSassData.join('\n'),
      },
    },
  ];

  // The publicPath config sets the client-side base path for all built / asynchronously loaded assets. By default the loader script will automatically figure out the relative path to load your components, but uses publicPath as a fallback. It's recommended to have it start with a `/`. Note: this ONLY sets the base path the browser requests -- it does not set where files are saved during build. To change where files are saved at build time, use the buildDir config.
  // Must start and end with `/`
  // conditional is temp workaround for when servers are disabled via absence of `config.wwwDir`
  const publicPath = config.publicPath ? config.publicPath : (config.wwwDir
    ? `/${path.relative(config.wwwDir, config.buildDir)}/`
    : config.buildDir); // @todo Ensure ends with `/` or we can get `distfonts/` instead of `dist/fonts/`

  // THIS IS IT!! The object that gets passed in as WebPack's config object.
  const webpackConfig = {
    entry: buildWebpackEntry(),
    output: {
      path: path.resolve(process.cwd(), config.buildDir),
      filename: `[name]${langSuffix}.js`,
      chunkFilename: `[name]-bundle${langSuffix}-[chunkhash].js`,
      publicPath,
    },
    cache: true,
    resolve: {
      extensions: ['.js', '.jsx', '.json', '.svg', '.scss'],
      unsafeCache: true,
    },
    module: {
      rules: [
        {
          test: /\.scss$/,
          oneOf: [
            {
              issuer: /\.js$/,
              use: [
                scssLoaders,
              ].reduce((acc, val) => acc.concat(val), []),
            },
            {
              // no issuer here as it has a bug when its an entry point - https://github.com/webpack/webpack/issues/5906
              use: [
                {
                  loader: MiniCssExtractPlugin.loader,
                },
                scssLoaders,
              ].reduce((acc, val) => acc.concat(val), []),
            },
          ],
        },
        {
          test: /\.js$/,
          exclude: /(node_modules\/\@webcomponents\/webcomponentsjs\/custom-elements-es5-adapter\.js)/,
          use: {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true,
              babelrc: false,
              presets: ['@bolt/babel-preset-bolt'],
            },
          },
        },
        {
          test: /\.(woff|woff2)$/,
          loader: 'file-loader',
          options: {
            name: 'fonts/[name].[ext]',
          },
        },
        {
          test: /\.svg$/,
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
          },
        },
        // {
        //   test: [/\.json$/],
        //   use: [
        //     {
        //       loader: 'json-loader',
        //     },
        //   ],
        // },
        {
          test: [/\.yml$/, /\.yaml$/],
          use: [
            { loader: 'json-loader' },
            { loader: 'yaml-loader' },
          ],
        },
      ],
    },
    mode: config.prod ? 'production' : 'development',
    optimization: {
      mergeDuplicateChunks: true,
      // splitChunks: {
      //   chunks: 'all',
      //   // cacheGroups: {
      //   //   js: {
      //   //     test: /\.js$/,
      //   //     // name: 'commons',
      //   //     chunks: 'all',
      //   //     minChunks: 2,
      //   //     // test: /node_modules/,
      //   //     // enforce: true,
      //   //   },
      //   //   css: {
      //   //     test: /\.s?css$/,
      //   //     chunks: 'all',
      //   //     minChunks: 2,
      //   //     // enforce: true,
      //   //   },
      //   // },
      // },
    },
    plugins: [
      // Ignore generated output if generated output is on a dependency chain (causes endless loop)
      new webpack.WatchIgnorePlugin([
        /dist\/styleguide/,
        /dist\/annotations/,
        /styleguide/,
        path.join(__dirname, 'node_modules'),
      ]),
      new webpack.IgnorePlugin(/vertx/), // needed to ignore vertx dependency in webcomponentsjs-lite
      new MiniCssExtractPlugin({
        // Options similar to the same options in webpackOptions.output
        // both options are optional
        filename: `[name]${langSuffix}.css`,
        chunkFilename: `[id]${langSuffix}.css`,
        allChunks: true,
      }),
      // @todo This needs to be in `config.dataDir`
      new ManifestPlugin({
        fileName: `bolt-webpack-manifest${langSuffix}.json`,
        publicPath,
        writeToFileEmit: true,
        seed: {
          name: 'Bolt Manifest',
        },
      }),
      new webpack.ProvidePlugin({
        Promise: 'es6-promise',
      }),
      new webpack.DefinePlugin(globalJsData),
      // Show build progress
      // Disabling for now as it messes up spinners
      // @todo consider bringing it back
      // new webpack.ProgressPlugin({ profile: false }),
    ],
  };

  if (!config.prod) {
    webpackConfig.plugins.push(
      new webpack.HotModuleReplacementPlugin(),
    );
  }

  if (config.prod) {
    // Optimize JS - https://webpack.js.org/plugins/uglifyjs-webpack-plugin/
    // Config recommendation based off of https://slack.engineering/keep-webpack-fast-a-field-guide-for-better-build-performance-f56a5995e8f1#f548
    webpackConfig.plugins.push(new UglifyJsPlugin({
      sourceMap: true,
      parallel: true,
      cache: true,
      uglifyOptions: {
        cache: true,
        compress: true,

        mangle: true,
      },
    }));

    // https://webpack.js.org/plugins/module-concatenation-plugin/
    webpackConfig.plugins.push(new webpack.optimize.ModuleConcatenationPlugin());

    // Optimize CSS - https://github.com/NMFR/optimize-css-assets-webpack-plugin
    webpackConfig.plugins.push(new OptimizeCssAssetsPlugin({
      canPrint: config.verbosity > 2,
      cssProcessorOptions: {// passes to `cssnano`
        zindex: false, // don't alter `z-index` values
        mergeRules: false, // this MUST be disabled - otherwise certain selectors (ex. ::slotted(*), which IE 11 can't parse) break
      },
    }));

    // @todo Evaluate best source map approach for production
    webpackConfig.devtool = 'hidden-source-map';
  } else { // not prod
    // @todo fix source maps
    // webpackConfig.devtool = 'cheap-module-eval-source-map';
    webpackConfig.devtool = 'eval';
  }

  if (config.wwwDir) {
    webpackConfig.devServer = {
      contentBase: [
        path.resolve(process.cwd(), config.wwwDir),
      // @TODO: add Pattern Lab Styleguidekit Assets Default dist path here
      ],
      compress: true,
      clientLogLevel: 'none',
      port: config.proxyPort,
      stats: statsPreset(webpackStats[config.verbosity]),
      overlay: {
        errors: true,
      },
      hot: !!config.prod,
      inline: true,
      noInfo: true, // webpackTasks.watch handles output info related to success & failure
      publicPath,
      watchContentBase: true,
      historyApiFallback: true,
      watchOptions: {
        aggregateTimeout: 200,
    //    ignored: /(annotations|fonts|bower_components|dist\/styleguide|node_modules|styleguide|images|fonts|assets)/
       // Poll using interval (in ms, accepts boolean too)
      },
    };
  }

  return webpackConfig;
}

module.exports = createConfig;
<commit_msg>Fix: increase sass math precision to 3 decimals<commit_after>const path = require('path');
const log = require('./utils/log');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const npmSass = require('npm-sass');
const autoprefixer = require('autoprefixer');
const postcssDiscardDuplicates = require('postcss-discard-duplicates');
const ManifestPlugin = require('webpack-manifest-plugin');
const sassImportGlobbing = require('@theme-tools/sass-import-globbing');
const { getBoltManifest, createComponentsManifest } = require('./utils/manifest');
const { promisify } = require('util');
const fs = require('fs');
const readFile = promisify(fs.readFile);
const deepmerge = require('deepmerge');

function createConfig(config) {
  // @TODO: move this setting to .boltrc config
  const sassExportData = require('@theme-tools/sass-export-data')({
    path: path.resolve(process.cwd(), config.dataDir),
  });

  // filename suffix to tack on based on lang being compiled for
  const langSuffix = `${config.lang && config.lang.length > 1 ? '-' + config.lang : ''}`;

  // Default global Sass data defined
  let globalSassData = [
    `$bolt-namespace: ${config.namespace};`,

    // output $bolt-lang variable in Sass even if not specified so things fall back accordingly.
    `${config.lang && config.lang.length > 1 ?
      `$bolt-lang: ${config.lang};` :
      '$bolt-lang: null;'
    }`,
  ];

  // Default global JS data defined
  let globalJsData = {
    'process.env.NODE_ENV': config.prod ?
      JSON.stringify('production') :
      JSON.stringify('development'),
    bolt: {
      namespace: JSON.stringify(config.namespace),
    },
  };

  // Merge together global Sass data overrides specified in a .boltrc config
  if (config.globalData.scss && config.globalData.scss.length !== 0){
    const overrideItems = [];
    config.globalData.scss.forEach((item) => {
      try {
        const file = fs.readFileSync(item, 'utf8');
        file
          .split('\n')
          .filter(x => x)
          .forEach(x => overrideItems.push(x));
      } catch(err) {
        log.errorAndExit(`Could not find ${item}`, err);
      }
    });

    globalSassData = [...globalSassData, ...overrideItems];
  }

  // Merge together any global JS data overrides
  if (config.globalData.js && config.globalData.js.length !== 0){
    const overrideJsItems = [];
    config.globalData.js.forEach((item) => {
      try {
        const overrideFile = require(path.resolve(process.cwd(), item));
        overrideJsItems.push(overrideFile);
      } catch(err) {
        log.errorAndExit(`Could not find ${item} file`, err);
      }
    });

    globalJsData = deepmerge(globalJsData, ...overrideJsItems);
  }

  /**
   * Build WebPack config's `entry` object
   * @link https://webpack.js.org/configuration/entry-context/#entry
   * @returns {object} entry - WebPack config `entry`
   */
  function buildWebpackEntry() {
    const { components } = getBoltManifest();
    const entry = {};
    const globalEntryName = 'bolt-global';

    if (components.global) {
      entry[globalEntryName] = [];

      components.global.forEach((component) => {
        if (component.assets.style) {
          entry[globalEntryName].push(component.assets.style);
        }

        if (component.assets.main) {
          entry[globalEntryName].push(component.assets.main);
        }
      });
    }
    if (components.individual) {
      components.individual.forEach((component) => {
        const files = [];
        if (component.assets.style) files.push(component.assets.style);
        if (component.assets.main) files.push(component.assets.main);
        if (files) {
          entry[component.basicName] = files;
        }
      });
    }
    if (config.verbosity > 4) {
      log.info('WebPack `entry`:');
      console.log(entry);
    }
    return entry;
  }

  // Map out the global config verbosity setting to the 6 preset levels of Webpack stats: https://webpack.js.org/configuration/stats/#stats + https://github.com/webpack/webpack/blob/b059e07cf90db871fe9497f5c14b9383fc71d2ad/lib/Stats.js#L906

  const webpackStats = {
    0: 'none', // Output nothing
    1: 'errors-only', // only output when errors happen
    2: 'minimal', // only output when errors or new compilation happen
    3: 'normal', // standard output
    4: 'detailed',
    5: 'verbose', // output everything
  };

  function statsPreset(name) {
    /**
     * Accepted values: none, errors-only, minimal, normal, detailed,
     * verbose. Any other falsy value will behave as 'none', truthy
     * values as 'normal'
     */
    const pn = (typeof name === 'string') && name.toLowerCase() || name || 'none';

    switch (pn) {
      case 'none':
        return {
          all: false,
        };
      case 'verbose':
        return {
          entrypoints: true,
          modules: false,
          colors: true,
          chunks: true,
          chunkModules: true,
          chunkOrigins: true,
          depth: true,
          env: true,
          reasons: true,
          usedExports: true,
          providedExports: true,
          optimizationBailout: true,
          errorDetails: true,
          publicPath: true,
          exclude: () => false,
          maxModules: Infinity,
        };
      case 'detailed':
        return {
          entrypoints: true,
          chunks: true,
          colors: true,
          chunkModules: false,
          chunkOrigins: true,
          depth: true,
          usedExports: true,
          providedExports: true,
          optimizationBailout: true,
          errorDetails: true,
          publicPath: true,
          exclude: () => false,
          maxModules: Infinity,
        };
      case 'minimal':
        return {
          all: false,
          colors: true,
          modules: true,
          maxModules: 0,
          errors: true,
          warnings: true,
        };
      case 'errors-only':
        return {
          all: false,
          colors: true,
          errors: true,
          moduleTrace: true,
        };
      default:
        return {
          colors: true,
        };
    }
  }

  // Output CSS module data as JSON.
  // @todo: enable when ready for CSS Modules
  // function getJSONFromCssModules(cssFileName, json) {
  //   const cssName = path.basename(cssFileName, '.css');
  //   const jsonFileName = path.resolve(process.cwd(), config.buildDir, `${cssName}.json`);
  //   fs.writeFileSync(jsonFileName, JSON.stringify(json));
  // }

  /** This workaround has been disabled for now as setting
    * `modules: false` on `css-loader` fixes it; see https://github.com/bolt-design-system/bolt/pull/410
    * Workaround for getting classes with `\@` to compile correctly
    * CSS Classes like `.u-hide\@large` were getting compiled like `.u-hide-large`.
    * Due to this bug: https://github.com/webpack-contrib/css-loader/issues/578
    * Workaround: using the `string-replace-loader` to
    * change `\@` to our `workaroundAtValue` before
    * passing to `css-loader`, then turning it back
    * afterwards.
    */
  const workaroundAtValue = '-theSlashSymbol-';

  const scssLoaders = [
    // {
    //   loader: 'string-replace-loader',
    //   query: {
    //     search: workaroundAtValue,
    //     replace: String.raw`\\`, // needed to ensure `\` comes through
    //     flags: 'g',
    //   },
    // },
    {
      loader: 'css-loader',
      options: {
        sourceMap: true,
        modules: false, // needed for JS referencing classNames directly, such as critical fonts
        importLoaders: 4,
      },
    },
    // {
    //   loader: 'string-replace-loader',
    //   query: {
    //     search: /\\/,
    //     replace: workaroundAtValue,
    //     flags: 'g',
    //   },
    // },
    {
      loader: 'postcss-loader',
      options: {
        sourceMap: true,
        plugins: () => [
          postcssDiscardDuplicates,
          autoprefixer,
        ],
      },
    },
    {
      loader: 'clean-css-loader',
      options: {
        skipWarn: true,
        compatibility: 'ie9',
        level: config.prod ? 1 : 0,
        inline: ['remote'],
        format: 'beautify',
      },
    },
    {
      loader: 'resolve-url-loader',
    },
    {
      loader: 'sass-loader',
      options: {
        sourceMap: true,
        importer: [
          sassImportGlobbing,
          npmSass.importer,
        ],
        functions: sassExportData,
        outputStyle: 'expanded',
        precision: 3,
        data: globalSassData.join('\n'),
      },
    },
  ];

  // The publicPath config sets the client-side base path for all built / asynchronously loaded assets. By default the loader script will automatically figure out the relative path to load your components, but uses publicPath as a fallback. It's recommended to have it start with a `/`. Note: this ONLY sets the base path the browser requests -- it does not set where files are saved during build. To change where files are saved at build time, use the buildDir config.
  // Must start and end with `/`
  // conditional is temp workaround for when servers are disabled via absence of `config.wwwDir`
  const publicPath = config.publicPath ? config.publicPath : (config.wwwDir
    ? `/${path.relative(config.wwwDir, config.buildDir)}/`
    : config.buildDir); // @todo Ensure ends with `/` or we can get `distfonts/` instead of `dist/fonts/`

  // THIS IS IT!! The object that gets passed in as WebPack's config object.
  const webpackConfig = {
    entry: buildWebpackEntry(),
    output: {
      path: path.resolve(process.cwd(), config.buildDir),
      filename: `[name]${langSuffix}.js`,
      chunkFilename: `[name]-bundle${langSuffix}-[chunkhash].js`,
      publicPath,
    },
    cache: true,
    resolve: {
      extensions: ['.js', '.jsx', '.json', '.svg', '.scss'],
      unsafeCache: true,
    },
    module: {
      rules: [
        {
          test: /\.scss$/,
          oneOf: [
            {
              issuer: /\.js$/,
              use: [
                scssLoaders,
              ].reduce((acc, val) => acc.concat(val), []),
            },
            {
              // no issuer here as it has a bug when its an entry point - https://github.com/webpack/webpack/issues/5906
              use: [
                {
                  loader: MiniCssExtractPlugin.loader,
                },
                scssLoaders,
              ].reduce((acc, val) => acc.concat(val), []),
            },
          ],
        },
        {
          test: /\.js$/,
          exclude: /(node_modules\/\@webcomponents\/webcomponentsjs\/custom-elements-es5-adapter\.js)/,
          use: {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true,
              babelrc: false,
              presets: ['@bolt/babel-preset-bolt'],
            },
          },
        },
        {
          test: /\.(woff|woff2)$/,
          loader: 'file-loader',
          options: {
            name: 'fonts/[name].[ext]',
          },
        },
        {
          test: /\.svg$/,
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
          },
        },
        // {
        //   test: [/\.json$/],
        //   use: [
        //     {
        //       loader: 'json-loader',
        //     },
        //   ],
        // },
        {
          test: [/\.yml$/, /\.yaml$/],
          use: [
            { loader: 'json-loader' },
            { loader: 'yaml-loader' },
          ],
        },
      ],
    },
    mode: config.prod ? 'production' : 'development',
    optimization: {
      mergeDuplicateChunks: true,
      // splitChunks: {
      //   chunks: 'all',
      //   // cacheGroups: {
      //   //   js: {
      //   //     test: /\.js$/,
      //   //     // name: 'commons',
      //   //     chunks: 'all',
      //   //     minChunks: 2,
      //   //     // test: /node_modules/,
      //   //     // enforce: true,
      //   //   },
      //   //   css: {
      //   //     test: /\.s?css$/,
      //   //     chunks: 'all',
      //   //     minChunks: 2,
      //   //     // enforce: true,
      //   //   },
      //   // },
      // },
    },
    plugins: [
      // Ignore generated output if generated output is on a dependency chain (causes endless loop)
      new webpack.WatchIgnorePlugin([
        /dist\/styleguide/,
        /dist\/annotations/,
        /styleguide/,
        path.join(__dirname, 'node_modules'),
      ]),
      new webpack.IgnorePlugin(/vertx/), // needed to ignore vertx dependency in webcomponentsjs-lite
      new MiniCssExtractPlugin({
        // Options similar to the same options in webpackOptions.output
        // both options are optional
        filename: `[name]${langSuffix}.css`,
        chunkFilename: `[id]${langSuffix}.css`,
        allChunks: true,
      }),
      // @todo This needs to be in `config.dataDir`
      new ManifestPlugin({
        fileName: `bolt-webpack-manifest${langSuffix}.json`,
        publicPath,
        writeToFileEmit: true,
        seed: {
          name: 'Bolt Manifest',
        },
      }),
      new webpack.ProvidePlugin({
        Promise: 'es6-promise',
      }),
      new webpack.DefinePlugin(globalJsData),
      // Show build progress
      // Disabling for now as it messes up spinners
      // @todo consider bringing it back
      // new webpack.ProgressPlugin({ profile: false }),
    ],
  };

  if (!config.prod) {
    webpackConfig.plugins.push(
      new webpack.HotModuleReplacementPlugin(),
    );
  }

  if (config.prod) {
    // Optimize JS - https://webpack.js.org/plugins/uglifyjs-webpack-plugin/
    // Config recommendation based off of https://slack.engineering/keep-webpack-fast-a-field-guide-for-better-build-performance-f56a5995e8f1#f548
    webpackConfig.plugins.push(new UglifyJsPlugin({
      sourceMap: true,
      parallel: true,
      cache: true,
      uglifyOptions: {
        cache: true,
        compress: true,

        mangle: true,
      },
    }));

    // https://webpack.js.org/plugins/module-concatenation-plugin/
    webpackConfig.plugins.push(new webpack.optimize.ModuleConcatenationPlugin());

    // Optimize CSS - https://github.com/NMFR/optimize-css-assets-webpack-plugin
    webpackConfig.plugins.push(new OptimizeCssAssetsPlugin({
      canPrint: config.verbosity > 2,
      cssProcessorOptions: {// passes to `cssnano`
        zindex: false, // don't alter `z-index` values
        mergeRules: false, // this MUST be disabled - otherwise certain selectors (ex. ::slotted(*), which IE 11 can't parse) break
      },
    }));

    // @todo Evaluate best source map approach for production
    webpackConfig.devtool = 'hidden-source-map';
  } else { // not prod
    // @todo fix source maps
    // webpackConfig.devtool = 'cheap-module-eval-source-map';
    webpackConfig.devtool = 'eval';
  }

  if (config.wwwDir) {
    webpackConfig.devServer = {
      contentBase: [
        path.resolve(process.cwd(), config.wwwDir),
      // @TODO: add Pattern Lab Styleguidekit Assets Default dist path here
      ],
      compress: true,
      clientLogLevel: 'none',
      port: config.proxyPort,
      stats: statsPreset(webpackStats[config.verbosity]),
      overlay: {
        errors: true,
      },
      hot: !!config.prod,
      inline: true,
      noInfo: true, // webpackTasks.watch handles output info related to success & failure
      publicPath,
      watchContentBase: true,
      historyApiFallback: true,
      watchOptions: {
        aggregateTimeout: 200,
    //    ignored: /(annotations|fonts|bower_components|dist\/styleguide|node_modules|styleguide|images|fonts|assets)/
       // Poll using interval (in ms, accepts boolean too)
      },
    };
  }

  return webpackConfig;
}

module.exports = createConfig;
<|endoftext|>


<commit_before>const getElementById = require('../../_common/common_functions').getElementById;
const MenuSelector   = require('../../_common/menu_selector');
const ClientBase     = require('../../_common/base/client_base');

module.exports = {
    BinaryOptions: {
        onLoad  : () => { MenuSelector.init(['what-are-binary-options', 'how-to-trade-binary', 'types-of-trades', 'range-of-markets', 'glossary']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    CFDs: {
        onLoad  : () => { MenuSelector.init(['what-cfds-trading', 'how-trade-cfds', 'margin-policy', 'contract-specification']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    Cryptocurrencies: {
        onLoad  : () => { MenuSelector.init(['what-crypto-trading', 'how-trade-crypto', 'margin-policy', 'contract-specification']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    Metals: {
        onLoad  : () => { MenuSelector.init(['what-metals-trading', 'how-trade-metals', 'margin-policy', 'contract-specification']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    Forex: {
        onLoad  : () => { MenuSelector.init(['what-forex-trading', 'how-to-trade-forex', 'margin-policy', 'contract-specification']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    BinaryOptionsForMT5: {
        onLoad: () => {
            let menu_sections = [
                'what-are-binary-options',
                'how-to-trade-binary',
                'types-of-trades',
            ];
            const landing_company_shortcode = ClientBase.get('landing_company_shortcode');
            if (landing_company_shortcode === 'malta' || landing_company_shortcode === 'maltainvest') {
                menu_sections = menu_sections.filter(menu_item => menu_item !== 'how-to-trade-binary');
            }
            MenuSelector.init(menu_sections);
        },
        onUnload: () => { MenuSelector.clean(); },
    },
};
<commit_msg>remove unused import<commit_after>const MenuSelector   = require('../../_common/menu_selector');
const ClientBase     = require('../../_common/base/client_base');

module.exports = {
    BinaryOptions: {
        onLoad  : () => { MenuSelector.init(['what-are-binary-options', 'how-to-trade-binary', 'types-of-trades', 'range-of-markets', 'glossary']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    CFDs: {
        onLoad  : () => { MenuSelector.init(['what-cfds-trading', 'how-trade-cfds', 'margin-policy', 'contract-specification']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    Cryptocurrencies: {
        onLoad  : () => { MenuSelector.init(['what-crypto-trading', 'how-trade-crypto', 'margin-policy', 'contract-specification']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    Metals: {
        onLoad  : () => { MenuSelector.init(['what-metals-trading', 'how-trade-metals', 'margin-policy', 'contract-specification']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    Forex: {
        onLoad  : () => { MenuSelector.init(['what-forex-trading', 'how-to-trade-forex', 'margin-policy', 'contract-specification']); },
        onUnload: () => { MenuSelector.clean(); },
    },
    BinaryOptionsForMT5: {
        onLoad: () => {
            let menu_sections = [
                'what-are-binary-options',
                'how-to-trade-binary',
                'types-of-trades',
            ];
            const landing_company_shortcode = ClientBase.get('landing_company_shortcode');
            if (landing_company_shortcode === 'malta' || landing_company_shortcode === 'maltainvest') {
                menu_sections = menu_sections.filter(menu_item => menu_item !== 'how-to-trade-binary');
            }
            MenuSelector.init(menu_sections);
        },
        onUnload: () => { MenuSelector.clean(); },
    },
};
<|endoftext|>


<commit_before>var client = new function()
{
  var self = this;

  var services = [];
  var services_dict = {};
  var services_avaible = {};

  this.addService = function(service)
  {
    services[services.length] = service;
    services_dict[service.name] = service;
  }

  /**** methods for integrated proxy ****/

  var host_connected = function(_services)
  {
    opera.postError('on host_connected: '+_services);
    services_avaible = eval("({\"" + _services.replace(/,/g, "\":1,\"") + "\":1})");
    var service = null, i = 0;
    for( ; service = services[i]; i++)
    {
      if (service.name in services_avaible)
      {
        opera.postError(service.name);
        opera.scopeEnableService(service.name);
      }
      else
      {
        alert
        (
           'Service is avaible: ' + service.name
        );

      }
    }

  }

  var receive = function(service, msg)
  {
    //opera.postError(service+' '+msg);
    var xml_doc = ( new DOMParser() ).parseFromString(msg, "application/xml");
    if(xml_doc)
    {
      services_dict[service].onreceive(xml_doc);
    }
  }

  var quit = function()
  {
    alert('Session quited');
  }

  var post_scope = function(service, msg)
  {
    if( ini.debug )
    {
      debug.logCommand(msg);
    }
    opera.scopeSendToHost(service, "<?xml version=\"1.0\"?>" + msg)
  }

  /**** methods for standalone proxy ****/

  var post_proxy = function(service, msg)
  {
    if( ini.debug )
    {
      debug.logCommand(msg);

    }
    proxy.POST("/" + service, msg);
  }

  var bindCB = function(service)
  {
    var service_name = service.name;
    var boundGetEvent = function(xml)
    {
      if(xml.documentElement.nodeName != 'timeout')
      {
        service.onreceive(xml);
      }
      proxy.GET( "/" + service_name, boundGetEvent );
    }
    return boundGetEvent;
  }

  var proxy_onsetup = function()
  {
    var service = null, i = 0;
    for( ; service = services[i]; i++)
    {
      if (!proxy.enable(service.name))
      {
        alert
        (
           'Could not find an Opera session to connect to.\n' +
           'Please try the following:\n' +
           '1. Open another Opera instance\n' +
           '2. In that Opera instance, open opera:config and check "Enable Debugging" and "Enable Script Debugging" under "Developer Tools"\n' +
           '3. Restart that Opera instance'
        );
      }
      else
      {
        service.onconnect();
        proxy.GET( "/" + service.name, bindCB(service) );
      }
    }

  }

  this.setup = function()
  {

    document.addEventListener('load', arguments.callee, false);

    var args = location.search, params = {}, arg = '', i = 0, ele = null;

    var no_params = true;

    if( args )
    {
      args = args.slice(1).split(';');
      for( ; arg = args[i]; i++)
      {
        arg = arg.split('=');
        params[arg[0]] = arg[1] ? arg[1] : true;
        no_params = false;
      }
    }

    if( params.debug || params['event-flow'] )
    {
      Debug.init();
      if(params.debug) ini.debug = true;
      if(params['event-flow']) window.__debug_event_flow__ = true;
    }
     // e.g. log-events=thread-started,thread-stopped-at,thread-finished,new-script
    if( params['log-events'] )
    {

      if(!ini.debug)
      {
        ini.debug = true;
        Debug.init();
      }
      debug.setEventFilter(params['log-events']);
    }
    // e.g. log-commands=continue
    if( params['log-commands'] )
    {
      if(!ini.debug)
      {
        ini.debug = true;
        Debug.init();
      }
      debug.setCommandFilter(params['log-commands']);
    }

    if( params['profiling'] )
    {
      Debug.init();
      window.__profiling__ = true;
      window.__times__ = [];
    }

    if( params['test'] )
    {
      Debug.init();
      window.__testing__ = true;
      window.__times_spotlight__ = [];
    }

    if( params['profile-dom'] )
    {
      Debug.init();
      window.__times_dom = [];
    }

    window[defaults.viewport] = document.getElementsByTagName(defaults.viewport_main_container)[0];

    if( viewport )
    {
      setupMarkup();

      var host = location.host.split(':');

      if( opera.scopeAddClient )
      {
        self.post = post_scope;
        opera.scopeAddClient(host_connected, receive, quit);
      }
      else
      {
        self.post = post_proxy;
        proxy.onsetup = proxy_onsetup;
        proxy.configure(host[0], host[1]);
      }
    }
    else
    {
      opera.postError('missing viewport');
    }

  }

  var setupMarkup = function()
  {

    UIBase.copyCSS(resolve_map);

    // TODO clean up

    var container = viewport.appendChild(document.createElement('div'));
    container.style.cssText = 'position:absolute;top:0;left:-1000px;';
    container.innerHTML = resolve_map_2.markup;

    var set = null, i = 0;

    for( ; set = resolve_map_2[i]; i++ )
    {
      defaults[set.target] = set.getValue();
    }
    viewport.removeChild(container);

    new CompositeView('console_new', 'Console', console_rough_layout);
    new CompositeView('js_new', 'Script', js_rough_layout);
    new CompositeView('dom_new', 'DOM', dom_rough_layout);

    new CompositeView('export_new', 'Export', export_rough_layout);

    window.topCell = new TopCell
    (
      main_layout,
      function()
      {
        this.top = 0;
        this.left = 0;
        this.width = innerWidth;
        this.height = innerHeight;
      },
      function()
      {
        this.setStartDimesions();
        this.update();
        this.setup();
      }
    );

    new SlideViews(document);
  }

  this.onquit = function()
  {
    messages.post('host-state', {state: 'inactive'});
  }

  document.addEventListener('load', this.setup, false);

}

/* TODO take that out from the global scope */
/* this is a quick hack to get the create all runtimes button in the toptab bar */
new ToolbarConfig
(
  'main-view-top-tab',
  [
    {
      handler: 'create-all-runtimes',
      title: 'Create all runtimes'
    }
  ]
)

var console_rough_layout =
{
  dir: 'v', width: 700, height: 700,
  children:
  [
    { height: 200, tabs: ['console'] }
  ]
}

var export_rough_layout =
{
  dir: 'v', width: 700, height: 700,
  children:
  [
    { height: 200, tabs: ['export_data'] }
  ]
}

var dom_rough_layout =
{
  dir: 'h', width: 700, height: 700,
  children:
  [
    {
      width: 700,
      children:
      [
        { height: 150, tabs: ['runtimes_dom', 'runtimes_css'] },
        { width: 200, tabs: ['dom-markup-style', 'dom-tree-style', 'stylesheets'] }
      ]
    },
    {
      width: 250, tabs: ['css-inspector']
    }
  ]
}

var js_rough_layout =
{
  dir: 'h', width: 700, height: 700,
  children:
  [
    {
      width: 700,
      children:
      [
        { height: 150, tabs: ['runtimes'] },
        { width: 650, tabs: ['js_source']},
      ]
    },
    {
      width: 250,
      children:
      [
        { height: 250, tabs: ['callstack', 'threads'] },
        { height: 1000, tabs: ['frame_inspection'] }
      ]
    }
  ]
}

var main_layout =
{
  id: 'main-view',
  tabs: ['js_new', 'dom_new', 'console_new', 'export_new']
}

var resolve_map_properties =
[
  {s_name: 'border-top-width'},
  {s_name: 'border-right-width'},
  {s_name: 'border-bottom-width'},
  {s_name: 'border-left-width'},
  {s_name: 'padding-top'},
  {s_name: 'padding-right'},
  {s_name: 'padding-bottom'},
  {s_name: 'padding-left'},
  {s_name: 'width'},
  {s_name: 'height'}
]

var resolve_map =
[
  {
    source: 'toolbar',
    target: Toolbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'tabs',
    target: Tabs.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'container',
    target: Container.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'top-tabs',
    target: TopTabs.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'top-container',
    target: TopContainer.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'top-statusbar',
    target: TopStatusbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'top-toolbar',
    target: TopToolbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'window-toolbar',
    target: WindowToolbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'window-header',
    target: defaults,
    properties:
    [
      {
        t_name: 'window_header_offsetHeight',
        setProp: function(source, decalaration)
        {
          return source.offsetHeight;
        }
      }
    ]
  },
  {
    source: 'window-container',
    target: WindowContainer.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'window-satusbar',
    target: WindowStatusbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'window-statusbar',
    target: defaults,
    properties:
    [
      {
        t_name: 'window_statusbar_offsetHeight',
        setProp: function(source, decalaration)
        {
          return source.offsetHeight;
        }
      }
    ]
  },
];

var resolve_map_2 =
[
  {
    id: 'test-line-height',
    property: 'lineHeight',
    target: 'js-source-line-height',
    getValue: function(){return parseInt(document.getElementById(this.id).currentStyle[this.property])}
  },
  {
    id: 'test-scrollbar-width',
    target: 'scrollbar-width',
    getValue: function(){return ( 100 - document.getElementById(this.id).offsetWidth )}
  }
];

resolve_map_2.markup =
  "
"+
    "
"+
      "
"+
        "
test
"+
        "
"+
          "

"+
        "
"
      "
"+
    "
"+
  "
";

<commit_msg>Work on built in proxy for scope<commit_after>var client = new function()
{
  var self = this;

  var services = [];
  var services_dict = {};
  var services_avaible = {};

  this.addService = function(service)
  {
    services[services.length] = service;
    services_dict[service.name] = service;
  }

  /**** methods for integrated proxy ****/

  var host_connected = function(_services)
  {
    opera.postError('on host_connected: '+_services);
    services_avaible = eval("({\"" + _services.replace(/,/g, "\":1,\"") + "\":1})");
    var service = null, i = 0;
    for( ; service = services[i]; i++)
    {
      if (service.name in services_avaible)
      {
        opera.postError(service.name);
        opera.scopeEnableService(service.name);
      }
      else
      {
        alert
        (
           'Service is avaible: ' + service.name
        );

      }
    }

  }

  var receive = function(service, msg)
  {
    //opera.postError(service+' '+msg);
    var xml_doc = ( new DOMParser() ).parseFromString(msg, "application/xml");
    if(xml_doc)
    {
      services_dict[service].onreceive(xml_doc);
    }
  }

  var quit = function()
  {
    alert('Session quited');
  }

  var post_scope = function(service, msg)
  {
    if( ini.debug )
    {
      debug.logCommand(msg);
    }
    opera.scopeTransmit(service, "<?xml version=\"1.0\"?>" + msg)
  }

  /**** methods for standalone proxy ****/

  var post_proxy = function(service, msg)
  {
    if( ini.debug )
    {
      debug.logCommand(msg);

    }
    proxy.POST("/" + service, msg);
  }

  var bindCB = function(service)
  {
    var service_name = service.name;
    var boundGetEvent = function(xml)
    {
      if(xml.documentElement.nodeName != 'timeout')
      {
        service.onreceive(xml);
      }
      proxy.GET( "/" + service_name, boundGetEvent );
    }
    return boundGetEvent;
  }

  var proxy_onsetup = function()
  {
    var service = null, i = 0;
    for( ; service = services[i]; i++)
    {
      if (!proxy.enable(service.name))
      {
        alert
        (
           'Could not find an Opera session to connect to.\n' +
           'Please try the following:\n' +
           '1. Open another Opera instance\n' +
           '2. In that Opera instance, open opera:config and check "Enable Debugging" and "Enable Script Debugging" under "Developer Tools"\n' +
           '3. Restart that Opera instance'
        );
      }
      else
      {
        service.onconnect();
        proxy.GET( "/" + service.name, bindCB(service) );
      }
    }

  }

  this.setup = function()
  {

    document.addEventListener('load', arguments.callee, false);

    var args = location.search, params = {}, arg = '', i = 0, ele = null;

    var no_params = true;

    if( args )
    {
      args = args.slice(1).split(';');
      for( ; arg = args[i]; i++)
      {
        arg = arg.split('=');
        params[arg[0]] = arg[1] ? arg[1] : true;
        no_params = false;
      }
    }

    if( params.debug || params['event-flow'] )
    {
      Debug.init();
      if(params.debug) ini.debug = true;
      if(params['event-flow']) window.__debug_event_flow__ = true;
    }
     // e.g. log-events=thread-started,thread-stopped-at,thread-finished,new-script
    if( params['log-events'] )
    {

      if(!ini.debug)
      {
        ini.debug = true;
        Debug.init();
      }
      debug.setEventFilter(params['log-events']);
    }
    // e.g. log-commands=continue
    if( params['log-commands'] )
    {
      if(!ini.debug)
      {
        ini.debug = true;
        Debug.init();
      }
      debug.setCommandFilter(params['log-commands']);
    }

    if( params['profiling'] )
    {
      Debug.init();
      window.__profiling__ = true;
      window.__times__ = [];
    }

    if( params['test'] )
    {
      Debug.init();
      window.__testing__ = true;
      window.__times_spotlight__ = [];
    }

    if( params['profile-dom'] )
    {
      Debug.init();
      window.__times_dom = [];
    }

    window[defaults.viewport] = document.getElementsByTagName(defaults.viewport_main_container)[0];

    if( viewport )
    {
      setupMarkup();

      var host = location.host.split(':');

      if( opera.scopeAddClient )
      {
        self.post = post_scope;
        opera.scopeAddClient(host_connected, receive, quit);
      }
      else
      {
        self.post = post_proxy;
        proxy.onsetup = proxy_onsetup;
        proxy.configure(host[0], host[1]);
      }
    }
    else
    {
      opera.postError('missing viewport');
    }

  }

  var setupMarkup = function()
  {

    UIBase.copyCSS(resolve_map);

    // TODO clean up

    var container = viewport.appendChild(document.createElement('div'));
    container.style.cssText = 'position:absolute;top:0;left:-1000px;';
    container.innerHTML = resolve_map_2.markup;

    var set = null, i = 0;

    for( ; set = resolve_map_2[i]; i++ )
    {
      defaults[set.target] = set.getValue();
    }
    viewport.removeChild(container);

    new CompositeView('console_new', 'Console', console_rough_layout);
    new CompositeView('js_new', 'Script', js_rough_layout);
    new CompositeView('dom_new', 'DOM', dom_rough_layout);

    new CompositeView('export_new', 'Export', export_rough_layout);

    window.topCell = new TopCell
    (
      main_layout,
      function()
      {
        this.top = 0;
        this.left = 0;
        this.width = innerWidth;
        this.height = innerHeight;
      },
      function()
      {
        this.setStartDimesions();
        this.update();
        this.setup();
      }
    );

    new SlideViews(document);
  }

  this.onquit = function()
  {
    messages.post('host-state', {state: 'inactive'});
  }

  document.addEventListener('load', this.setup, false);

}

/* TODO take that out from the global scope */
/* this is a quick hack to get the create all runtimes button in the toptab bar */
new ToolbarConfig
(
  'main-view-top-tab',
  [
    {
      handler: 'create-all-runtimes',
      title: 'Create all runtimes'
    }
  ]
)

var console_rough_layout =
{
  dir: 'v', width: 700, height: 700,
  children:
  [
    { height: 200, tabs: ['console'] }
  ]
}

var export_rough_layout =
{
  dir: 'v', width: 700, height: 700,
  children:
  [
    { height: 200, tabs: ['export_data'] }
  ]
}

var dom_rough_layout =
{
  dir: 'h', width: 700, height: 700,
  children:
  [
    {
      width: 700,
      children:
      [
        { height: 150, tabs: ['runtimes_dom', 'runtimes_css'] },
        { width: 200, tabs: ['dom-markup-style', 'dom-tree-style', 'stylesheets'] }
      ]
    },
    {
      width: 250, tabs: ['css-inspector']
    }
  ]
}

var js_rough_layout =
{
  dir: 'h', width: 700, height: 700,
  children:
  [
    {
      width: 700,
      children:
      [
        { height: 150, tabs: ['runtimes'] },
        { width: 650, tabs: ['js_source']},
      ]
    },
    {
      width: 250,
      children:
      [
        { height: 250, tabs: ['callstack', 'threads'] },
        { height: 1000, tabs: ['frame_inspection'] }
      ]
    }
  ]
}

var main_layout =
{
  id: 'main-view',
  tabs: ['js_new', 'dom_new', 'console_new', 'export_new']
}

var resolve_map_properties =
[
  {s_name: 'border-top-width'},
  {s_name: 'border-right-width'},
  {s_name: 'border-bottom-width'},
  {s_name: 'border-left-width'},
  {s_name: 'padding-top'},
  {s_name: 'padding-right'},
  {s_name: 'padding-bottom'},
  {s_name: 'padding-left'},
  {s_name: 'width'},
  {s_name: 'height'}
]

var resolve_map =
[
  {
    source: 'toolbar',
    target: Toolbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'tabs',
    target: Tabs.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'container',
    target: Container.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'top-tabs',
    target: TopTabs.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'top-container',
    target: TopContainer.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'top-statusbar',
    target: TopStatusbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'top-toolbar',
    target: TopToolbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'window-toolbar',
    target: WindowToolbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'window-header',
    target: defaults,
    properties:
    [
      {
        t_name: 'window_header_offsetHeight',
        setProp: function(source, decalaration)
        {
          return source.offsetHeight;
        }
      }
    ]
  },
  {
    source: 'window-container',
    target: WindowContainer.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'window-satusbar',
    target: WindowStatusbar.prototype,
    properties: resolve_map_properties
  },
  {
    source: 'window-statusbar',
    target: defaults,
    properties:
    [
      {
        t_name: 'window_statusbar_offsetHeight',
        setProp: function(source, decalaration)
        {
          return source.offsetHeight;
        }
      }
    ]
  },
];

var resolve_map_2 =
[
  {
    id: 'test-line-height',
    property: 'lineHeight',
    target: 'js-source-line-height',
    getValue: function(){return parseInt(document.getElementById(this.id).currentStyle[this.property])}
  },
  {
    id: 'test-scrollbar-width',
    target: 'scrollbar-width',
    getValue: function(){return ( 100 - document.getElementById(this.id).offsetWidth )}
  }
];

resolve_map_2.markup =
  "
"+
    "
"+
      "
"+
        "
test
"+
        "
"+
          "

"+
        "
"
      "
"+
    "
"+
  "
";

<|endoftext|>


<commit_before>dojo.provide("dojox.mobile.deviceTheme");

// summary:
//		Automatic Theme Loader
// description:
//		Detects the User Agent of the browser and loads appropriate theme files.
//		Simply dojo.require this module to enable the automatic theme loading.
//
//		By default, an all-in-one theme file (e.g. themes/iphone/iphone.css) is
//		loaded. The all-in-one theme files contain style sheets for all the
//		dojox.mobile widgets regardless of whether they are used in your
//		application or not.
//		If you want to choose what theme files to load, you can specify them
//		via djConfig as shown in the following example:
//
//	|	djConfig="parseOnLoad:true, mblThemeFiles:['base','Button']"
//
//		Or you may want to use dojox.mobile.themeFiles as follows to get the
//		same result. Note that the assignment has to be done before loading
//		deviceTheme.js.
//
//	|	dojo.require("dojox.mobile");
//	|	dojox.mobile.themeFiles = ['base','Button'];
//	|	dojo.require("dojox.mobile.deviceTheme");
//
//		In the case of this example, if iphone is detected, for example, the
//		following files will be loaded:
//
//	|	dojox/mobile/themes/iphone/base.css
//	|	dojox/mobile/themes/iphone/Button.css
//
//		If you want to load style sheets for your own custom widgets, you can
//		specify a package name along with a theme file name in an array.
//
//	|	['base',['com.acme','MyWidget']]
//
//		In this case, the following files will be loaded.
//
//	|	dojox/mobile/themes/iphone/base.css
//	|	com/acme/themes/iphone/MyWidget.css
//
//		If you specify '@theme' as a theme file name, it will be replaced with
//		the theme folder name. For example,
//
//	|	['@theme',['com.acme','MyWidget']]
//
//		will load the following files.
//
//	|	dojox/mobile/themes/iphone/iphone.css
//	|	com/acme/themes/iphone/MyWidget.css

dojox.mobile.loadCssFile = function(/*String*/file){
	dojo.create("LINK", {
		href: file,
		type: "text/css",
		rel: "stylesheet"
	}, dojo.doc.getElementsByTagName('head')[0]);
};

dojox.mobile.themeMap = [
	// summary:
	//		A map of user-agents to theme files.
	// description:
	//		The first array element is a regexp pattern that matches the
	//		userAgent string.
	//
	//		The second array element is a theme folder name.
	//
	//		The third array element is an array of css file paths to load.
	//
	//		The matching is performed in the array order, and stops after the
	//		first match.
	[
		"Android",
		"android",
		[]
	],
	[
		"BlackBerry",
		"blackberry",
		[]
	],
	[
		"iPad",
		"iphone",
		[dojo.moduleUrl("dojox.mobile", "themes/iphone/ipad.css")]
	],
	[
		".*",
		"iphone",
		[]
	]
];

dojox.mobile.loadDeviceTheme = function(){
	var t = dojo.config["mblThemeFiles"] || dojox.mobile.themeFiles || ["@theme"];
	if(!dojo.isArray(t)){ alert("loadDeviceTheme: array is expected but found: "+t); }
	var i, j;
	var m = dojox.mobile.themeMap;
	for(i = 0; i < m.length; i++){
		var re1 = new RegExp("theme="+m[i][0]);
		var re2 = new RegExp(m[i][0]);
		if(location.search.match(re1) || navigator.userAgent.match(re2)){
			var theme = m[i][1];
			var files = m[i][2];
			for(j = t.length - 1; j >= 0; j--){
				var pkg = dojo.isArray(t[j]) ? t[j][0] : "dojox.mobile";
				var name = dojo.isArray(t[j]) ? t[j][1] : t[j];
				var f = "themes/" + theme + "/" +
					(name === "@theme" ? theme : name) + ".css";
				files.unshift(dojo.moduleUrl(pkg, f));
			}
			for(j = 0; j < files.length; j++){
				dojox.mobile.loadCssFile(files[j]);
			}
			break;
		}
	}
};

dojox.mobile.loadDeviceTheme();
<commit_msg>Fixes #12720 !strict. Check the query string parameter first, then User-Agent string.<commit_after>dojo.provide("dojox.mobile.deviceTheme");

// summary:
//		Automatic Theme Loader
// description:
//		Detects the User Agent of the browser and loads appropriate theme files.
//		Simply dojo.require this module to enable the automatic theme loading.
//
//		By default, an all-in-one theme file (e.g. themes/iphone/iphone.css) is
//		loaded. The all-in-one theme files contain style sheets for all the
//		dojox.mobile widgets regardless of whether they are used in your
//		application or not.
//		If you want to choose what theme files to load, you can specify them
//		via djConfig as shown in the following example:
//
//	|	djConfig="parseOnLoad:true, mblThemeFiles:['base','Button']"
//
//		Or you may want to use dojox.mobile.themeFiles as follows to get the
//		same result. Note that the assignment has to be done before loading
//		deviceTheme.js.
//
//	|	dojo.require("dojox.mobile");
//	|	dojox.mobile.themeFiles = ['base','Button'];
//	|	dojo.require("dojox.mobile.deviceTheme");
//
//		In the case of this example, if iphone is detected, for example, the
//		following files will be loaded:
//
//	|	dojox/mobile/themes/iphone/base.css
//	|	dojox/mobile/themes/iphone/Button.css
//
//		If you want to load style sheets for your own custom widgets, you can
//		specify a package name along with a theme file name in an array.
//
//	|	['base',['com.acme','MyWidget']]
//
//		In this case, the following files will be loaded.
//
//	|	dojox/mobile/themes/iphone/base.css
//	|	com/acme/themes/iphone/MyWidget.css
//
//		If you specify '@theme' as a theme file name, it will be replaced with
//		the theme folder name. For example,
//
//	|	['@theme',['com.acme','MyWidget']]
//
//		will load the following files.
//
//	|	dojox/mobile/themes/iphone/iphone.css
//	|	com/acme/themes/iphone/MyWidget.css

dojox.mobile.loadCssFile = function(/*String*/file){
	dojo.create("LINK", {
		href: file,
		type: "text/css",
		rel: "stylesheet"
	}, dojo.doc.getElementsByTagName('head')[0]);
};

dojox.mobile.themeMap = [
	// summary:
	//		A map of user-agents to theme files.
	// description:
	//		The first array element is a regexp pattern that matches the
	//		userAgent string.
	//
	//		The second array element is a theme folder name.
	//
	//		The third array element is an array of css file paths to load.
	//
	//		The matching is performed in the array order, and stops after the
	//		first match.
	[
		"Android",
		"android",
		[]
	],
	[
		"BlackBerry",
		"blackberry",
		[]
	],
	[
		"iPad",
		"iphone",
		[dojo.moduleUrl("dojox.mobile", "themes/iphone/ipad.css")]
	],
	[
		".*",
		"iphone",
		[]
	]
];

dojox.mobile.loadDeviceTheme = function(){
	var t = dojo.config["mblThemeFiles"] || dojox.mobile.themeFiles || ["@theme"];
	if(!dojo.isArray(t)){ alert("loadDeviceTheme: array is expected but found: "+t); }
	var i, j;
	var m = dojox.mobile.themeMap;
	var ua = (location.search.match(/theme=(\w+)/)) ? RegExp.$1 : navigator.userAgent;
	for(i = 0; i < m.length; i++){
		if(ua.match(new RegExp(m[i][0]))){
			var theme = m[i][1];
			var files = m[i][2];
			for(j = t.length - 1; j >= 0; j--){
				var pkg = dojo.isArray(t[j]) ? t[j][0] : "dojox.mobile";
				var name = dojo.isArray(t[j]) ? t[j][1] : t[j];
				var f = "themes/" + theme + "/" +
					(name === "@theme" ? theme : name) + ".css";
				files.unshift(dojo.moduleUrl(pkg, f));
			}
			for(j = 0; j < files.length; j++){
				dojox.mobile.loadCssFile(files[j]);
			}
			break;
		}
	}
};

dojox.mobile.loadDeviceTheme();
<|endoftext|>


<commit_before>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var createLine = require('regl-line2d');

var Registry = require('../../registry');
var prepareRegl = require('../../lib/prepare_regl');
var getModuleCalcData = require('../../plots/get_data').getModuleCalcData;
var Cartesian = require('../../plots/cartesian');
var getFromId = require('../../plots/cartesian/axis_ids').getFromId;
var shouldShowZeroLine = require('../../plots/cartesian/axes').shouldShowZeroLine;

var SPLOM = 'splom';

function plot(gd) {
    var fullLayout = gd._fullLayout;
    var _module = Registry.getModule(SPLOM);
    var splomCalcData = getModuleCalcData(gd.calcdata, _module)[0];

    var success = prepareRegl(gd, ['ANGLE_instanced_arrays', 'OES_element_index_uint']);
    if(!success) return;

    if(fullLayout._hasOnlyLargeSploms) {
        drawGrid(gd);
    }

    _module.plot(gd, {}, splomCalcData);
}

function drag(gd) {
    var cd = gd.calcdata;
    var fullLayout = gd._fullLayout;

    if(fullLayout._hasOnlyLargeSploms) {
        drawGrid(gd);
    }

    for(var i = 0; i < cd.length; i++) {
        var cd0 = cd[i][0];
        var trace = cd0.trace;
        var scene = fullLayout._splomScenes[trace.uid];

        if(trace.type === 'splom' && scene && scene.matrix) {
            dragOne(gd, trace, scene);
        }
    }
}

function dragOne(gd, trace, scene) {
    var visibleLength = scene.matrixOptions.data.length;
    var visibleDims = trace._visibleDims;
    var ranges = scene.viewOpts.ranges = new Array(visibleLength);

    for(var k = 0; k < visibleDims.length; k++) {
        var i = visibleDims[k];
        var rng = ranges[k] = new Array(4);

        var xa = getFromId(gd, trace._diag[i][0]);
        if(xa) {
            rng[0] = xa.r2l(xa.range[0]);
            rng[2] = xa.r2l(xa.range[1]);
        }

        var ya = getFromId(gd, trace._diag[i][1]);
        if(ya) {
            rng[1] = ya.r2l(ya.range[0]);
            rng[3] = ya.r2l(ya.range[1]);
        }
    }

    if(scene.selectBatch) {
        scene.matrix.update({ranges: ranges}, {ranges: ranges});
        scene.matrix.draw(scene.unselectBatch, scene.selectBatch);
    } else {
        scene.matrix.update({ranges: ranges});
        scene.matrix.draw();
    }
}

function drawGrid(gd) {
    var fullLayout = gd._fullLayout;
    var regl = fullLayout._glcanvas.data()[0].regl;
    var splomGrid = fullLayout._splomGrid;

    if(!splomGrid) {
        splomGrid = fullLayout._splomGrid = createLine(regl);
    }

    splomGrid.update(makeGridData(gd));
    splomGrid.draw();
}

function makeGridData(gd) {
    var fullLayout = gd._fullLayout;
    var gs = fullLayout._size;
    var fullView = [0, 0, fullLayout.width, fullLayout.height];
    var lookup = {};
    var k;

    function push(prefix, ax, x0, x1, y0, y1) {
        var lcolor = ax[prefix + 'color'];
        var lwidth = ax[prefix + 'width'];
        var key = String(lcolor + lwidth);

        if(key in lookup) {
            lookup[key].data.push(NaN, NaN, x0, x1, y0, y1);
        } else {
            lookup[key] = {
                data: [x0, x1, y0, y1],
                join: 'rect',
                thickness: lwidth,
                color: lcolor,
                viewport: fullView,
                range: fullView,
                overlay: false
            };
        }
    }

    for(k in fullLayout._splomSubplots) {
        var sp = fullLayout._plots[k];
        var xa = sp.xaxis;
        var ya = sp.yaxis;
        var xVals = xa._vals;
        var yVals = ya._vals;
        // ya.l2p assumes top-to-bottom coordinate system (a la SVG),
        // we need to compute bottom-to-top offsets and slopes:
        var yOffset = gs.b + ya.domain[0] * gs.h;
        var ym = -ya._m;
        var yb = -ym * ya.r2l(ya.range[0], ya.calendar);
        var x, y;

        if(xa.showgrid) {
            for(k = 0; k < xVals.length; k++) {
                x = xa._offset + xa.l2p(xVals[k].x);
                push('grid', xa, x, yOffset, x, yOffset + ya._length);
            }
        }
        if(ya.showgrid) {
            for(k = 0; k < yVals.length; k++) {
                y = yOffset + yb + ym * yVals[k].x;
                push('grid', ya, xa._offset, y, xa._offset + xa._length, y);
            }
        }
        if(shouldShowZeroLine(gd, xa, ya)) {
            x = xa._offset + xa.l2p(0);
            push('zeroline', xa, x, yOffset, x, yOffset + ya._length);
        }
        if(shouldShowZeroLine(gd, ya, xa)) {
            y = yOffset + yb + 0;
            push('zeroline', ya, xa._offset, y, xa._offset + xa._length, y);
        }
    }

    var gridBatches = [];
    for(k in lookup) {
        gridBatches.push(lookup[k]);
    }

    return gridBatches;
}

function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
    oldLoop:
    for(var i = 0; i < oldFullData.length; i++) {
        var oldTrace = oldFullData[i];

        if(oldTrace.type === 'splom') {
            for(var j = 0; j < newFullData.length; j++) {
                var newTrace = newFullData[j];

                if(oldTrace.uid === newTrace.uid && newTrace.type === 'splom') {
                    continue oldLoop;
                }
            }

            if(oldFullLayout._splomScenes) {
                var scene = oldFullLayout._splomScenes[oldTrace.uid];
                if(scene && scene.destroy) scene.destroy();
                // must first set scene to null in order to get garbage collected
                oldFullLayout._splomScenes[oldTrace.uid] = null;
                delete oldFullLayout._splomScenes[oldTrace.uid];
            }
        }
    }

    if(Object.keys(oldFullLayout._splomScenes || {}).length === 0) {
        delete oldFullLayout._splomScenes;
    }

    if(oldFullLayout._splomGrid &&
        (!newFullLayout._hasOnlyLargeSploms && oldFullLayout._hasOnlyLargeSploms)) {
        // must first set scene to null in order to get garbage collected
        oldFullLayout._splomGrid.destroy();
        oldFullLayout._splomGrid = null;
        delete oldFullLayout._splomGrid;
    }

    Cartesian.clean(newFullData, newFullLayout, oldFullData, oldFullLayout);
}

function updateFx(gd) {
    Cartesian.updateFx(gd);

    var fullLayout = gd._fullLayout;
    var dragmode = fullLayout.dragmode;

    // unset selection styles when coming out of a selection mode
    if(dragmode === 'zoom' || dragmode === 'pan') {
        var cd = gd.calcdata;

        for(var i = 0; i < cd.length; i++) {
            var cd0 = cd[i][0];
            var trace = cd0.trace;

            if(trace.type === 'splom') {
                var scene = fullLayout._splomScenes[trace.uid];
                if(scene.selectBatch === null) {
                    scene.matrix.update(scene.matrixOptions, null);
                }
            }
        }
    }
}

module.exports = {
    name: SPLOM,
    attr: Cartesian.attr,
    attrRegex: Cartesian.attrRegex,
    layoutAttributes: Cartesian.layoutAttributes,
    supplyLayoutDefaults: Cartesian.supplyLayoutDefaults,
    drawFramework: Cartesian.drawFramework,
    plot: plot,
    drag: drag,
    clean: clean,
    updateFx: updateFx,
    toSVG: Cartesian.toSVG
};
<commit_msg>speed up splom.clean<commit_after>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var createLine = require('regl-line2d');

var Registry = require('../../registry');
var prepareRegl = require('../../lib/prepare_regl');
var getModuleCalcData = require('../../plots/get_data').getModuleCalcData;
var Cartesian = require('../../plots/cartesian');
var getFromId = require('../../plots/cartesian/axis_ids').getFromId;
var shouldShowZeroLine = require('../../plots/cartesian/axes').shouldShowZeroLine;

var SPLOM = 'splom';

function plot(gd) {
    var fullLayout = gd._fullLayout;
    var _module = Registry.getModule(SPLOM);
    var splomCalcData = getModuleCalcData(gd.calcdata, _module)[0];

    var success = prepareRegl(gd, ['ANGLE_instanced_arrays', 'OES_element_index_uint']);
    if(!success) return;

    if(fullLayout._hasOnlyLargeSploms) {
        drawGrid(gd);
    }

    _module.plot(gd, {}, splomCalcData);
}

function drag(gd) {
    var cd = gd.calcdata;
    var fullLayout = gd._fullLayout;

    if(fullLayout._hasOnlyLargeSploms) {
        drawGrid(gd);
    }

    for(var i = 0; i < cd.length; i++) {
        var cd0 = cd[i][0];
        var trace = cd0.trace;
        var scene = fullLayout._splomScenes[trace.uid];

        if(trace.type === 'splom' && scene && scene.matrix) {
            dragOne(gd, trace, scene);
        }
    }
}

function dragOne(gd, trace, scene) {
    var visibleLength = scene.matrixOptions.data.length;
    var visibleDims = trace._visibleDims;
    var ranges = scene.viewOpts.ranges = new Array(visibleLength);

    for(var k = 0; k < visibleDims.length; k++) {
        var i = visibleDims[k];
        var rng = ranges[k] = new Array(4);

        var xa = getFromId(gd, trace._diag[i][0]);
        if(xa) {
            rng[0] = xa.r2l(xa.range[0]);
            rng[2] = xa.r2l(xa.range[1]);
        }

        var ya = getFromId(gd, trace._diag[i][1]);
        if(ya) {
            rng[1] = ya.r2l(ya.range[0]);
            rng[3] = ya.r2l(ya.range[1]);
        }
    }

    if(scene.selectBatch) {
        scene.matrix.update({ranges: ranges}, {ranges: ranges});
        scene.matrix.draw(scene.unselectBatch, scene.selectBatch);
    } else {
        scene.matrix.update({ranges: ranges});
        scene.matrix.draw();
    }
}

function drawGrid(gd) {
    var fullLayout = gd._fullLayout;
    var regl = fullLayout._glcanvas.data()[0].regl;
    var splomGrid = fullLayout._splomGrid;

    if(!splomGrid) {
        splomGrid = fullLayout._splomGrid = createLine(regl);
    }

    splomGrid.update(makeGridData(gd));
    splomGrid.draw();
}

function makeGridData(gd) {
    var fullLayout = gd._fullLayout;
    var gs = fullLayout._size;
    var fullView = [0, 0, fullLayout.width, fullLayout.height];
    var lookup = {};
    var k;

    function push(prefix, ax, x0, x1, y0, y1) {
        var lcolor = ax[prefix + 'color'];
        var lwidth = ax[prefix + 'width'];
        var key = String(lcolor + lwidth);

        if(key in lookup) {
            lookup[key].data.push(NaN, NaN, x0, x1, y0, y1);
        } else {
            lookup[key] = {
                data: [x0, x1, y0, y1],
                join: 'rect',
                thickness: lwidth,
                color: lcolor,
                viewport: fullView,
                range: fullView,
                overlay: false
            };
        }
    }

    for(k in fullLayout._splomSubplots) {
        var sp = fullLayout._plots[k];
        var xa = sp.xaxis;
        var ya = sp.yaxis;
        var xVals = xa._vals;
        var yVals = ya._vals;
        // ya.l2p assumes top-to-bottom coordinate system (a la SVG),
        // we need to compute bottom-to-top offsets and slopes:
        var yOffset = gs.b + ya.domain[0] * gs.h;
        var ym = -ya._m;
        var yb = -ym * ya.r2l(ya.range[0], ya.calendar);
        var x, y;

        if(xa.showgrid) {
            for(k = 0; k < xVals.length; k++) {
                x = xa._offset + xa.l2p(xVals[k].x);
                push('grid', xa, x, yOffset, x, yOffset + ya._length);
            }
        }
        if(ya.showgrid) {
            for(k = 0; k < yVals.length; k++) {
                y = yOffset + yb + ym * yVals[k].x;
                push('grid', ya, xa._offset, y, xa._offset + xa._length, y);
            }
        }
        if(shouldShowZeroLine(gd, xa, ya)) {
            x = xa._offset + xa.l2p(0);
            push('zeroline', xa, x, yOffset, x, yOffset + ya._length);
        }
        if(shouldShowZeroLine(gd, ya, xa)) {
            y = yOffset + yb + 0;
            push('zeroline', ya, xa._offset, y, xa._offset + xa._length, y);
        }
    }

    var gridBatches = [];
    for(k in lookup) {
        gridBatches.push(lookup[k]);
    }

    return gridBatches;
}

function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
    var lookup = {};
    var i;

    if(oldFullLayout._splomScenes) {
        for(i = 0; i < newFullData.length; i++) {
            var newTrace = newFullData[i];
            if(newTrace.type === 'splom') {
                lookup[newTrace.uid] = 1;
            }
        }
        for(i = 0; i < oldFullData.length; i++) {
            var oldTrace = oldFullData[i];
            if(!lookup[oldTrace.uid]) {
                var scene = oldFullLayout._splomScenes[oldTrace.uid];
                if(scene && scene.destroy) scene.destroy();
                // must first set scene to null in order to get garbage collected
                oldFullLayout._splomScenes[oldTrace.uid] = null;
                delete oldFullLayout._splomScenes[oldTrace.uid];
            }
        }
    }

    if(Object.keys(oldFullLayout._splomScenes || {}).length === 0) {
        delete oldFullLayout._splomScenes;
    }

    if(oldFullLayout._splomGrid &&
        (!newFullLayout._hasOnlyLargeSploms && oldFullLayout._hasOnlyLargeSploms)) {
        // must first set scene to null in order to get garbage collected
        oldFullLayout._splomGrid.destroy();
        oldFullLayout._splomGrid = null;
        delete oldFullLayout._splomGrid;
    }

    Cartesian.clean(newFullData, newFullLayout, oldFullData, oldFullLayout);
}

function updateFx(gd) {
    Cartesian.updateFx(gd);

    var fullLayout = gd._fullLayout;
    var dragmode = fullLayout.dragmode;

    // unset selection styles when coming out of a selection mode
    if(dragmode === 'zoom' || dragmode === 'pan') {
        var cd = gd.calcdata;

        for(var i = 0; i < cd.length; i++) {
            var cd0 = cd[i][0];
            var trace = cd0.trace;

            if(trace.type === 'splom') {
                var scene = fullLayout._splomScenes[trace.uid];
                if(scene.selectBatch === null) {
                    scene.matrix.update(scene.matrixOptions, null);
                }
            }
        }
    }
}

module.exports = {
    name: SPLOM,
    attr: Cartesian.attr,
    attrRegex: Cartesian.attrRegex,
    layoutAttributes: Cartesian.layoutAttributes,
    supplyLayoutDefaults: Cartesian.supplyLayoutDefaults,
    drawFramework: Cartesian.drawFramework,
    plot: plot,
    drag: drag,
    clean: clean,
    updateFx: updateFx,
    toSVG: Cartesian.toSVG
};
<|endoftext|>


<commit_before>/**
* Frost ___ Plugin
* Informational commands
* by: panpawn
*/

exports.commands = {
	coldfront: 'frostmag',
	frostmag: function (target, room, user, connection) {
		if (room.id !== 'coldfront') return false;
		if (!this.canTalk()) return;
		var mag = target;
		var mag_name = "Cold Front";
		var allowed_set_usernames = ['flicette','panpawn'];
		var mag1 = toId(mag.slice(0, mag.indexOf(', ')));
		var mag2 = mag.slice(mag.indexOf(', ') + 1).trim();
		var link_to_newest_issue = Rooms.rooms.lobby.frostMagLink;
		if (mag1 === 'set') {
			if (allowed_set_usernames.indexOf(toId(user.name)) === -1) return false;
			link_to_newest_issue = mag2;
			this.sendReply("The link to the newest issue has been set to: " + link_to_newest_issue);
			this.logModCommand(user.name + " has set the link of the newest issue of the " + mag_name + " to be: " + link_to_newest_issue);
		} else {
			if (!this.canBroadcast()) return;
			this.sendReplyBox(
				"" + mag_name + "
 " +
				"- A link to the site of the " + mag_name + " can be found here.
" +
				"- For information on how to become a contrubutor, go here.
" +
				"- A link to our newest issue can be found here."
			);
		}
	}
};
<commit_msg>Update coldfront.js<commit_after>/**
* Frost ___ Plugin
* Informational commands
* by: panpawn
*/

var link_to_newest_issue = Rooms.rooms.lobby.frostMagLink;
exports.commands = {
	coldfront: 'frostmag',
	frostmag: function (target, room, user, connection) {
		if (room.id !== 'coldfront') return false;
		if (!this.canTalk()) return;
		var mag = target;
		var mag_name = "Cold Front";
		var allowed_set_usernames = ['flicette','panpawn'];
		var mag1 = toId(mag.slice(0, mag.indexOf(', ')));
		var mag2 = mag.slice(mag.indexOf(', ') + 1).trim();
		if (mag1 === 'set') {
			if (allowed_set_usernames.indexOf(toId(user.name)) === -1) return false;
			link_to_newest_issue = mag2;
			this.sendReply("The link to the newest issue has been set to: " + link_to_newest_issue);
			this.logModCommand(user.name + " has set the link of the newest issue of the " + mag_name + " to be: " + link_to_newest_issue);
		} else {
			if (!this.canBroadcast()) return;
			this.sendReplyBox(
				"" + mag_name + "
 " +
				"- A link to the site of the " + mag_name + " can be found here.
" +
				"- For information on how to become a contrubutor, go here.
" +
				"- A link to our newest issue can be found here."
			);
		}
	}
};
<|endoftext|>


<commit_before>const { toKeyValue, fromKeyValue } = require('../api/key-value');
const api = require('../api');

const resolvers = {
  Query: {
    account: () => api.account.get(),
    keys: (root, { login, name }) =>
      name
        ? api.keys.get({ login, name }).then(key => [key])
        : api.keys.list({ login, name }),
    key: (root, { login, name }) => api.keys.get({ login, name }),
    users: (root, { id }) =>
      id ? api.users.get({ id }).then(user => [user]) : api.users.list(),
    user: (root, { id }) => api.users.get({ id }),
    roles: (root, { id, name }) =>
      id || name
        ? api.roles.get({ id, name }).then(role => [role])
        : api.roles.list(),
    role: (root, { id, name }) => api.roles.get({ id, name }),
    policies: (root, { id }) =>
      id
        ? api.policies.get({ id }).then(policy => [policy])
        : api.policies.list(),
    policy: (root, { id }) => api.policies.get({ id }),
    config: () => api.config().then(toKeyValue),
    datacenters: () =>
      api.datacenters().then(dcs =>
        Object.keys(dcs).map(name => ({
          name,
          url: dcs[name]
        }))
      ),
    services: () => api.services().then(toKeyValue),
    images: (root, { id, ...rest }) =>
      id
        ? api.images.get({ id }).then(image => [image])
        : api.images.list(rest),
    image: (root, { id }) => api.images.get({ id }),
    packages: (root, { id, ...rest }) =>
      id
        ? api.packages.get({ id }).then(pkg => [pkg])
        : api.packages.list(rest),
    package: (root, { id, name }) => api.packages.get({ id, name }),
    machines: (root, { id, brand, state, tags, ...rest }) =>
      id
        ? api.machines.get({ id }).then(machine => [machine])
        : api.machines.list(
            Object.assign(rest, {
              brand: brand ? brand.toLowerCase() : brand,
              state: state ? state.toLowerCase() : state,
              tags: fromKeyValue(tags)
            })
          ),
    machine: (root, { id }) => api.machines.get({ id }),
    snapshots: (root, { name, machine }) =>
      name
        ? api.machines.snapshots
            .get({ id: machine, name })
            .then(snapshot => [snapshot])
        : api.machines.snapshots.list({ id: machine }),
    snapshot: (root, { name, machine }) =>
      api.machines.snapshots.get({ name, id: machine }),
    metadata: (root, { machine, name, ...rest }) =>
      name
        ? api.machines.metadata
            .get(Object.assign(rest, { id: machine, key: name }))
            .then(value => toKeyValue({ [name]: value }))
        : api.machines.metadata.list({ id: machine }).then(toKeyValue),
    metadataValue: (root, { name, machine }) =>
      api.machines.metadata
        .get({ key: name, id: machine })
        .then(value => toKeyValue({ [name]: value }).shift()),
    tags: (root, { machine, name }) =>
      name
        ? api.machines.tags
            .get({ id: machine, tag: name })
            .then(value => toKeyValue({ [name]: value }))
        : api.machines.tags.list({ id: machine }).then(toKeyValue),
    tag: (root, { machine, name }) =>
      api.machines.tags
        .get({ id: machine, tag: name })
        .then(value => toKeyValue({ [name]: value }).shift()),
    actions: (root, { machine }) => api.machines.audit({ id: machine }),
    // eslint-disable-next-line camelcase
    firewall_rules: (root, { machine, id }) =>
      id
        ? api.firewall.get({ id })
        : machine
          ? api.firewall.listByMachine({ id: machine })
          : api.firewall.list(),
    // eslint-disable-next-line camelcase
    firewall_rule: (root, { id }) => api.firewall.get({ id }),
    vlans: (root, { id }) => (id ? api.vlans.get({ id }) : api.vlans.list()),
    vlan: (root, { id }) => api.vlans.get({ id }),
    networks: (root, { id, vlan }) =>
      id ? api.networks.get({ id, vlan }) : api.networks.list({ vlan }),
    network: (root, { id, vlan }) => api.networks.get({ id, vlan }),
    nics: (root, { machine, mac }) =>
      mac ? api.nics.get({ machine, mac }) : api.nics.list({ machine }),
    nic: (root, { machine, mac }) => api.nics.get({ machine, mac })
  },
  User: {
    keys: ({ login }, { name }) => resolvers.Query.keys(null, { login, name })
  },
  Machine: {
    brand: ({ brand }) => (brand ? brand.toUpperCase() : brand),
    state: ({ state }) => (state ? state.toUpperCase() : state),
    image: ({ image }) => resolvers.Query.image(null, { id: image }),
    tags: ({ id }, { name }) =>
      resolvers.Query.tags(null, { machine: id, name }),
    metadata: ({ id }, { name }) =>
      resolvers.Query.metadata(null, { machine: id, name }),
    networks: ({ networks }) =>
      Promise.all(networks.map(id => resolvers.Query.network(null, { id }))),
    // eslint-disable-next-line camelcase
    package: (root) => resolvers.Query.package(null, { name: root.package }),
    snapshots: ({ id }, { name }) =>
      resolvers.Query.snapshots(null, { machine: id, name }),
    // eslint-disable-next-line camelcase
    firewall_rules: ({ id: machine }, { id }) =>
      resolvers.Query.firewall_rules(null, { machine, id }),
    actions: ({ id }) => resolvers.Query.actions(null, { machine: id })
  },
  Image: {
    os: ({ os }) => (os ? os.toUpperCase() : os),
    state: ({ state }) => (state ? state.toUpperCase() : state),
    type: ({ type }) => (type ? type.toUpperCase() : type)
  },
  Action: {
    name: ({ action }) => action,
    parameters: ({ parameters }) => toKeyValue(parameters)
  },
  Caller: {
    type: ({ type }) => (type ? type.toUpperCase() : type),
    // eslint-disable-next-line camelcase
    key_id: ({ keyId }) => keyId
  }
};

module.exports = resolvers;
<commit_msg>feat(cloudapi-gql): primary_ip Machine resolver<commit_after>const { toKeyValue, fromKeyValue } = require('../api/key-value');
const api = require('../api');

const resolvers = {
  Query: {
    account: () => api.account.get(),
    keys: (root, { login, name }) =>
      name
        ? api.keys.get({ login, name }).then(key => [key])
        : api.keys.list({ login, name }),
    key: (root, { login, name }) => api.keys.get({ login, name }),
    users: (root, { id }) =>
      id ? api.users.get({ id }).then(user => [user]) : api.users.list(),
    user: (root, { id }) => api.users.get({ id }),
    roles: (root, { id, name }) =>
      id || name
        ? api.roles.get({ id, name }).then(role => [role])
        : api.roles.list(),
    role: (root, { id, name }) => api.roles.get({ id, name }),
    policies: (root, { id }) =>
      id
        ? api.policies.get({ id }).then(policy => [policy])
        : api.policies.list(),
    policy: (root, { id }) => api.policies.get({ id }),
    config: () => api.config().then(toKeyValue),
    datacenters: () =>
      api.datacenters().then(dcs =>
        Object.keys(dcs).map(name => ({
          name,
          url: dcs[name]
        }))
      ),
    services: () => api.services().then(toKeyValue),
    images: (root, { id, ...rest }) =>
      id
        ? api.images.get({ id }).then(image => [image])
        : api.images.list(rest),
    image: (root, { id }) => api.images.get({ id }),
    packages: (root, { id, ...rest }) =>
      id
        ? api.packages.get({ id }).then(pkg => [pkg])
        : api.packages.list(rest),
    package: (root, { id, name }) => api.packages.get({ id, name }),
    machines: (root, { id, brand, state, tags, ...rest }) =>
      id
        ? api.machines.get({ id }).then(machine => [machine])
        : api.machines.list(
            Object.assign(rest, {
              brand: brand ? brand.toLowerCase() : brand,
              state: state ? state.toLowerCase() : state,
              tags: fromKeyValue(tags)
            })
          ),
    machine: (root, { id }) => api.machines.get({ id }),
    snapshots: (root, { name, machine }) =>
      name
        ? api.machines.snapshots
            .get({ id: machine, name })
            .then(snapshot => [snapshot])
        : api.machines.snapshots.list({ id: machine }),
    snapshot: (root, { name, machine }) =>
      api.machines.snapshots.get({ name, id: machine }),
    metadata: (root, { machine, name, ...rest }) =>
      name
        ? api.machines.metadata
            .get(Object.assign(rest, { id: machine, key: name }))
            .then(value => toKeyValue({ [name]: value }))
        : api.machines.metadata.list({ id: machine }).then(toKeyValue),
    metadataValue: (root, { name, machine }) =>
      api.machines.metadata
        .get({ key: name, id: machine })
        .then(value => toKeyValue({ [name]: value }).shift()),
    tags: (root, { machine, name }) =>
      name
        ? api.machines.tags
            .get({ id: machine, tag: name })
            .then(value => toKeyValue({ [name]: value }))
        : api.machines.tags.list({ id: machine }).then(toKeyValue),
    tag: (root, { machine, name }) =>
      api.machines.tags
        .get({ id: machine, tag: name })
        .then(value => toKeyValue({ [name]: value }).shift()),
    actions: (root, { machine }) => api.machines.audit({ id: machine }),
    // eslint-disable-next-line camelcase
    firewall_rules: (root, { machine, id }) =>
      id
        ? api.firewall.get({ id })
        : machine
          ? api.firewall.listByMachine({ id: machine })
          : api.firewall.list(),
    // eslint-disable-next-line camelcase
    firewall_rule: (root, { id }) => api.firewall.get({ id }),
    vlans: (root, { id }) => (id ? api.vlans.get({ id }) : api.vlans.list()),
    vlan: (root, { id }) => api.vlans.get({ id }),
    networks: (root, { id, vlan }) =>
      id ? api.networks.get({ id, vlan }) : api.networks.list({ vlan }),
    network: (root, { id, vlan }) => api.networks.get({ id, vlan }),
    nics: (root, { machine, mac }) =>
      mac ? api.nics.get({ machine, mac }) : api.nics.list({ machine }),
    nic: (root, { machine, mac }) => api.nics.get({ machine, mac })
  },
  User: {
    keys: ({ login }, { name }) => resolvers.Query.keys(null, { login, name })
  },
  Machine: {
    brand: ({ brand }) => (brand ? brand.toUpperCase() : brand),
    state: ({ state }) => (state ? state.toUpperCase() : state),
    image: ({ image }) => resolvers.Query.image(null, { id: image }),
    // eslint-disable-next-line camelcase
    primary_ip: ({ primaryIp }) => primaryIp,
    tags: ({ id }, { name }) =>
      resolvers.Query.tags(null, { machine: id, name }),
    metadata: ({ id }, { name }) =>
      resolvers.Query.metadata(null, { machine: id, name }),
    networks: ({ networks }) =>
      Promise.all(networks.map(id => resolvers.Query.network(null, { id }))),
    // eslint-disable-next-line camelcase
    package: (root) => resolvers.Query.package(null, { name: root.package }),
    snapshots: ({ id }, { name }) =>
      resolvers.Query.snapshots(null, { machine: id, name }),
    // eslint-disable-next-line camelcase
    firewall_rules: ({ id: machine }, { id }) =>
      resolvers.Query.firewall_rules(null, { machine, id }),
    actions: ({ id }) => resolvers.Query.actions(null, { machine: id })
  },
  Image: {
    os: ({ os }) => (os ? os.toUpperCase() : os),
    state: ({ state }) => (state ? state.toUpperCase() : state),
    type: ({ type }) => (type ? type.toUpperCase() : type)
  },
  Action: {
    name: ({ action }) => action,
    parameters: ({ parameters }) => toKeyValue(parameters)
  },
  Caller: {
    type: ({ type }) => (type ? type.toUpperCase() : type),
    // eslint-disable-next-line camelcase
    key_id: ({ keyId }) => keyId
  }
};

module.exports = resolvers;
<|endoftext|>


<commit_before>/*
  Q Light Controller Plus
  FixtureDrag.js

  Copyright (c) Massimo Callegari

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

var itemComponent = null;
var draggedItem = null;
var startingMouse;
var posnInWindow;
var manufacturer, model, mode, name;
var universeIndex, address, channels, quantity, gap;

function initProperties()
{
    manufacturer = fixtureBrowser.selectedManufacturer;
    model = fixtureBrowser.selectedModel;
    mode = fixtureBrowser.selectedMode;
    name = fixtureBrowser.fixtureName;
    universeIndex = fxPropsRect.fxUniverseIndex;
    address = fxPropsRect.fxAddress - 1;
    channels = fixtureBrowser.modeChannelsCount;
    quantity = fxPropsRect.fxQuantity;
    gap = fxPropsRect.fxGap;
    console.log("mf: " + manufacturer + ", mdl: " + model + ", mode: " + mode);
    console.log("addr: " + address + ", ch: " + channels);
}

// Creation is split into two functions due to an asynchronous wait while
// possible external files are loaded.

function createItem()
{
    if (itemComponent.status === Component.Ready && draggedItem == null)
    {
        draggedItem = itemComponent.createObject(mainView,
                  {"x": posnInWindow.x, "y": posnInWindow.y, "z": 10,
                   "manufacturer": manufacturer, "model": model,
                   "address": address, "universe": universeIndex,
                   "channels": channels, "quantity": quantity, "gap": gap });
    }
    else if (itemComponent.status === Component.Error)
    {
        draggedItem = null;
        console.log("error creating component");
        console.log(itemComponent.errorString());
    }
}

function loadComponent()
{
    if (itemComponent != null) // component has been previously loaded
    {
        createItem();
        return;
    }

    itemComponent = Qt.createComponent("FixtureDragItem.qml");
    createItem();
}

function handleDrag(mouse)
{
    if (draggedItem == null)
    {
        posnInWindow = fxDraggableItem.mapToItem(mainView, 0, 0);
        loadComponent();
    }

    draggedItem.x = mouse.x + posnInWindow.x - 5;
    draggedItem.y = mouse.y + posnInWindow.y - 5;
}

function endDrag(mouse)
{
    if (draggedItem == null)
    {
        return;
    }

    var currContext = previewLoader.item.contextName;
    console.log("Current context: " + currContext);
    var x = draggedItem.x - leftSidePanel.width;
    var y = draggedItem.y - previewLoader.y - viewToolbar.height;

    console.log("Item x: " + x + ", y: " + y);

    if (x >= 0 && y >= 0)
    {
        fixtureManager.addFixture(manufacturer, model, mode, name, universeIndex,
                                  draggedItem.address, channels, quantity, gap, x, y);
    }

    draggedItem.destroy();
    draggedItem = null;
}

<commit_msg>qmlui: fix offset when dragging a new fixture in 2D view<commit_after>/*
  Q Light Controller Plus
  FixtureDrag.js

  Copyright (c) Massimo Callegari

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

var itemComponent = null;
var draggedItem = null;
var startingMouse;
var posnInWindow;
var manufacturer, model, mode, name;
var universeIndex, address, channels, quantity, gap;

function initProperties()
{
    manufacturer = fixtureBrowser.selectedManufacturer;
    model = fixtureBrowser.selectedModel;
    mode = fixtureBrowser.selectedMode;
    name = fixtureBrowser.fixtureName;
    universeIndex = fxPropsRect.fxUniverseIndex;
    address = fxPropsRect.fxAddress - 1;
    channels = fixtureBrowser.modeChannelsCount;
    quantity = fxPropsRect.fxQuantity;
    gap = fxPropsRect.fxGap;
    console.log("mf: " + manufacturer + ", mdl: " + model + ", mode: " + mode);
    console.log("addr: " + address + ", ch: " + channels);
}

// Creation is split into two functions due to an asynchronous wait while
// possible external files are loaded.

function createItem()
{
    if (itemComponent.status === Component.Ready && draggedItem == null)
    {
        draggedItem = itemComponent.createObject(mainView,
                  {"x": posnInWindow.x, "y": posnInWindow.y, "z": 10,
                   "manufacturer": manufacturer, "model": model,
                   "address": address, "universe": universeIndex,
                   "channels": channels, "quantity": quantity, "gap": gap });
    }
    else if (itemComponent.status === Component.Error)
    {
        draggedItem = null;
        console.log("error creating component");
        console.log(itemComponent.errorString());
    }
}

function loadComponent()
{
    if (itemComponent != null) // component has been previously loaded
    {
        createItem();
        return;
    }

    itemComponent = Qt.createComponent("FixtureDragItem.qml");
    createItem();
}

function handleDrag(mouse)
{
    if (draggedItem == null)
    {
        posnInWindow = fxDraggableItem.mapToItem(mainView, 0, 0);
        loadComponent();
    }

    draggedItem.x = mouse.x + posnInWindow.x - 5;
    draggedItem.y = mouse.y + posnInWindow.y - 5;
}

function endDrag(mouse)
{
    if (draggedItem == null)
    {
        return;
    }

    var currContext = previewLoader.item.contextName;
    var offset = 0;
    console.log("Current context: " + currContext);
    if (currContext === "2D")
        offset = View2D.gridPosition.x;
    var x = draggedItem.x - leftSidePanel.width - offset;
    var y = draggedItem.y - previewLoader.y - viewToolbar.height;

    console.log("Item x: " + x + ", y: " + y);

    if (x >= 0 && y >= 0)
    {
        fixtureManager.addFixture(manufacturer, model, mode, name, universeIndex,
                                  draggedItem.address, channels, quantity, gap, x, y);
    }

    draggedItem.destroy();
    draggedItem = null;
}

<|endoftext|>