<commit_before>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

'use strict';

const mix = require('laravel-mix');
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const concatenate = require('concatenate');

const Autoprefixer = require('autoprefixer');
const CopyPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const SentryPlugin = require('webpack-sentry-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

const inProduction = process.env.NODE_ENV === 'production' || process.argv.includes('-p');

let min = '';
let reactMin = 'development';
if (inProduction) {
  min = '.min';
  reactMin = 'production.min';
}

const paymentSandbox = !(process.env.PAYMENT_SANDBOX === '0'
                         || process.env.PAYMENT_SANDBOX === 'false'
                         || !process.env.PAYMENT_SANDBOX);

// relative from root?
const nodeRoot = path.resolve(__dirname, 'node_modules');

const vendor = [
  'clipboard-polyfill/build/clipboard-polyfill.js',
  `url-polyfill/url-polyfill${min}.js`,
  'turbolinks/dist/turbolinks.js',
  `jquery/dist/jquery${min}.js`,
  'jquery-ujs/src/rails.js',
  `qtip2/dist/jquery.qtip${min}.js`,
  'jquery.scrollto/jquery.scrollTo.js',
  'jquery-ui/ui/data.js',
  'jquery-ui/ui/scroll-parent.js',
  'jquery-ui/ui/widget.js',
  'jquery-ui/ui/widgets/mouse.js',
  'jquery-ui/ui/widgets/slider.js',
  'jquery-ui/ui/widgets/sortable.js',
  'jquery-ui/ui/keycode.js',
  'timeago/jquery.timeago.js',
  'blueimp-file-upload/js/jquery.fileupload.js',
  'bootstrap/dist/js/bootstrap.js',
  'lodash/lodash.js',
  'layzr.js/dist/layzr.js',
  `react/umd/react.${reactMin}.js`,
  'react-dom-factories/index.js',
  `react-dom/umd/react-dom.${reactMin}.js`,
  `prop-types/prop-types${min}.js`,
  'photoswipe/dist/photoswipe.js',
  'photoswipe/dist/photoswipe-ui-default.js',
  `d3/dist/d3${min}.js`,
  'moment/moment.js',
  'js-cookie/src/js.cookie.js',
  `imagesloaded/imagesloaded.pkgd${min}.js`,
].map((name) => path.join(nodeRoot, name));

vendor.forEach(function(script) {
  if (!fs.existsSync(script)) {
    throw new Error(`${script} doesn't exist`);
  }
});

if (!fs.readdirSync('resources/assets/build/locales').some((file) => file.endsWith('.js'))) {
  throw new Error('missing locale files.');
}

const filesToConcat = {
  // FIXME: less dumb name; this needs to be separated -
  // compiling coffee and then concating together doesn't
  // work so well when versioning is used with webpack.
  'app-deps': [
    'resources/assets/js/ga.js',
    'resources/assets/build/lang.js',
    'resources/assets/js/bootstrap-lang.js',
  ],
  vendor: vendor,
};

// TODO: move to plugin for webpack
fs.mkdirSync('public/js', {recursive: true});
for (const key in filesToConcat) {
  const out = path.resolve(__dirname, `public/js/${key}.js`);
  console.log(`Writing concatenate output to: ${out}`);
  concatenate.sync(filesToConcat[key], out);
}

const entry = {
  '/js/app': [
    './resources/assets/app.js',
    './resources/assets/less/app.less',
  ],
};

const coffeeReactComponents = [
  'artist-page',
  'beatmap-discussions',
  'beatmap-discussions-history',
  'beatmapset-page',
  'changelog-build',
  'changelog-index',
  'comments-index',
  'comments-show',
  'mp-history',
  'modding-profile',
  'profile-page',
  'admin/contest',
  'contest-entry',
  'contest-voting',
];

const tsReactComponents = [
  'account-edit',
  'beatmaps',
  'chat',
  'friends-index',
  'groups-show',
  'news-index',
  'news-show',
  'notifications-index',
  'scores-show',
  'store-bootstrap',
];

for (const name of coffeeReactComponents) {
  entry[`js/react/${name}`] = [path.resolve(__dirname, `resources/assets/coffee/react/${name}.coffee`)];
}

for (const name of tsReactComponents) {
  entry[`js/react/${name}`] = [path.resolve(__dirname, `resources/assets/lib/${name}.ts`)];
}

const webpackConfig = {
  devtool: 'source-map',
  entry: entry,
  externals: {
    'd3': 'd3',
    'lodash': '_',
    'moment': 'moment',
    'prop-types': 'PropTypes',
    'react': 'React',
    'react-dom': 'ReactDOM',
    'react-dom-factories': 'ReactDOMFactories',
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        exclude: /(node_modules)/,
        loader: 'import-glob-loader',
        test: /\.(js|coffee)$/,
      },
      {
        test: /\\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  'node_modules/@babel/preset-env/lib/index.js',
                  {
                    modules: false,
                    forceAllTransforms: true
                  }
                ]
              ],
              plugins: [
                'node_modules/@babel/plugin-syntax-dynamic-import/lib/index.js',
                'node_modules/@babel/plugin-proposal-object-rest-spread/lib/index.js',
                [
                  'node_modules/@babel/plugin-transform-runtime/lib/index.js',
                  {
                    helpers: false
                  }
                ]
              ],
              cacheDirectory: true
            }
          }
        ]<commit_msg>set mode, correct plugin syntax<commit_after>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

'use strict';

const mix = require('laravel-mix');
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const concatenate = require('concatenate');

const Autoprefixer = require('autoprefixer');
const CopyPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const SentryPlugin = require('webpack-sentry-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

const inProduction = process.env.NODE_ENV === 'production' || process.argv.includes('-p');

let min = '';
let reactMin = 'development';
if (inProduction) {
  min = '.min';
  reactMin = 'production.min';
}

const paymentSandbox = !(process.env.PAYMENT_SANDBOX === '0'
                         || process.env.PAYMENT_SANDBOX === 'false'
                         || !process.env.PAYMENT_SANDBOX);

// relative from root?
const nodeRoot = path.resolve(__dirname, 'node_modules');

const vendor = [
  'clipboard-polyfill/build/clipboard-polyfill.js',
  `url-polyfill/url-polyfill${min}.js`,
  'turbolinks/dist/turbolinks.js',
  `jquery/dist/jquery${min}.js`,
  'jquery-ujs/src/rails.js',
  `qtip2/dist/jquery.qtip${min}.js`,
  'jquery.scrollto/jquery.scrollTo.js',
  'jquery-ui/ui/data.js',
  'jquery-ui/ui/scroll-parent.js',
  'jquery-ui/ui/widget.js',
  'jquery-ui/ui/widgets/mouse.js',
  'jquery-ui/ui/widgets/slider.js',
  'jquery-ui/ui/widgets/sortable.js',
  'jquery-ui/ui/keycode.js',
  'timeago/jquery.timeago.js',
  'blueimp-file-upload/js/jquery.fileupload.js',
  'bootstrap/dist/js/bootstrap.js',
  'lodash/lodash.js',
  'layzr.js/dist/layzr.js',
  `react/umd/react.${reactMin}.js`,
  'react-dom-factories/index.js',
  `react-dom/umd/react-dom.${reactMin}.js`,
  `prop-types/prop-types${min}.js`,
  'photoswipe/dist/photoswipe.js',
  'photoswipe/dist/photoswipe-ui-default.js',
  `d3/dist/d3${min}.js`,
  'moment/moment.js',
  'js-cookie/src/js.cookie.js',
  `imagesloaded/imagesloaded.pkgd${min}.js`,
].map((name) => path.join(nodeRoot, name));

vendor.forEach(function(script) {
  if (!fs.existsSync(script)) {
    throw new Error(`${script} doesn't exist`);
  }
});

if (!fs.readdirSync('resources/assets/build/locales').some((file) => file.endsWith('.js'))) {
  throw new Error('missing locale files.');
}

const filesToConcat = {
  // FIXME: less dumb name; this needs to be separated -
  // compiling coffee and then concating together doesn't
  // work so well when versioning is used with webpack.
  'app-deps': [
    'resources/assets/js/ga.js',
    'resources/assets/build/lang.js',
    'resources/assets/js/bootstrap-lang.js',
  ],
  vendor: vendor,
};

// TODO: move to plugin for webpack
fs.mkdirSync('public/js', {recursive: true});
for (const key in filesToConcat) {
  const out = path.resolve(__dirname, `public/js/${key}.js`);
  console.log(`Writing concatenate output to: ${out}`);
  concatenate.sync(filesToConcat[key], out);
}

const entry = {
  '/js/app': [
    './resources/assets/app.js',
    './resources/assets/less/app.less',
  ],
};

const coffeeReactComponents = [
  'artist-page',
  'beatmap-discussions',
  'beatmap-discussions-history',
  'beatmapset-page',
  'changelog-build',
  'changelog-index',
  'comments-index',
  'comments-show',
  'mp-history',
  'modding-profile',
  'profile-page',
  'admin/contest',
  'contest-entry',
  'contest-voting',
];

const tsReactComponents = [
  'account-edit',
  'beatmaps',
  'chat',
  'friends-index',
  'groups-show',
  'news-index',
  'news-show',
  'notifications-index',
  'scores-show',
  'store-bootstrap',
];

for (const name of coffeeReactComponents) {
  entry[`js/react/${name}`] = [path.resolve(__dirname, `resources/assets/coffee/react/${name}.coffee`)];
}

for (const name of tsReactComponents) {
  entry[`js/react/${name}`] = [path.resolve(__dirname, `resources/assets/lib/${name}.ts`)];
}

const webpackConfig = {
  mode: inProduction ? 'production' : 'development',
  devtool: 'source-map',
  entry: entry,
  output: {
    path: path.resolve(__dirname, 'public'),
  },
  externals: {
    'd3': 'd3',
    'lodash': '_',
    'moment': 'moment',
    'prop-types': 'PropTypes',
    'react': 'React',
    'react-dom': 'ReactDOM',
    'react-dom-factories': 'ReactDOMFactories',
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        exclude: /(node_modules)/,
        loader: 'import-glob-loader',
        test: /\.(js|coffee)$/,
      },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    modules: false,
                    forceAllTransforms: true
                  }
                ]
              ],
              plugins: [
                '@babel/plugin-syntax-dynamic-import',
                '@babel/plugin-proposal-object-rest-spread',
                [
                  '@babel/plugin-transform-runtime',
                  {
                    helpers: false
                  }
                ]
              ],
              cacheDirectory: true
            }
          }
        ]
{'fraction_non_alphanumeric': 0.1743655285740369, 'fraction_numerical': 0.001460653642505021, 'mean_word_length': 2.7736823975198073, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6764243', 'n_tokens_mistral': 3791, 'n_tokens_neox': 3710, 'n_words': 616}