<commit_before>/* jshint unused:false */
/* global seqJS:true */
/*
 * Extensions to QUnit for testing seqJS objects
 */

var location_eq = function(actual, location1, operator, location2) {
    operator = operator || '';
    equal(actual.location(), location1, "First location is wrong");
    equal(typeof actual.location(), 'number',
          "location() should return a number");
    equal(actual.operator(), operator, "Operator is wrong");

    if(operator !== '.'){
        equal(actual.location2(), undefined,
              "location2() should be undefined for operator \'"+
                  operator+"\'");
    }
    else {
        equal(actual.location2(), location2, "Location2 is wrong");
        equal(typeof actual.location2(), 'number',
              "location2() should return a number");
    }
};

var span_eq = function(actual, location1, location2, complement, string){

    location_eq(actual.location1(), location1[0], location1[1], location1[2]);
    location_eq(actual.location2(), location2[0], location2[1], location2[2]);

    equal(actual.isComplement(), complement, "Complement flag wrong");
    equal(actual.toString(), string, "toString() is incorrect");
};

var featureloc_eq = function(actual, string, merge, spanlist){

    equal(actual.toString(), string, "toString() is wrong");

    equal(actual.getMergeOperator(), merge, "getMergeOperator() is wrong");

    var s = actual.getSpans(), j;
    equal(s.length, spanlist.length, "Wrong number of spans returned");
    for(var i = 0; i < spanlist.length; i++){
        j = spanlist[i];
        span_eq(s[i], j[0], j[1], j[2], j[3]);
    }
};

var feature_eq = function(actual, type, location_string, qualifiers, feat_name){

    var m = function(msg){
        if(feat_name){
            return feat_name + ': ' + msg;
        }
        return msg;
    };

    ok(actual instanceof seqJS.Feature, m("Didn't get a seqJS.Feature"));

    equal(actual.type(), type, m("feature type is wrong"));
    equal(actual.location().toString(), location_string,
          m('location is wrong'));
    ok(actual.location() instanceof seqJS.FeatureLocation,
       m('feature.location() should be from FeatureLocation, not \"' +
      actual.location().constructor.name + '"'));

    qualifiers = qualifiers || [];
    equal(actual.qualifierKeys().length, qualifiers.length,
         m('qualifier length is wrong'));
    for(var i =0; i< qualifiers.length; i++){
        equal(actual.qualifier(qualifiers[i][0]), qualifiers[i][1],
              m("qualifier " + i + " incorrect"));
    }
};

var gbrecord_eq = function(actual, expected){
    var an_keys = [
        'residue_type',
        'topology',
        'data_division',
        'date',
        'accession',
        'version',
        'gi',
        'source',
        'organism'];

    equal(actual.name, expected['name'], "Name is wrong");
    equal(actual.desc, expected['description'], "Description is wrong");
    equal(actual.length(), expected['length']);

    for(var i = 0; i < an_keys.length; i++){
        equal(actual.annotations[an_keys[i]], expected[an_keys[i]], an_keys[i] + " is wrong");
    }

    deepEqual(actual.annotations.taxonomy, expected.taxonomy,
          'taxonomy is wrong');

    for(i = 0; i < expected.references.length; i++){
        var eref = expected.references[i],
            aref = actual.annotations.references[i];
        deepEqual(aref, eref, "Reference "+i+" is wrong");
    }

    var f = actual.seq.features();
    equal(f.length, expected.features.length, 'Wrong number of features');
    for(i = 0; i < expected.features.length; i++)
    {
        var e = expected.features[i];
        feature_eq(f[i], e[0], e[1], e[2], 'Feature '+i);
    }

    equal(actual.seq.alphabet(), expected.alphabet, 'alphabet is wrong');
    equal(actual.seq.seq(), expected.seq, 'seq is wrong');

};

<commit_msg>Leave myself a todo list<commit_after>/* jshint unused:false */
/* global seqJS:true */
/*
 * Extensions to QUnit for testing seqJS objects
 */

var location_eq = function(actual, location1, operator, location2) {
    operator = operator || '';
    equal(actual.location(), location1, "First location is wrong");
    equal(typeof actual.location(), 'number',
          "location() should return a number");
    equal(actual.operator(), operator, "Operator is wrong");

    if(operator !== '.'){
        equal(actual.location2(), undefined,
              "location2() should be undefined for operator \'"+
                  operator+"\'");
    }
    else {
        equal(actual.location2(), location2, "Location2 is wrong");
        equal(typeof actual.location2(), 'number',
              "location2() should return a number");
    }
};

var span_eq = function(actual, location1, location2, complement, string){

    location_eq(actual.location1(), location1[0], location1[1], location1[2]);
    location_eq(actual.location2(), location2[0], location2[1], location2[2]);

    equal(actual.isComplement(), complement, "Complement flag wrong");
    equal(actual.toString(), string, "toString() is incorrect");
};

var featureloc_eq = function(actual, string, merge, spanlist){

    equal(actual.toString(), string, "toString() is wrong");

    equal(actual.getMergeOperator(), merge, "getMergeOperator() is wrong");

    var s = actual.getSpans(), j;
    equal(s.length, spanlist.length, "Wrong number of spans returned");
    for(var i = 0; i < spanlist.length; i++){
        j = spanlist[i];
        span_eq(s[i], j[0], j[1], j[2], j[3]);
    }
};

var feature_eq = function(actual, type, location_string, qualifiers, feat_name){

    var m = function(msg){
        if(feat_name){
            return feat_name + ': ' + msg;
        }
        return msg;
    };

    ok(actual instanceof seqJS.Feature, m("Didn't get a seqJS.Feature"));

    equal(actual.type(), type, m("feature type is wrong"));
    equal(actual.location().toString(), location_string,
          m('location is wrong'));
    ok(actual.location() instanceof seqJS.FeatureLocation,
       m('feature.location() should be from FeatureLocation, not \"' +
      actual.location().constructor.name + '"'));

    qualifiers = qualifiers || [];
    equal(actual.qualifierKeys().length, qualifiers.length,
         m('qualifier length is wrong'));
    for(var i =0; i< qualifiers.length; i++){
        equal(actual.qualifier(qualifiers[i][0]), qualifiers[i][1],
              m("qualifier " + i + " incorrect"));
    }
};

var gbrecord_eq = function(actual, expected){

/* TODO:
 *
 *  Improve annotation parsing and testing.
 *
 *  There should be a fixed set of annotations which every SeqRecord is
 *  guaranteed to have, with fixed default values.
 *  Therse annotations are always written out first to file, but can appear in
 *  any order.
 *
 *  Test data should include:
 *      string: input file which should parse correctly
 *      object: {
 *          - this level contains things parsed from the LOCUS line (name,
 *          length, seq etc
 *
 *          annotations: [
 *              ['key', 'value']
 *              ],
 *
 *          references: [
 *              { as before}
 *          ]
 *      },
 *      output: string which should be the result of read/write
 *
 *
 *
 *
 */

    var an_keys = [
        'residue_type',
        'topology',
        'data_division',
        'date',
        'accession',
        'version',
        'gi',
        'source',
        'organism'];

    equal(actual.name, expected['name'], "Name is wrong");
    equal(actual.desc, expected['description'], "Description is wrong");
    equal(actual.length(), expected['length']);

    for(var i = 0; i < an_keys.length; i++){
        equal(actual.annotations[an_keys[i]], expected[an_keys[i]], an_keys[i] + " is wrong");
    }

    deepEqual(actual.annotations.taxonomy, expected.taxonomy,
          'taxonomy is wrong');

    for(i = 0; i < expected.references.length; i++){
        var eref = expected.references[i],
            aref = actual.annotations.references[i];
        deepEqual(aref, eref, "Reference "+i+" is wrong");
    }

    var f = actual.seq.features();
    equal(f.length, expected.features.length, 'Wrong number of features');
    for(i = 0; i < expected.features.length; i++)
    {
        var e = expected.features[i];
        feature_eq(f[i], e[0], e[1], e[2], 'Feature '+i);
    }

    equal(actual.seq.alphabet(), expected.alphabet, 'alphabet is wrong');
    equal(actual.seq.seq(), expected.seq, 'seq is wrong');

};

<|endoftext|>


<commit_before>const path = require("path");
const fs = require("fs");

require("dotenv").config({
  path: path.join(__dirname, ".env"),
});

const BundleAnalyzerPlugin =
  require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { InjectManifest } = require("workbox-webpack-plugin");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const WebpackBar = require("webpackbar");

const DISTPATH = path.resolve(__dirname, "assets/components");

const isDirectory = (f) => fs.statSync(f).isDirectory();
const directoryHasFile = (f) => (d) => fs.readdirSync(d).includes(f);

const CONFIG_TYPES = {
  ES2015: "es2015+",
  ES5: "es5",
  DEV: "dev",
};

// establish the list of Django applications with a `components` folder
const applications = fs
  .readdirSync(path.resolve(__dirname, "agir"))
  .map((f) => path.resolve(__dirname, "agir", f))
  .filter(isDirectory)
  .filter(directoryHasFile("components"));

// javascript components are either:
// - directories with an index.js
// - .js files
// that are directly found in a `components` folder of one of the django apps.
//
// The bundle name will be `<django app name>/<name of directory / .js file>`
const components = applications
  .flatMap((dir) =>
    fs
      .readdirSync(path.resolve(dir, "components"))
      .map((f) => [path.basename(dir), path.resolve(dir, "components", f)])
  )
  .filter(([_app, f]) =>
    isDirectory(f) ? directoryHasFile("index.js")(f) : f.endsWith(".js")
  )
  .map(([app, f]) => [app + "/" + path.basename(f, ".js"), f])
  .reduce((obj, [name, file]) => {
    obj[name] = file;
    return obj;
  }, {});

// create import aliases with the django app names leading to their `components` folders
const aliases = applications.reduce(
  (obj, app) => {
    obj["@agir/" + path.basename(app)] = path.resolve(app, "components/");
    return obj;
  },
  {
    luxon: "luxon/src/luxon",
  }
);

// Generate an HTML fragment with all chunks tag for each entry
const htmlPlugins = (type) =>
  Object.keys(components).map(
    (entry) =>
      new HtmlWebpackPlugin({
        filename: `includes/${entry}.${
          type === CONFIG_TYPES.ES2015 ? "modules" : "bundle"
        }.html`,
        scriptLoading: "defer",
        inject: false,
        chunks: [entry],
        templateContent: ({ htmlWebpackPlugin }) => {
          switch (type) {
            case CONFIG_TYPES.DEV:
              return (
                htmlWebpackPlugin.tags.headTags +
                htmlWebpackPlugin.tags.bodyTags
              );
            case CONFIG_TYPES.ES2015:
              return htmlWebpackPlugin.files.js
                .map((file) => `<script type="module" src="${file}"></script>`)
                .join("");
            case CONFIG_TYPES.ES5:
              return (
                htmlWebpackPlugin.files.js
                  .map((file) => `<script nomodule src="${file}"></script>`)
                  .join("") + `{% include "${entry}.modules.html" %}`
              );
          }
        },
      })
  );

// List all chunks on which main app depends for preloading by service worker
let _cachedAppEntryFiles;
const getAppEntryFiles = (compilation) => {
  if (_cachedAppEntryFiles) {
    return _cachedAppEntryFiles;
  }

  _cachedAppEntryFiles = compilation.namedChunkGroups
    .get("front/app")
    .chunks.map((c) => Array.from(c.files))
    .flat();

  return _cachedAppEntryFiles;
};

// List all chunks on which other apps depends for preload exclusion if not in main app
let _cachedOtherEntryFiles;
const getOtherEntryFiles = (compilation) => {
  if (_cachedOtherEntryFiles) {
    return _cachedOtherEntryFiles;
  }

  _cachedOtherEntryFiles = [
    "donations/donationForm",
    "donations/spendingRequestLib",
    "elus/parrainages",
    "front/legacyPages",
    "front/richEditor",
    "groups/groupSelector",
    "lib/adminJsonWidget",
    "lib/communeField",
    "lib/creationForms",
    "lib/IBANField",
    "lib/locationSearchField",
    "theme",
  ]
    .map((name) =>
      compilation.namedChunkGroups
        .get(name)
        .chunks.map((c) => Array.from(c.files))
        .flat()
    )
    .flat();

  return _cachedOtherEntryFiles;
};

const es5Browsers = [
  "> 0.5% in FR",
  "last 2 versions",
  "Firefox ESR",
  "not dead",
  "not IE 11",
];

const es2015Browsers = { esmodules: true };

const configureBabelLoader = (type) => ({
  test: /\.m?js$/,
  include: [
    path.resolve(__dirname, "agir"),
    type === CONFIG_TYPES.ES2015
      ? undefined
      : path.resolve(__dirname, "node_modules/react-spring"),
  ].filter(Boolean),
  exclude:
    type === CONFIG_TYPES.ES2015
      ? []
      : [new RegExp("node_modules\\" + path.sep)],
  use: {
    loader: "babel-loader",
    options: {
      cacheDirectory: process.env.BABEL_CACHE_DIRECTORY || true,
      exclude: [/core-js/, /regenerator-runtime/, /webpack[\\/]buildin/],
      presets: [
        "@babel/preset-react",
        [
          "@babel/preset-env",
          {
            modules: false,
            corejs: "3.20",
            useBuiltIns: "usage",
            targets: type === CONFIG_TYPES.ES5 ? es5Browsers : es2015Browsers,
          },
        ],
      ],
      plugins: [
        "@babel/plugin-syntax-dynamic-import",
        [
          "babel-plugin-styled-components",
          {
            // This option enhances the attached CSS class name on each component with richer output to help identify your components in the DOM.
            displayName: type === CONFIG_TYPES.DEV,
            // Remove comments and whitespace from the CSS.
            minify: type !== CONFIG_TYPES.DEV,
            // Transpile tagged template literals into optimized code.
            transpileTemplateLiterals: type !== CONFIG_TYPES.DEV,
            // By default minifiers cannot properly perform dead code elimination on styled components because they are assumed to have side effects. This enables "pure annotations" to tell the compiler that they do not have side effects.
            pure: type !== CONFIG_TYPES.DEV,
            // Enable SSR optimization
            ssr: false,
          },
        ],
        ["@babel/plugin-transform-runtime", { useESModules: true }],
        type === CONFIG_TYPES.DEV
          ? require.resolve("react-refresh/babel")
          : undefined,
        type !== CONFIG_TYPES.DEV
          ? [
              "transform-react-remove-prop-types",
              {
                removeImport: true,
              },
            ]
          : undefined,
      ].filter(Boolean),
    },
  },
});

module.exports = (type = CONFIG_TYPES.ES5) => ({
  context: path.resolve(__dirname, "agir/"),
  entry: Object.assign(
    {
      theme: path.resolve(__dirname, "agir/front/components/theme/theme.scss"),
    },
    components
  ),
  plugins: [
    type !== CONFIG_TYPES.DEV && new WebpackBar(),
    ...htmlPlugins(type),
    new HtmlWebpackPlugin({
      filename: `includes/theme.bundle.html`,
      inject: false,
      chunks: ["theme"],
      templateContent: ({ htmlWebpackPlugin }) =>
        `<link href="${htmlWebpackPlugin.files.css[0]}" rel="stylesheet">`,
    }),
    new MiniCssExtractPlugin({ filename: "[name]-[chunkhash].css" }),
    type !== CONFIG_TYPES.DEV &&
      new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/,
        contextRegExp: /moment$/,
      }),
    type !== CONFIG_TYPES.DEV &&
      new BundleAnalyzerPlugin({
        analyzerMode: "static",
        openAnalyzer: false,
        reportFilename:
          type === CONFIG_TYPES.ES2015 ? "es2015_report.html" : "report.html",
        reportTitle:
          type === CONFIG_TYPES.ES2015
            ? "es2015+ webpack build report"
            : "es5 webpack build report",
      }),
    type === CONFIG_TYPES.ES2015
      ? new InjectManifest({
          swSrc: path.resolve(
            __dirname,
            "agir/front/components/serviceWorker/serviceWorker.js"
          ),
          swDest: "service-worker.js",
          maximumFileSizeToCacheInBytes: 7000000,
          include: [
            ({ asset, compilation }) => {
              const mainAppEntryFiles = getAppEntryFiles(compilation);
              const otherEntryFiles = getOtherEntryFiles(compilation);

              return (
                mainAppEntryFiles.includes(asset.name) ||
                !(
                  otherEntryFiles.includes(asset.name) ||
                  [/front\/skins/, /\.html$/, /\.LICENSE.txt/].some(
                    (excluded) => excluded.test(asset.name)
                  )
                )
              );
            },
          ],
        })
      : null,
    new webpack.EnvironmentPlugin(["WEBPUSH_PUBLIC_KEY"]),
  ].filter(Boolean),
  output: {
    libraryTarget: "window",
    library: ["Agir", "[name]"],
    filename: `[name]-[chunkhash].${
      type === CONFIG_TYPES.ES2015 ? "mjs" : "js"
    }?cv=2`,
    path: DISTPATH,
  },
  module: {
    rules: [
      configureBabelLoader(type),
      {
        test: /theme\.scss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
      {
        test: /\.scss$/,
        exclude: [new RegExp("theme\\" + path.sep + "theme.scss")],
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              modules: { mode: "icss", auto: /\.scss$/i },
            },
          },
          "sass-loader",
        ],
      },
      {
        test: /\.css$/,
        exclude: [new RegExp("node_modules\\" + path.sep + "tinymce")],
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(jpg|jpeg|png|woff|woff2|eot|ttf|svg)$/,
        exclude: [new RegExp("node_modules\\" + path.sep + "tinymce")],
        type: "asset/resource",
      },
    ],
  },
  optimization: {
    splitChunks: {
      chunks: "all",
    },
  },
  target: "web",
  resolve: {
    alias: aliases,
    modules: ["node_modules"],
  },
  node: {
    __filename: true,
  },
  watchOptions: {
    ignored: /node_modules/,
  },
});

module.exports.CONFIG_TYPES = CONFIG_TYPES;
<commit_msg>fix: bump cloudflare cache version<commit_after>const path = require("path");
const fs = require("fs");

require("dotenv").config({
  path: path.join(__dirname, ".env"),
});

const BundleAnalyzerPlugin =
  require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { InjectManifest } = require("workbox-webpack-plugin");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const WebpackBar = require("webpackbar");

const DISTPATH = path.resolve(__dirname, "assets/components");

const isDirectory = (f) => fs.statSync(f).isDirectory();
const directoryHasFile = (f) => (d) => fs.readdirSync(d).includes(f);

const CONFIG_TYPES = {
  ES2015: "es2015+",
  ES5: "es5",
  DEV: "dev",
};

// establish the list of Django applications with a `components` folder
const applications = fs
  .readdirSync(path.resolve(__dirname, "agir"))
  .map((f) => path.resolve(__dirname, "agir", f))
  .filter(isDirectory)
  .filter(directoryHasFile("components"));

// javascript components are either:
// - directories with an index.js
// - .js files
// that are directly found in a `components` folder of one of the django apps.
//
// The bundle name will be `<django app name>/<name of directory / .js file>`
const components = applications
  .flatMap((dir) =>
    fs
      .readdirSync(path.resolve(dir, "components"))
      .map((f) => [path.basename(dir), path.resolve(dir, "components", f)])
  )
  .filter(([_app, f]) =>
    isDirectory(f) ? directoryHasFile("index.js")(f) : f.endsWith(".js")
  )
  .map(([app, f]) => [app + "/" + path.basename(f, ".js"), f])
  .reduce((obj, [name, file]) => {
    obj[name] = file;
    return obj;
  }, {});

// create import aliases with the django app names leading to their `components` folders
const aliases = applications.reduce(
  (obj, app) => {
    obj["@agir/" + path.basename(app)] = path.resolve(app, "components/");
    return obj;
  },
  {
    luxon: "luxon/src/luxon",
  }
);

// Generate an HTML fragment with all chunks tag for each entry
const htmlPlugins = (type) =>
  Object.keys(components).map(
    (entry) =>
      new HtmlWebpackPlugin({
        filename: `includes/${entry}.${
          type === CONFIG_TYPES.ES2015 ? "modules" : "bundle"
        }.html`,
        scriptLoading: "defer",
        inject: false,
        chunks: [entry],
        templateContent: ({ htmlWebpackPlugin }) => {
          switch (type) {
            case CONFIG_TYPES.DEV:
              return (
                htmlWebpackPlugin.tags.headTags +
                htmlWebpackPlugin.tags.bodyTags
              );
            case CONFIG_TYPES.ES2015:
              return htmlWebpackPlugin.files.js
                .map((file) => `<script type="module" src="${file}"></script>`)
                .join("");
            case CONFIG_TYPES.ES5:
              return (
                htmlWebpackPlugin.files.js
                  .map((file) => `<script nomodule src="${file}"></script>`)
                  .join("") + `{% include "${entry}.modules.html" %}`
              );
          }
        },
      })
  );

// List all chunks on which main app depends for preloading by service worker
let _cachedAppEntryFiles;
const getAppEntryFiles = (compilation) => {
  if (_cachedAppEntryFiles) {
    return _cachedAppEntryFiles;
  }

  _cachedAppEntryFiles = compilation.namedChunkGroups
    .get("front/app")
    .chunks.map((c) => Array.from(c.files))
    .flat();

  return _cachedAppEntryFiles;
};

// List all chunks on which other apps depends for preload exclusion if not in main app
let _cachedOtherEntryFiles;
const getOtherEntryFiles = (compilation) => {
  if (_cachedOtherEntryFiles) {
    return _cachedOtherEntryFiles;
  }

  _cachedOtherEntryFiles = [
    "donations/donationForm",
    "donations/spendingRequestLib",
    "elus/parrainages",
    "front/legacyPages",
    "front/richEditor",
    "groups/groupSelector",
    "lib/adminJsonWidget",
    "lib/communeField",
    "lib/creationForms",
    "lib/IBANField",
    "lib/locationSearchField",
    "theme",
  ]
    .map((name) =>
      compilation.namedChunkGroups
        .get(name)
        .chunks.map((c) => Array.from(c.files))
        .flat()
    )
    .flat();

  return _cachedOtherEntryFiles;
};

const es5Browsers = [
  "> 0.5% in FR",
  "last 2 versions",
  "Firefox ESR",
  "not dead",
  "not IE 11",
];

const es2015Browsers = { esmodules: true };

const configureBabelLoader = (type) => ({
  test: /\.m?js$/,
  include: [
    path.resolve(__dirname, "agir"),
    type === CONFIG_TYPES.ES2015
      ? undefined
      : path.resolve(__dirname, "node_modules/react-spring"),
  ].filter(Boolean),
  exclude:
    type === CONFIG_TYPES.ES2015
      ? []
      : [new RegExp("node_modules\\" + path.sep)],
  use: {
    loader: "babel-loader",
    options: {
      cacheDirectory: process.env.BABEL_CACHE_DIRECTORY || true,
      exclude: [/core-js/, /regenerator-runtime/, /webpack[\\/]buildin/],
      presets: [
        "@babel/preset-react",
        [
          "@babel/preset-env",
          {
            modules: false,
            corejs: "3.20",
            useBuiltIns: "usage",
            targets: type === CONFIG_TYPES.ES5 ? es5Browsers : es2015Browsers,
          },
        ],
      ],
      plugins: [
        "@babel/plugin-syntax-dynamic-import",
        [
          "babel-plugin-styled-components",
          {
            // This option enhances the attached CSS class name on each component with richer output to help identify your components in the DOM.
            displayName: type === CONFIG_TYPES.DEV,
            // Remove comments and whitespace from the CSS.
            minify: type !== CONFIG_TYPES.DEV,
            // Transpile tagged template literals into optimized code.
            transpileTemplateLiterals: type !== CONFIG_TYPES.DEV,
            // By default minifiers cannot properly perform dead code elimination on styled components because they are assumed to have side effects. This enables "pure annotations" to tell the compiler that they do not have side effects.
            pure: type !== CONFIG_TYPES.DEV,
            // Enable SSR optimization
            ssr: false,
          },
        ],
        ["@babel/plugin-transform-runtime", { useESModules: true }],
        type === CONFIG_TYPES.DEV
          ? require.resolve("react-refresh/babel")
          : undefined,
        type !== CONFIG_TYPES.DEV
          ? [
              "transform-react-remove-prop-types",
              {
                removeImport: true,
              },
            ]
          : undefined,
      ].filter(Boolean),
    },
  },
});

module.exports = (type = CONFIG_TYPES.ES5) => ({
  context: path.resolve(__dirname, "agir/"),
  entry: Object.assign(
    {
      theme: path.resolve(__dirname, "agir/front/components/theme/theme.scss"),
    },
    components
  ),
  plugins: [
    type !== CONFIG_TYPES.DEV && new WebpackBar(),
    ...htmlPlugins(type),
    new HtmlWebpackPlugin({
      filename: `includes/theme.bundle.html`,
      inject: false,
      chunks: ["theme"],
      templateContent: ({ htmlWebpackPlugin }) =>
        `<link href="${htmlWebpackPlugin.files.css[0]}" rel="stylesheet">`,
    }),
    new MiniCssExtractPlugin({ filename: "[name]-[chunkhash].css" }),
    type !== CONFIG_TYPES.DEV &&
      new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/,
        contextRegExp: /moment$/,
      }),
    type !== CONFIG_TYPES.DEV &&
      new BundleAnalyzerPlugin({
        analyzerMode: "static",
        openAnalyzer: false,
        reportFilename:
          type === CONFIG_TYPES.ES2015 ? "es2015_report.html" : "report.html",
        reportTitle:
          type === CONFIG_TYPES.ES2015
            ? "es2015+ webpack build report"
            : "es5 webpack build report",
      }),
    type === CONFIG_TYPES.ES2015
      ? new InjectManifest({
          swSrc: path.resolve(
            __dirname,
            "agir/front/components/serviceWorker/serviceWorker.js"
          ),
          swDest: "service-worker.js",
          maximumFileSizeToCacheInBytes: 7000000,
          include: [
            ({ asset, compilation }) => {
              const mainAppEntryFiles = getAppEntryFiles(compilation);
              const otherEntryFiles = getOtherEntryFiles(compilation);

              return (
                mainAppEntryFiles.includes(asset.name) ||
                !(
                  otherEntryFiles.includes(asset.name) ||
                  [/front\/skins/, /\.html$/, /\.LICENSE.txt/].some(
                    (excluded) => excluded.test(asset.name)
                  )
                )
              );
            },
          ],
        })
      : null,
    new webpack.EnvironmentPlugin(["WEBPUSH_PUBLIC_KEY"]),
  ].filter(Boolean),
  output: {
    libraryTarget: "window",
    library: ["Agir", "[name]"],
    filename: `[name]-[chunkhash].${
      type === CONFIG_TYPES.ES2015 ? "mjs" : "js"
    }?cv=3`,
    path: DISTPATH,
  },
  module: {
    rules: [
      configureBabelLoader(type),
      {
        test: /theme\.scss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
      {
        test: /\.scss$/,
        exclude: [new RegExp("theme\\" + path.sep + "theme.scss")],
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              modules: { mode: "icss", auto: /\.scss$/i },
            },
          },
          "sass-loader",
        ],
      },
      {
        test: /\.css$/,
        exclude: [new RegExp("node_modules\\" + path.sep + "tinymce")],
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(jpg|jpeg|png|woff|woff2|eot|ttf|svg)$/,
        exclude: [new RegExp("node_modules\\" + path.sep + "tinymce")],
        type: "asset/resource",
      },
    ],
  },
  optimization: {
    splitChunks: {
      chunks: "all",
    },
  },
  target: "web",
  resolve: {
    alias: aliases,
    modules: ["node_modules"],
  },
  node: {
    __filename: true,
  },
  watchOptions: {
    ignored: /node_modules/,
  },
});

module.exports.CONFIG_TYPES = CONFIG_TYPES;
<|endoftext|>


<commit_before>/**
 * Tests whether or not an object is an array.
 *
 * @private
 * @category Internal
 * @param {*} val The object to test.
 * @return {boolean} `true` if `val` is an array, `false` otherwise.
 * @example
 *
 *      isArray([]); //=> true
 *      isArray(true); //=> false
 *      isArray({}); //=> false
 */
var isArray = Array.isArray || function _isArray(val) {
    return val && val.length >= 0 && toString.call(val) === '[object Array]';
};

export default isArray;
<commit_msg>Add missing private variable to isArray<commit_after>// Private reference to toString function.
var toString = Object.prototype.toString;

/**
 * Tests whether or not an object is an array.
 *
 * @private
 * @category Internal
 * @param {*} val The object to test.
 * @return {boolean} `true` if `val` is an array, `false` otherwise.
 * @example
 *
 *      isArray([]); //=> true
 *      isArray(true); //=> false
 *      isArray({}); //=> false
 */
var isArray = Array.isArray || function _isArray(val) {
    return val && val.length >= 0 && toString.call(val) === '[object Array]';
};

export default isArray;
<|endoftext|>


<commit_before>/**
 * @jsx React.DOM
 */
'use strict';

// config
var config = require('./config');
var api = require('./modules/api')(config);

// dependencies
var React = require('react');
var ReactAsync = require('react-async');
var superagent = require('superagent');

// custom components
var TodoApp = require('./modules/components/todo-app');
var CommentBox = require('./modules/components/comment-box');
var Avatar = require('./modules/components/avatar');
var Counter = require('./modules/components/counter');
var LikeButton = require('./modules/components/like-button');
var Ticker = require('./modules/components/ticker');
var Time = require('./modules/components/time');
var FilterableProductTable = require('./modules/components/filterable-product-table');

// common components
var Head = require('./modules/components/head');
var Header = require('./modules/components/header');
var ExternalScripts = require('./modules/components/common/external-scripts');

// Main page component (this is asyncronous)
var App = React.createClass({
    // mixins
    mixins: [ReactAsync.Mixin],

    // static methods
    statics: {
        getAsyncContent: function(callback) {
            superagent.get('http://localhost:3000/api/resource', function (err, res) {
                callback(err, res ? res.body : null);
            });
        }.bind(this)
    },

    // the initial state of the component (this.type refers to a static method)
    getInitialStateAsync: function(callback) {
        //this.type.getAsyncContent(callback); // fetch async content (disabled for now)
        callback(null, this.props); // set the input props as state (equal to 'return this.props' in getInitialState, but async)
    },

    // main rendering function (uses the state of the component, not the props)
    render: function() {
        return (

React Demo Components

                        <Counter initialCount={10} />
                        <Time startTime={this.state.startTime} />
                        <LikeButton liked={false} />
                        <Ticker offset={0} interval={1000} />

                        <TodoApp
                            type='todo'
                            title='TODO'
                            skin='warning'
                            placeholder='What do you need to do?'
                        />
                        <TodoApp
                            type='focus'
                            title='FOCUS AREAS'
                            skin='success'
                            placeholder='What do you need to focus on?'
                        />
                        <TodoApp
                            type='goal'
                            title='GOALS'
                            skin='info'
                            placeholder='What are your goals?'
                        />
                        <TodoApp
                            type='motivation'
                            title='MOTIVATIONS'
                            skin='danger'
                            placeholder='What are your motivations?'
                        />

                        <CommentBox user={this.state.user} api={api} pollInterval={3000} />

                        <FilterableProductTable
                            skin='danger'
                            title='Filterable Product Table'
                            products={this.state.products}
                        />

                    <ExternalScripts />

        );
    }
});

module.exports = App;

// If the file is processed by the browser, it should mount itself to the document and 'overtake' the markup from the server without rerendering
if (typeof window !== 'undefined') {
    // enable the react developer tools when developing (loads another 450k into the DOM..)
    if (config.environment == 'development') {
        window.React = require('react');
    }

    window.onload = function() {
        React.renderComponent(App(), document);
    }
}
<commit_msg>use correct path for external script dependencies component<commit_after>/**
 * @jsx React.DOM
 */
'use strict';

// config
var config = require('./config');
var api = require('./modules/api')(config);

// dependencies
var React = require('react');
var ReactAsync = require('react-async');
var superagent = require('superagent');

// custom components
var TodoApp = require('./modules/components/todo-app');
var CommentBox = require('./modules/components/comment-box');
var Avatar = require('./modules/components/avatar');
var Counter = require('./modules/components/counter');
var LikeButton = require('./modules/components/like-button');
var Ticker = require('./modules/components/ticker');
var Time = require('./modules/components/time');
var FilterableProductTable = require('./modules/components/filterable-product-table');

// common components
var Head = require('./modules/components/head');
var Header = require('./modules/components/header');
var ExternalScripts = require('./modules/components/external-scripts');

// Main page component (this is asyncronous)
var App = React.createClass({
    // mixins
    mixins: [ReactAsync.Mixin],

    // static methods
    statics: {
        getAsyncContent: function(callback) {
            superagent.get('http://localhost:3000/api/resource', function (err, res) {
                callback(err, res ? res.body : null);
            });
        }.bind(this)
    },

    // the initial state of the component (this.type refers to a static method)
    getInitialStateAsync: function(callback) {
        //this.type.getAsyncContent(callback); // fetch async content (disabled for now)
        callback(null, this.props); // set the input props as state (equal to 'return this.props' in getInitialState, but async)
    },

    // main rendering function (uses the state of the component, not the props)
    render: function() {
        return (

React Demo Components

                        <Counter initialCount={10} />
                        <Time startTime={this.state.startTime} />
                        <LikeButton liked={false} />
                        <Ticker offset={0} interval={1000} />

                        <TodoApp
                            type='todo'
                            title='TODO'
                            skin='warning'
                            placeholder='What do you need to do?'
                        />
                        <TodoApp
                            type='focus'
                            title='FOCUS AREAS'
                            skin='success'
                            placeholder='What do you need to focus on?'
                        />
                        <TodoApp
                            type='goal'
                            title='GOALS'
                            skin='info'
                            placeholder='What are your goals?'
                        />
                        <TodoApp
                            type='motivation'
                            title='MOTIVATIONS'
                            skin='danger'
                            placeholder='What are your motivations?'
                        />

                        <CommentBox user={this.state.user} api={api} pollInterval={3000} />

                        <FilterableProductTable
                            skin='danger'
                            title='Filterable Product Table'
                            products={this.state.products}
                        />

                    <ExternalScripts />

        );
    }
});

module.exports = App;

// If the file is processed by the browser, it should mount itself to the document and 'overtake' the markup from the server without rerendering
if (typeof window !== 'undefined') {
    // enable the react developer tools when developing (loads another 450k into the DOM..)
    if (config.environment == 'development') {
        window.React = require('react');
    }

    window.onload = function() {
        React.renderComponent(App(), document);
    }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { connect } from 'react-redux'

import ScreenshotsPage from '../components/ScreenshotsPage'
import { getScreenshots } from '../actions/entities'

class ScreenshotsContainer extends Component {
  componentDidMount() {
    const { dispatch } = this.props
    dispatch(getScreenshots())
  }

  render() {
    return <ScreenshotsPage {...this.props} />
  }
}

function mapStateToProps(state) {
  const { user, entities, screenshots, ui } = state
  const { users } = entities
  const { uid } = user
  const { view, itemsPerRow } = ui

  return {
    authedUser: users[uid],
    view,
    itemsPerRow,
    users,
    screenshots: entities.screenshots,
    screenshotIds: screenshots.ids
  }
}

export default connect(mapStateToProps)(ScreenshotsContainer)
<commit_msg>Get filtered screenshots by default #5<commit_after>import React, { Component } from 'react'
import { connect } from 'react-redux'

import ScreenshotsPage from '../components/ScreenshotsPage'
import { getFilteredScreenshots } from '../actions/entities'

class ScreenshotsContainer extends Component {
  componentDidMount() {
    const { dispatch } = this.props
    dispatch(getFilteredScreenshots())
  }

  render() {
    return <ScreenshotsPage {...this.props} />
  }
}

function mapStateToProps(state) {
  const { user, entities, screenshots, ui } = state
  const { users } = entities
  const { uid } = user
  const { view, itemsPerRow } = ui

  return {
    authedUser: users[uid],
    view,
    itemsPerRow,
    users,
    screenshots: entities.screenshots,
    screenshotIds: screenshots.ids
  }
}

export default connect(mapStateToProps)(ScreenshotsContainer)
<|endoftext|>


<commit_before>angular.module('mwUI.List')

  .directive('mwListFooterRow', function (Loading) {
    return {
      require: '^mwListableBb',
      templateUrl: 'uikit/templates/mwList/mw-list-footer.html',
      link: function (scope, elm, attr, mwListCtrl) {
        scope.Loading = Loading;
        scope.collection = mwListCtrl.getCollection();
        scope.columns = mwListCtrl.getColumns();
      }
    };
  });<commit_msg>fixes backwards compatibility by using old name<commit_after>angular.module('mwUI.List')
  //TODO rename
  .directive('mwListableFooterBb', function (Loading) {
    return {
      require: '^mwListableBb',
      templateUrl: 'uikit/mw-list/directives/templates/mw_list_footer.html',
      link: function (scope, elm, attr, mwListCtrl) {
        scope.Loading = Loading;
        scope.collection = mwListCtrl.getCollection();
        scope.columns = mwListCtrl.getColumns();
      }
    };
  });<|endoftext|>


<commit_before>Handlebars.registerHelper('cedar', function(options) {
  "use strict";

  var hashCode = function(string) {
    var hash = 0;
    if (string.length == 0) return hash;
    for (var i = 0; i < string.length; i++) {
      var character = string.charCodeAt(i);
      hash = ((hash << 5) - hash) + character;
      hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
  };

  var unescapeHtml = function(string) {
    var MAP = {
      '&': '&',
      '<': '<',
      '>': '>',
      '"': '"',
      ''': "'",
      ''': "'"
    };

    return string.replace(/&#?\w+;/g, function(c) {
      return MAP[c];
    });
  };

  options.el = document.createElement("span");
  options.el.id = "cedar-js-" + hashCode(options.hash.id);

  new Cedar.ContentEntry({ cedarId: options.hash.id }).retrieve().then(function(contentEntry){

    var domEl = document.getElementById(options.el.id);
    if (domEl === null) {
      domEl = options.el;
    }

    if (typeof options.fn === "undefined") {
      domEl.innerHTML = contentEntry.getContent();
    } else if (typeof options.fn === "function") {
      var output = '';
      if (Cedar.auth.isEditMode()) {
        output += contentEntry.getEditOpen();
      }
      output += unescapeHtml(options.fn(contentEntry.toJSON()));
      if (Cedar.auth.isEditMode()) {
        output += contentEntry.getEditClose();
      }
      domEl.innerHTML = output;
    }
  });

  return new Handlebars.SafeString(options.el.outerHTML);
});
<commit_msg>Added comments<commit_after>Handlebars.registerHelper('cedar', function(options) {
  "use strict";

  var hashCode = function(string) {
    var hash = 0;
    if (string.length == 0) return hash;
    for (var i = 0; i < string.length; i++) {
      var character = string.charCodeAt(i);
      hash = ((hash << 5) - hash) + character;
      hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
  };

  var unescapeHtml = function(string) {
    var MAP = {
      '&': '&',
      '<': '<',
      '>': '>',
      '"': '"',
      ''': "'",
      ''': "'"
    };

    return string.replace(/&#?\w+;/g, function(c) {
      return MAP[c];
    });
  };

  options.el = document.createElement("span");
  options.el.id = "cedar-js-" + hashCode(options.hash.id);

  new Cedar.ContentEntry({ cedarId: options.hash.id }).retrieve().then(function(contentEntry){

    var domEl = document.getElementById(options.el.id);
    if (domEl === null) {
      domEl = options.el;
    }

    if (typeof options.fn === "undefined") { // If using inline-style helper
      domEl.innerHTML = contentEntry.getContent();
    } else if (typeof options.fn === "function") { // If using block-style helper
      var output = '';
      if (Cedar.auth.isEditMode()) {
        output += contentEntry.getEditOpen();
      }
      output += unescapeHtml(options.fn(contentEntry.toJSON()));
      if (Cedar.auth.isEditMode()) {
        output += contentEntry.getEditClose();
      }
      domEl.innerHTML = output;
    }
  });

  return new Handlebars.SafeString(options.el.outerHTML);
});
<|endoftext|>


<commit_before>const os = require('os');
const utils = require('./../../utils.js');
const config = require('config');

// Non-changing statistics
// (x64) AMD Athlon (x3) Something @ 3ghz (clocked at ????MHz)
const hardwareinfo = `(${os.arch()}) ${os.cpus()[0].model} clocked at ${os.cpus()[0].speed} MHz`;
const softwareinfo = `[${os.type()}] ${os.release()}`;

module.exports.info = {
	name: 'Information',
	description: 'Get info regarding the bot.',
	category: 'Info',
	aliases: [
		'info'
	],
	use: [
		{
			name: '',
			value: 'Obtain info'
		}
	]
};

module.exports.command = (message, client) => {
	const embed = {
		embed: {
			title: config.get('name'),
			fields: [
				{
					name: 'Node.js',
					value: process.version,
					embed: true
				},
				{
					name: 'Uptime',
					value: utils.timestamp(process.uptime()),
					embed: true
				},
				{
					name: 'Guilds',
					value: client.guilds.size,
					embed: true
				},
				{
					name: 'PID',
					value: process.pid,
					embed: true
				},
				{
					name: 'Hardware',
					value: hardwareinfo
				},
				{
					name: 'Software',
					value: softwareinfo
				},
				{
					name: 'Licence',
					value: `${config.get('name')}, an instance of MSS-Discord is licenced under the MIT Licence`
				}
			]
		}
	};

	return message.channel.createMessage(embed);
};
<commit_msg>allow inline<commit_after>const os = require('os');
const utils = require('./../../utils.js');
const config = require('config');

// Non-changing statistics
// (x64) AMD Athlon (x3) Something @ 3ghz (clocked at ????MHz)
const hardwareinfo = `(${os.arch()}) ${os.cpus()[0].model} clocked at ${os.cpus()[0].speed} MHz`;
const softwareinfo = `[${os.type()}] ${os.release()}`;

module.exports.info = {
	name: 'Information',
	description: 'Get info regarding the bot.',
	category: 'Info',
	aliases: [
		'info'
	],
	use: [
		{
			name: '',
			value: 'Obtain info'
		}
	]
};

module.exports.command = (message, client) => {
	const embed = {
		embed: {
			title: config.get('name'),
			fields: [
				{
					name: 'Node.js',
					value: process.version,
					inline: true
				},
				{
					name: 'Uptime',
					value: utils.timestamp(process.uptime()),
					inline: true
				},
				{
					name: 'Guilds',
					value: client.guilds.size,
					inline: true
				},
				{
					name: 'PID',
					value: process.pid,
					inline: true
				},
				{
					name: 'Hardware',
					value: hardwareinfo
				},
				{
					name: 'Software',
					value: softwareinfo
				},
				{
					name: 'Licence',
					value: `${config.get('name')}, an instance of MSS-Discord is licenced under the MIT Licence`
				}
			]
		}
	};

	return message.channel.createMessage(embed);
};
<|endoftext|>


<commit_before>/* eslint-env mocha */

import { Client as CozyClient } from 'cozy-client-js'
console.log(CozyClient)

import { FILES_DOCTYPE, ROOT_DIR_ID, TRASH_DIR_ID } from '../../src/remote/constants'
import { BuilderFactory } from '../builders'

// The URL of the Cozy instance used for tests
export const COZY_URL = process.env.COZY_URL || 'http://test.cozy-desktop.local:8080'

if (!process.env.COZY_STACK_TOKEN) {
  const domain = COZY_URL.replace('http://', '')
  console.log('COZY_STACK_TOKEN is missing. You can generate it with this command:')
  console.log(`export COZY_CLIENT_ID=$(cozy-stack instances client-oauth "${domain}" http://localhost/ test github.com/cozy-labs/cozy-desktop)`)
  console.log(`export COZY_STACK_TOKEN=$(cozy-stack instances token-oauth "${domain}" "$COZY_CLIENT_ID" io.cozy.files)`)
  console.log(' ')
  throw new Error('No COZY_STACK_TOKEN')
}

// A cozy-client-js instance
export const cozy = new CozyClient({
  cozyURL: COZY_URL,
  oauth: {}
})

// FIXME: Temporary hack to make cozy-client-js think it has OAuth tokens
cozy._authstate = 3
cozy._authcreds = Promise.resolve({
  token: {
    toAuthHeader () { return 'Bearer ' + process.env.COZY_STACK_TOKEN }
  }
})

// Facade for all the test data builders
export const builders = new BuilderFactory(cozy)

// List files and directories in the root directory
async function rootDirContents () {
  const index = await cozy.data.defineIndex(FILES_DOCTYPE, ['dir_id'])
  const docs = await cozy.data.query(index, {
    selector: {
      dir_id: ROOT_DIR_ID,
      '$not': {_id: TRASH_DIR_ID}
    },
    fields: ['_id', 'dir_id']
  })

  return docs
}

// Delete all files and directories
export async function deleteAll () {
  const docs = await rootDirContents()

  await Promise.all(docs.map(doc => cozy.files.trashById(doc._id)))

  return cozy.files.clearTrash()
}

// Creates a root directory named 'couchdb-folder', used in a lot of v2 tests.
//
// TODO: Use test data builders instead
export async function createTheCouchdbFolder () {
  await builders.dir()
    .named('couchdb-folder')
    .inRootDir()
    .build()
}
<commit_msg>test/helpers: Enable type checks<commit_after>/* @flow */
/* eslint-env mocha */

import { Client as CozyClient } from 'cozy-client-js'

import { FILES_DOCTYPE, ROOT_DIR_ID, TRASH_DIR_ID } from '../../src/remote/constants'
import { BuilderFactory } from '../builders'

// The URL of the Cozy instance used for tests
export const COZY_URL = process.env.COZY_URL || 'http://test.cozy-desktop.local:8080'

if (!process.env.COZY_STACK_TOKEN) {
  const domain = COZY_URL.replace('http://', '')
  console.log('COZY_STACK_TOKEN is missing. You can generate it with this command:')
  console.log(`export COZY_CLIENT_ID=$(cozy-stack instances client-oauth "${domain}" http://localhost/ test github.com/cozy-labs/cozy-desktop)`)
  console.log(`export COZY_STACK_TOKEN=$(cozy-stack instances token-oauth "${domain}" "$COZY_CLIENT_ID" io.cozy.files)`)
  console.log(' ')
  throw new Error('No COZY_STACK_TOKEN')
}

// A cozy-client-js instance
export const cozy = new CozyClient({
  cozyURL: COZY_URL,
  oauth: {}
})

// FIXME: Temporary hack to make cozy-client-js think it has OAuth tokens
cozy._authstate = 3
cozy._authcreds = Promise.resolve({
  token: {
    toAuthHeader () { return 'Bearer ' + (process.env.COZY_STACK_TOKEN || '') }
  }
})

// Facade for all the test data builders
export const builders = new BuilderFactory(cozy)

// List files and directories in the root directory
async function rootDirContents () {
  const index = await cozy.data.defineIndex(FILES_DOCTYPE, ['dir_id'])
  const docs = await cozy.data.query(index, {
    selector: {
      dir_id: ROOT_DIR_ID,
      '$not': {_id: TRASH_DIR_ID}
    },
    fields: ['_id', 'dir_id']
  })

  return docs
}

// Delete all files and directories
export async function deleteAll () {
  const docs = await rootDirContents()

  await Promise.all(docs.map(doc => cozy.files.trashById(doc._id)))

  return cozy.files.clearTrash()
}

// Creates a root directory named 'couchdb-folder', used in a lot of v2 tests.
//
// TODO: Use test data builders instead
export async function createTheCouchdbFolder () {
  await builders.dir()
    .named('couchdb-folder')
    .inRootDir()
    .build()
}
<|endoftext|>


<commit_before>/*eslint-env node */
var path = require('path');

var loaders = [
  {
    test: /\.js$/,
    loader: 'babel',
    exclude: /node_modules/,
  },
  {
    test: /\.css$/,
    exclude: /\.global\.css$/,
    loaders: [
      'style?sourceMap',
      'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
    ],
  },
  {test: /\.global\.css$/, loader: 'style!raw'},
];

module.exports = [{
  entry: './src/RichTextEditor.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'react-rte.js',
    libraryTarget: 'commonjs2',
  },
  externals: {
    react: 'react',
    'react-dom': 'react-dom',
  },
  module: {loaders: loaders},
}, {
  entry: './src/demo.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'demo.js',
  },
  module: {loaders: loaders},
}];
<commit_msg>Eliminate dead code from output bundle (#80)<commit_after>/*eslint-env node */
var path = require('path');
var webpack = require('webpack');

var loaders = [
  {
    test: /\.js$/,
    loader: 'babel',
    exclude: /node_modules/,
  },
  {
    test: /\.css$/,
    exclude: /\.global\.css$/,
    loaders: [
      'style?sourceMap',
      'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
    ],
  },
  {test: /\.global\.css$/, loader: 'style!raw'},
];

module.exports = [{
  entry: './src/RichTextEditor.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'react-rte.js',
    libraryTarget: 'commonjs2',
  },
  externals: {
    react: 'react',
    'react-dom': 'react-dom',
  },
  module: {loaders: loaders},
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      beautify: true,
      comments: true,
      mangle: false,
      compress: {
        dead_code: true,
      },
    }),
  ],
}, {
  entry: './src/demo.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'demo.js',
  },
  module: {loaders: loaders},
}];
<|endoftext|>


<commit_before>#!/usr/bin/env node

import './babel-maybefill';

import _ from 'lodash';
import request from 'request-promise';

import {asyncMap} from './promise-array';
import {getOriginForRepo} from './git-api';
import {getNwoFromRepoUrl, getCommitStatusesForRef} from './github-api';
import createRefServer from './ref-server-api';

const d = require('debug')('surf:commit-status-cli');

const yargs = require('yargs')
  .usage(`Usage: surf-status --repo https://github.com/owner/repo
Returns the GitHub Status for all the branches in a repo`)
  .alias('s', 'server')
  .describe('s', 'The Surf server to connect to - use this if you call surf-status repeatedly')  .help('h')
  .alias('r', 'repo')
  .describe('r', 'The URL of the repository to fetch status for. Defaults to the repo in the current directory')
  .alias('h', 'help')
  .epilog(`
Some useful environment variables:

SURF_PORT - the port to serve on if not specified via -p, defaults to 3000.
GITHUB_ENTERPRISE_URL - the GitHub Enterprise URL to use.
GITHUB_TOKEN - the GitHub API token to use. Must be provided.

SURF_REPO - an alternate way to specify the --repo parameter, provided
            automatically by surf-client.`);

const argv = yargs.argv;

async function main(testRepo=null, testServer=null) {
  let repo = testRepo || argv.r || process.env.SURF_REPO;
  let server = testServer || argv.s;

  if (!repo) {
    try {
      repo = await getOriginForRepo('.');
    } catch (e) {
      console.error("Repository not specified and current directory is not a Git repo");
      d(e.stack);

      yargs.showHelp();
      process.exit(-1);
    }
  }

  let killRefServer = null;
  if (!server) {
    let nwo = getNwoFromRepoUrl(repo);
    killRefServer = createRefServer([nwo]);
    server = `http://localhost:${process.env.SURF_PORT || 3000}`;
  }

  d(`Getting nwo for ${repo}`);
  let nwo = getNwoFromRepoUrl(repo);
  let surfUrl = `${server}/info/${nwo}`;

  const fetchRefs = async () => {
    return await request({
      uri: surfUrl,
      json: true
    });
  };

  let refList = _.map(await fetchRefs(), (x) => x.ref);
  let statuses = await asyncMap(refList, (ref) => getCommitStatusesForRef(nwo, ref));

  let statusArr = _.map(refList, (x) => statuses[x]);
  console.log(JSON.stringify(statusArr));

  killRefServer.dispose();
}

main()
  .then(() => process.exit(0), (e) => {
    console.error(e.message);
    d(e.stack);
    process.exit(-1);
  });
<commit_msg>Get some text going<commit_after>#!/usr/bin/env node

import './babel-maybefill';

import _ from 'lodash';
import request from 'request-promise';
import chalk from 'chalk';

import {asyncMap} from './promise-array';
import {getOriginForRepo} from './git-api';
import {getNwoFromRepoUrl, getCommitStatusesForRef} from './github-api';
import createRefServer from './ref-server-api';

const d = require('debug')('surf:commit-status-cli');

const yargs = require('yargs')
  .usage(`Usage: surf-status --repo https://github.com/owner/repo
Returns the GitHub Status for all the branches in a repo`)
  .alias('s', 'server')
  .describe('s', 'The Surf server to connect to - use this if you call surf-status repeatedly')  .help('h')
  .alias('r', 'repo')
  .describe('r', 'The URL of the repository to fetch status for. Defaults to the repo in the current directory')
  .alias('j', 'json')
  .describe('j', 'Dump the commit status in JSON format for machine parsing instead of human-readable format')
  .alias('h', 'help')
  .epilog(`
Some useful environment variables:

SURF_PORT - the port to serve on if not specified via -p, defaults to 3000.
GITHUB_ENTERPRISE_URL - the GitHub Enterprise URL to use.
GITHUB_TOKEN - the GitHub API token to use. Must be provided.

SURF_REPO - an alternate way to specify the --repo parameter, provided
            automatically by surf-client.`);

const argv = yargs.argv;

async function main(testRepo=null, testServer=null, useJson=null) {
  let repo = testRepo || argv.r || process.env.SURF_REPO;
  let server = testServer || argv.s;
  let jsonOnly = useJson || argv.j;

  if (!repo) {
    try {
      repo = await getOriginForRepo('.');
    } catch (e) {
      console.error("Repository not specified and current directory is not a Git repo");
      d(e.stack);

      yargs.showHelp();
      process.exit(-1);
    }
  }

  let killRefServer = null;
  if (!server) {
    let nwo = getNwoFromRepoUrl(repo);
    killRefServer = createRefServer([nwo]);
    server = `http://localhost:${process.env.SURF_PORT || 3000}`;
  }

  d(`Getting nwo for ${repo}`);
  let nwo = getNwoFromRepoUrl(repo);
  let surfUrl = `${server}/info/${nwo}`;

  const fetchRefs = async () => {
    return await request({
      uri: surfUrl,
      json: true
    });
  };

  let refInfo = await fetchRefs();
  let refList = _.map(refInfo, (x) => x.ref);
  let statuses = await asyncMap(refList, (ref) => getCommitStatusesForRef(nwo, ref));

  if (jsonOnly) {
    let statusArr = _.map(refList, (x) => statuses[x].result);
    console.log(JSON.stringify(statusArr));
  } else {
    const statusToIcon = {
      'success': chalk.green('✓'),
      'failure': chalk.red('✘'),
      'error': chalk.red('✘'),
      'pending': chalk.yellow('‽')
    };

    _.each(refList, (ref) => {
      let status = statuses[ref].result;
      if (status.total_count < 1) return;

      if (status.total_count === 1) {
        console.log(`${statusToIcon[status.state]}: ${ref} - ${status.description || '(No description)'} - ${status.target_url || '(No CI URL given)'}`);
      } else {
        console.log(`${statusToIcon[status.state]}: ${ref}`);
        _.each(status.statuses, (status) => {
          console.log(`  ${status.description} - ${status.target_url}`);
        });
      }
    });
  }

  killRefServer.dispose();
}

main()
  .then(() => process.exit(0), (e) => {
    console.error(e.message);
    d(e.stack);
    process.exit(-1);
  });
<|endoftext|>


<commit_before>/*jshint white: false, strict: false, plusplus: false, onevar: false,
  nomen: false */
/*global module: false, gladius: false, stop: false, start: false, test: false,
  expect: false, asyncTest: false, ok: false, deepEqual: false, equal: false */

(function() {
    var engine = null;

    module('base/Resource', {

        setup : function() {
            stop();

            gladius.create({
                debug : true
            }, function(instance) {
                engine = instance;
                start();
            });
        },
        teardown : function() {
            engine = null;
        }
    });

    asyncTest( 'construct a new resource type and an instance of it',
           function() {
             expect(1);

             var Text = engine.base.Resource({
               type: 'Text',
               construct: function constructText( data ) {
                 this.value = data;
               }
             });

             Text({
               url: "data:text/plain,Hello%20World",
               onsuccess: function onTextSuccess( text ) {
                 deepEqual( text ,
                    { value: "Hello World" },
                    "text object constructed from data URL");
                 start();
               },
               onfailure: function onTextFailure( error ) {
                 ok(false, "onTextFailure improperly called with " + error);
                 start();
               }
             });
           });

    // Some day we can do even better by using mocks and ensuring that any HTTP
    // status code < 200 or > 299 fails.
    asyncTest( 'ensure onfailure gets called on loading non-existent file',
                function () {

        expect(1);

        var Text = engine.base.Resource({
            type: 'Text',
            construct: function constructText( data ) {
              this.value = data;
            }
          });

        Text({
            url: "no-such-url-exists",
            onsuccess: function onTextSuccess( text ) {
                ok( false, "non-existent file load shouldn't call onsuccess" );
                start();            },
            onfailure: function onTextFailure( error ) {
                ok( true, "non-existent file load should call onfailure");
                start();
            }
          });

     });

    test( 'custom resource without type throws an exception',
      function () {

        expect(1);

        raises( function() {
            var Text = engine.base.Resource({
                construct: function constructText( data ) {
                    this.value = data;
                }
            });
        }, function( exception ) {
            return exception.message == "missing type parameter";
        }, 'base resource throws exception for missing type parameter');

      });

    asyncTest( 'construct a new resource type and an instance of it',
            function() {
              expect(3);

              var testUrl = 'test-url';

              var Text = engine.base.Resource({
                type: 'Text',
                load: function loadText( url ) {
                    equal( url, testUrl, 'url is passed into load function' );
                    return url;
                },
                construct: function constructText( data ) {
                  equal( data, testUrl, 'data returned by load is correct' );
                  this.value = data;
                }
              });

              Text({
                url: testUrl,
                onsuccess: function onTextSuccess( text ) {
                  deepEqual( text ,
                     { value: testUrl },
                     "text object is constructed from loaded data");
                  start();
                },
                onfailure: function onTextFailure( error ) {
                  ok(false, "onTextFailure improperly called with " + error);
                  start();
                }
              });
            });

    // TD: test that default loader can be overridden with a closure when
    // creating an procedurally loaded instance of a given type

    // TD: test that onfailure is invoked if load fails or returned undefined

    // TD: test that onfailure is invoked if construct fails

}());

     // TD: test data URLs, and commutativity/normalization of params:
     //
     // "data:gladius/script;core.script.test?x=1&y=2"
     // "data:gladius/script;core.script.test?y=2&x=1"

<commit_msg>More unit tests, along with some qunit message changes.<commit_after>/*jshint white: false, strict: false, plusplus: false, onevar: false,
  nomen: false */
/*global module: false, gladius: false, stop: false, start: false, test: false,
  expect: false, asyncTest: false, ok: false, deepEqual: false, equal: false */

(function() {
    var engine = null;

    module('base/Resource', {

        setup : function() {
            stop();

            gladius.create({
                debug : true
            }, function(instance) {
                engine = instance;
                start();
            });
        },
        teardown : function() {
            engine = null;
        }
    });

    asyncTest( 'construct a new resource type and an instance of it',
           function() {
             expect(1);

             var Text = engine.base.Resource({
               type: 'Text',
               construct: function constructText( data ) {
                 this.value = data;
               }
             });

             Text({
               url: "data:text/plain,Hello%20World",
               onsuccess: function onTextSuccess( text ) {
                 deepEqual( text ,
                    { value: "Hello World" },
                    "text object constructed from data URL");
                 start();
               },
               onfailure: function onTextFailure( error ) {
                 ok(false, "onfailure should not be invoked");
                 start();
               }
             });
           });

    // Some day we can do even better by using mocks and ensuring that any HTTP
    // status code < 200 or > 299 fails.
    asyncTest( 'ensure onfailure gets called on loading non-existent file',
                function () {

        expect(1);

        var Text = engine.base.Resource({
            type: 'Text',
            construct: function constructText( data ) {
              this.value = data;
            }
          });

        Text({
            url: "no-such-url-exists",
            onsuccess: function onTextSuccess( text ) {
                ok( false, "non-existent file load shouldn't call onsuccess" );
                start();            },
            onfailure: function onTextFailure( error ) {
                ok( true, "onfailure is invoked");
                start();
            }
          });

     });

    test( 'custom resource without type throws an exception',
      function () {

        expect(1);

        raises( function() {
            var Text = engine.base.Resource({
                construct: function constructText( data ) {
                    this.value = data;
                }
            });
        }, function( exception ) {
            return exception.message == "missing type parameter";
        }, 'base resource throws exception for missing type parameter');

      });

    asyncTest( 'default load function is invoked',
            function() {
              expect(3);

              var testUrl = 'test-url';

              var Text = engine.base.Resource({
                type: 'Text',
                load: function loadText( url ) {
                    equal( url, testUrl, 'url is passed into load function' );
                    return url;
                },
                construct: function constructText( data ) {
                  equal( data, testUrl, 'data returned by load is correct' );
                  this.value = data;
                }
              });

              Text({
                url: testUrl,
                onsuccess: function onTextSuccess( text ) {
                  deepEqual( text ,
                     { value: testUrl },
                     "text object is constructed from loaded data");
                  start();
                },
                onfailure: function onTextFailure( error ) {
                  ok(false, "onfailure should not be invoked");
                  start();
                }
              });
            });

    asyncTest( 'default load function can be overridden and alternate load is invoked',
            function() {
              expect(3);

              var testUrl = 'test-url';
              var overrideUrl = 'override-url';

              var Text = engine.base.Resource({
                type: 'Text',
                load: function loadText( url ) {
                    ok( false, 'default load function should not be invoked' );
                    return url;
                },
                construct: function constructText( data ) {
                  equal( data, overrideUrl, 'data returned by load is correct' );
                  this.value = data;
                }
              });

              Text({
                url: testUrl,
                load: function loadText( url ) {
                    return overrideUrl;
                },
                onsuccess: function onTextSuccess( text ) {
                  deepEqual( text ,
                     { value: overrideUrul },
                     "text object is constructed from loaded data");
                  start();
                },
                onfailure: function onTextFailure( error ) {
                  ok(false, "onfailure should not be invoked");
                  start();
                }
              });
            });

    asyncTest( 'onfailure is invoked when load throws an exception',
            function() {
              expect(1);

              var testUrl = 'test-url';

              var Text = engine.base.Resource({
                type: 'Text',
                load: function loadText( url ) {
                    throw "an exception";
                    return url;
                },
                construct: function constructText( data ) {
                  ok( false, 'construct is not invoked when load throws an exception' );
                  this.value = data;
                }
              });

              Text({
                url: testUrl,
                onsuccess: function onTextSuccess( text ) {
                    ok( false, 'onsuccess should not be invoked when load throws an exception');
                    start();
                },
                onfailure: function onTextFailure( error ) {
                  ok(true, "onfailure is invoked");
                  start();
                }
              });
            });

    asyncTest( 'onfailure is invoked when load returns undefined',
            function() {
              expect(1);

              var testUrl = 'test-url';

              var Text = engine.base.Resource({
                type: 'Text',
                load: function loadText( url ) {
                    return undefined;
                },
                construct: function constructText( data ) {
                  ok( false, 'construct is not invoked when load returns undefined' );
                  this.value = data;
                }
              });

              Text({
                url: testUrl,
                onsuccess: function onTextSuccess( text ) {
                    ok( false, 'onsuccess should not be invoked when load returns undefined');
                    start();
                },
                onfailure: function onTextFailure( error ) {
                  ok(true, "onfailure is invoked");
                  start();
                }
              });
            });

    asyncTest( 'onfailure is invoked when construct throws an exception',
            function() {
              expect(1);

              var testUrl = 'test-url';

              var Text = engine.base.Resource({
                type: 'Text',
                load: function loadText( url ) {
                    return url;
                },
                construct: function constructText( data ) {
                    throw "an exception";
                }
              });

              Text({
                url: testUrl,
                onsuccess: function onTextSuccess( text ) {
                    ok( false, 'onsuccess should not be invoked when construct throws an exception');
                    start();
                },
                onfailure: function onTextFailure( error ) {
                  ok(true, "onfailure is invoked");
                  start();
                }
              });
            });

}());

     // TD: test data URLs, and commutativity/normalization of params:
     //
     // "data:gladius/script;core.script.test?x=1&y=2"
     // "data:gladius/script;core.script.test?y=2&x=1"

<|endoftext|>


<commit_before>(function() {
    'use strict';

    angular
        .module('student')
        .factory('lectureFactory', lectureFactory);

    /* @ngInject */
    function lectureFactory(lectureService, $location) {
        console.log('Ready (Lecture Factory)');
        var lectureId;

        // NOTE: This object needs to be stored locally
        // in order to load a joined lecture on page refresh.
        var lecture = {};

        var service = {
            submitComment: submitComment,
            joinLecture: joinLecture,
            leaveLecture: leaveLecture,
            getComments: getComments
        };

        return service;

        function joinLecture(id, error) {

            // Only get lecture if no lecture is present.
            if (angular.isUndefined(lecture.id)) {
                if (angular.isDefined(id)) {
                    lectureId = id;
                }

                lectureService.retrieveLecture
                    .get({lectureId: lectureId}, onSuccess, onFail);
            }

            function onSuccess(response) {
                console.log('Success');
                lecture = response;
                $location.path('/lecture/' + id);
            }

            function onFail(response) {
                console.log('Error: ', response.message);

                // Show user feedback.
                if (angular.isFunction(error)) {
                    error();
                }

                // When manually typing the route with an id,
                // Redirect user to default route.
                $location.path('/');
            }
        }

        function leaveLecture() {
            lectureId = undefined;
            $location.path('/');
        }

        function submitComment(comment, onSuccess, onError) {
            if (angular.isDefined(lectureId)) {
                lectureService.submitComment
                    .save({lectureId: lectureId}, {data: comment}, onSuccess, onError);
            }
        }

        function getComments(onSuccess, onFail) {
            if (angular.isDefined(lectureId)) {
                lectureService.retrieveComments
                    .get({lectureId: lectureId}, onSuccess, onFail);
            }
        }
    }
})();<commit_msg>Fix rejoining lecture<commit_after>(function() {
    'use strict';

    angular
        .module('student')
        .factory('lectureFactory', lectureFactory);

    /* @ngInject */
    function lectureFactory(lectureService, $location) {
        console.log('Ready (Lecture Factory)');
        var lectureId;

        // NOTE: This object needs to be stored locally
        // in order to load a joined lecture on page refresh.
        var lecture = {};

        var service = {
            submitComment: submitComment,
            joinLecture: joinLecture,
            leaveLecture: leaveLecture,
            getComments: getComments
        };

        return service;

        function joinLecture(id, error) {

            // Only get lecture if no lecture is present.
            if (angular.isUndefined(lecture.id)) {
                if (angular.isDefined(id)) {
                    lectureId = id;
                }

                lectureService.retrieveLecture
                    .get({lectureId: lectureId}, onSuccess, onFail);
            }

            function onSuccess(response) {
                console.log('Success');
                lecture = response;
                $location.path('/lecture/' + id);
            }

            function onFail(response) {
                console.log('Error: ', response.message);

                // Show user feedback.
                if (angular.isFunction(error)) {
                    error();
                }

                // When manually typing the route with an id,
                // Redirect user to default route.
                $location.path('/');
            }
        }

        function leaveLecture() {
            lectureId = undefined;
            lecture = {};
            $location.path('/');
        }

        function submitComment(comment, onSuccess, onError) {
            if (angular.isDefined(lectureId)) {
                lectureService.submitComment
                    .save({lectureId: lectureId}, {data: comment}, onSuccess, onError);
            }
        }

        function getComments(onSuccess, onFail) {
            if (angular.isDefined(lectureId)) {
                lectureService.retrieveComments
                    .get({lectureId: lectureId}, onSuccess, onFail);
            }
        }
    }
})();<|endoftext|>


<commit_before>/*
	以下文件老版本会引用到，不能在服务器上彻底删除

	/static/js/em-open.js
	/static/js/em-transfer.js
*/
// todo: 优化构建速度
// todo: 减少重复构建

const path = require("path");
const webpack = require("webpack");
const i18next = require("i18next");
const _zh_cn_map_ = require("./src/i18n/zh-CN");
const _en_us_map_ = require("./src/i18n/en-US");
const VERSION = "pre_47.15.0";

const argv = require("yargs").argv;
const lang = argv.lang || "zh-CN";

var distPath = lang === "zh-CN" ? "" : lang;
var staticPath = lang === "zh-CN" ? "static" : "../static";
var conmmonConfig;
var transfer;
var easemob;
var app;
var appPageCached;
var taskList;

i18next.init({
	lng: lang,
	fallbackLng: false,
	keySeparator: ".",
	nsSeparator: false,
	saveMissing: true,
	resources: {
		"zh-CN": {
			translation: _zh_cn_map_,
		},
		"en-US": {
			translation: _en_us_map_,
		},
	},
});

conmmonConfig = {
	plugins: [
		new webpack.optimize.UglifyJsPlugin({
			compress: {
				warnings: false,
			},
			test: /\.js$/i,
			sourceMap: true,
			comments: false,
			mangle: {
				screw_ie8: false,
			},
		}),
	],
	devtool: "eval",
	module: {
		loaders: [
			{
				test: /easemob\.scss$/,
				loaders: [
					"ie8-style-loader?sourceMap=true",
					"postcss-loader?sourceMap=true",
					"sass-loader?sourceMap=true",
				],
			},
			{
				test: /im\.html$/,
				loaders: [
					"file-loader?name=../../[name].[ext]",
					"extract-loader",
					"html-loader",
					"string-replace-loader"
						+ "?search=__STATIC_PATH__"
						+ "&replace=" + staticPath
						+ "&flags=g",
				],
			},
			{
				test: /transfer\.html$/,
				loaders: [
					"file-loader?name=../../[name].[ext]",
					"extract-loader",
					"html-loader",
				],
			},
			{
				test: /im\.scss$/,
				loaders: [
					"file-loader?name=../css/[name].css",
					"extract-loader",
					"css-loader?sourceMap=true",
					"postcss-loader?sourceMap=true",
					"sass-loader?sourceMap=true&importLoader=true"
				],
			},
			{
				test: require.resolve("./src/js/app/sdk/webim.config.js"),
				loader: "expose-loader?WebIM"
			},
			{
				test: require.resolve("underscore"),
				loader: "expose-loader?_"
			},
			{
				test: require.resolve("./src/js/app/lib/modernizr.js"),
				loader: "expose-loader?Modernizr"
			},
			{
				test: [
					/init\.js$/,
					/userAPI\.js$/,
					/im\.html/,
					/iframe\.js/,
					/transfer\.html/,
				],
				loader: "string-replace-loader",
				query: {
					search: "__WEBIM_PLUGIN_VERSION__",
					replace: VERSION,
					flags: "g",
				},
			},
			{
				test: /\.js$/,
				loader: "i18next-loader",
				query: {
					quotes: "\"",
				},
			},
			// 字体文件
			{
				test: /\.(eot|svg|ttf|woff|woff2)$/,
				loader: "file-loader",
				query: {
					name: "../css/font/[name]-[hash:6].[ext]",
				},
			},
		],
	},
};

transfer = Object.assign({}, conmmonConfig, {
	name: "transfer",
	entry: [
		"./src/js/transfer/api.js",
		"./src/html/transfer.html",
	],
	output: {
		filename: "em-transfer.js",
		path: path.resolve(__dirname, "static/js"),
	},
});

easemob = Object.assign({}, conmmonConfig, {
	name: "easemob",
	entry: [
		"./src/js/common/polyfill",
		"./src/js/plugin/userAPI.js",
	],
	output: {
		filename: "easemob.js",
		path: path.resolve(__dirname, distPath, "."),
		// 不能用umd模块输出的原因是：
		// 监测到AMD Loader时只执行define，此时不会初始化模块，所以不会暴露到全局
		// library: 'easemob-kefu-webim-plugin',
		// libraryTarget: 'umd',
		// umdNamedDefine: true,
	},
});

app = Object.assign({}, conmmonConfig, {
	name: "app",
	entry: [
		"./src/js/app/modules/init.js",
		"./src/scss/im.scss",
		"./src/html/im.html",
	],
	output: {
		filename: "main.js",
		path: path.resolve(__dirname, distPath, "static/js"),
	},
});

appPageCached = Object.assign({}, conmmonConfig, {
	name: "appCached",
	entry: "./src/html/im.html",
	devtool: false,
	output: {
		filename: "appPageCached.js",
		path: path.resolve(__dirname, distPath, "."),
	},
	module: {
		loaders: [
			{
				test: /im\.html$/,
				loaders: [
					"file-loader?name=[name]_cached.[ext]",
					"extract-loader",
					"html-loader",
					"string-replace-loader"
						+ "?search=__STATIC_PATH__"
						+ "&replace=" + staticPath
						+ "&flags=g",
					"string-replace-loader"
						+ "?search=__WEBIM_PLUGIN_VERSION__"
						+ "&replace=" + VERSION
						+ "&flags=g",
				],
			},
		],
	},
});

taskList = [
	transfer,
	easemob,
	app,
	appPageCached,
];

module.exports = taskList;
<commit_msg>ver pre_47.26.0<commit_after>/*
	以下文件老版本会引用到，不能在服务器上彻底删除

	/static/js/em-open.js
	/static/js/em-transfer.js
*/
// todo: 优化构建速度
// todo: 减少重复构建

const path = require("path");
const webpack = require("webpack");
const i18next = require("i18next");
const _zh_cn_map_ = require("./src/i18n/zh-CN");
const _en_us_map_ = require("./src/i18n/en-US");
const VERSION = "pre_47.26.0";

const argv = require("yargs").argv;
const lang = argv.lang || "zh-CN";

var distPath = lang === "zh-CN" ? "" : lang;
var staticPath = lang === "zh-CN" ? "static" : "../static";
var conmmonConfig;
var transfer;
var easemob;
var app;
var appPageCached;
var taskList;

i18next.init({
	lng: lang,
	fallbackLng: false,
	keySeparator: ".",
	nsSeparator: false,
	saveMissing: true,
	resources: {
		"zh-CN": {
			translation: _zh_cn_map_,
		},
		"en-US": {
			translation: _en_us_map_,
		},
	},
});

conmmonConfig = {
	plugins: [
		new webpack.optimize.UglifyJsPlugin({
			compress: {
				warnings: false,
			},
			test: /\.js$/i,
			sourceMap: true,
			comments: false,
			mangle: {
				screw_ie8: false,
			},
		}),
	],
	devtool: "eval",
	module: {
		loaders: [
			{
				test: /easemob\.scss$/,
				loaders: [
					"ie8-style-loader?sourceMap=true",
					"postcss-loader?sourceMap=true",
					"sass-loader?sourceMap=true",
				],
			},
			{
				test: /im\.html$/,
				loaders: [
					"file-loader?name=../../[name].[ext]",
					"extract-loader",
					"html-loader",
					"string-replace-loader"
						+ "?search=__STATIC_PATH__"
						+ "&replace=" + staticPath
						+ "&flags=g",
				],
			},
			{
				test: /transfer\.html$/,
				loaders: [
					"file-loader?name=../../[name].[ext]",
					"extract-loader",
					"html-loader",
				],
			},
			{
				test: /im\.scss$/,
				loaders: [
					"file-loader?name=../css/[name].css",
					"extract-loader",
					"css-loader?sourceMap=true",
					"postcss-loader?sourceMap=true",
					"sass-loader?sourceMap=true&importLoader=true"
				],
			},
			{
				test: require.resolve("./src/js/app/sdk/webim.config.js"),
				loader: "expose-loader?WebIM"
			},
			{
				test: require.resolve("underscore"),
				loader: "expose-loader?_"
			},
			{
				test: require.resolve("./src/js/app/lib/modernizr.js"),
				loader: "expose-loader?Modernizr"
			},
			{
				test: [
					/init\.js$/,
					/userAPI\.js$/,
					/im\.html/,
					/iframe\.js/,
					/transfer\.html/,
				],
				loader: "string-replace-loader",
				query: {
					search: "__WEBIM_PLUGIN_VERSION__",
					replace: VERSION,
					flags: "g",
				},
			},
			{
				test: /\.js$/,
				loader: "i18next-loader",
				query: {
					quotes: "\"",
				},
			},
			// 字体文件
			{
				test: /\.(eot|svg|ttf|woff|woff2)$/,
				loader: "file-loader",
				query: {
					name: "../css/font/[name]-[hash:6].[ext]",
				},
			},
		],
	},
};

transfer = Object.assign({}, conmmonConfig, {
	name: "transfer",
	entry: [
		"./src/js/transfer/api.js",
		"./src/html/transfer.html",
	],
	output: {
		filename: "em-transfer.js",
		path: path.resolve(__dirname, "static/js"),
	},
});

easemob = Object.assign({}, conmmonConfig, {
	name: "easemob",
	entry: [
		"./src/js/common/polyfill",
		"./src/js/plugin/userAPI.js",
	],
	output: {
		filename: "easemob.js",
		path: path.resolve(__dirname, distPath, "."),
		// 不能用umd模块输出的原因是：
		// 监测到AMD Loader时只执行define，此时不会初始化模块，所以不会暴露到全局
		// library: 'easemob-kefu-webim-plugin',
		// libraryTarget: 'umd',
		// umdNamedDefine: true,
	},
});

app = Object.assign({}, conmmonConfig, {
	name: "app",
	entry: [
		"./src/js/app/modules/init.js",
		"./src/scss/im.scss",
		"./src/html/im.html",
	],
	output: {
		filename: "main.js",
		path: path.resolve(__dirname, distPath, "static/js"),
	},
});

appPageCached = Object.assign({}, conmmonConfig, {
	name: "appCached",
	entry: "./src/html/im.html",
	devtool: false,
	output: {
		filename: "appPageCached.js",
		path: path.resolve(__dirname, distPath, "."),
	},
	module: {
		loaders: [
			{
				test: /im\.html$/,
				loaders: [
					"file-loader?name=[name]_cached.[ext]",
					"extract-loader",
					"html-loader",
					"string-replace-loader"
						+ "?search=__STATIC_PATH__"
						+ "&replace=" + staticPath
						+ "&flags=g",
					"string-replace-loader"
						+ "?search=__WEBIM_PLUGIN_VERSION__"
						+ "&replace=" + VERSION
						+ "&flags=g",
				],
			},
		],
	},
});

taskList = [
	transfer,
	easemob,
	app,
	appPageCached,
];

module.exports = taskList;
<|endoftext|>


<commit_before>
var VNode = require('vtree/vnode');
var VText = require('vtree/vtext');
var diff = require('virtual-dom/diff');
var patch = require('virtual-dom/patch');
var createElement = require('virtual-dom/create-element');
var DataSet = require("data-set");
var Delegator = require("dom-delegator");

Elm.Native.Html = {};
Elm.Native.Html.make = function(elm) {
    elm.Native = elm.Native || {};
    elm.Native.Html = elm.Native.Html || {};
    if (elm.Native.Html.values) return elm.Native.Html.values;
    if ('values' in Elm.Native.Html)
        return elm.Native.Html.values = Elm.Native.Html.values;

    // This manages event listeners. Somehow...
    Delegator();

    var newElement = Elm.Graphics.Element.make(elm).newElement;
    var List = Elm.Native.List.make(elm);
    var eq = Elm.Native.Utils.make(elm).eq;

    function node(name, attributes, properties, contents) {
        return eventNode(name, attributes, properties, List.Nil, contents);
    }

    function eventNode(name, attributes, properties, handlers, contents) {
        var attrs = {};
        while (attributes.ctor !== '[]') {
            var attribute = attributes._0;
            attrs[attribute._0] = attribute._1;
            attributes = attributes._1;
        }
        var props = {};
        while (properties.ctor !== '[]') {
            var property = properties._0;
            props[property._0] = property._1;
            properties = properties._1;
        }
        attrs.style = props;
        while (handlers.ctor !== '[]') {
            var handler = handlers._0;
            attrs[handler.eventName] = DataSetHook(handler.eventHandler);
            handlers = handlers._1;
        }
        return new VNode(name, attrs, List.toArray(contents));
    }

    function on(name, coerce) {
        function createListener(handle, convert) {
            function eventHandler(event) {
                console.log(event);
                elm.notify(handle.id, convert(coerce(event)));
            }
            return {
                eventName: name,
                eventHandler: eventHandler
            };
        }
        return F2(createListener);
    }

    function DataSetHook(value) {
        if (!(this instanceof DataSetHook)) {
            return new DataSetHook(value);
        }

        this.value = value;
    }

    DataSetHook.prototype.hook = function (node, propertyName) {
        var ds = DataSet(node);
        ds[propertyName] = this.value;
    };

    function text(string) {
        return new VText(string);
    }

    function toElement(width, height, html) {
        return A3(newElement, width, height,
                  { ctor: 'Custom'
                  , type: 'evancz/elm-html'
                  , render: createElement
                  , update: update
                  , model: html
                  });
    }

    function update(node, oldModel, newModel) {
        var patches = diff(oldModel, newModel);
        node = patch(node, patches);
    }

    function lazyRef(fn, a) {
        function thunk() {
            return fn(a);
        }
        return new Thunk('ref', fn, [a], thunk, shouldUpdate_refEq);
    }

    function lazyRef2(fn, a, b) {
        function thunk() {
            return A2(fn, a, b);
        }
        return new Thunk('ref', fn, [a,b], thunk, shouldUpdate_refEq);
    }

    function lazyRef3(fn, a, b, c) {
        function thunk() {
            return A3(fn, a, b, c);
        }
        return new Thunk('ref', fn, [a,b,c], thunk, shouldUpdate_refEq);
    }

    function lazyStruct(fn, a) {
        function thunk() {
            return fn(a);
        }
        return new Thunk('struct', fn, [a], thunk, shouldUpdate_structEq);
    }

    function lazyStruct2(fn, a, b) {
        function thunk() {
            return A2(fn, a, b);
        }
        return new Thunk('struct', fn, [a,b], thunk, shouldUpdate_structEq);
    }

    function lazyStruct3(fn, a, b, c) {
        function thunk() {
            return A3(fn, a, b, c);
        }
        return new Thunk('struct', fn, [a,b,c], thunk, shouldUpdate_structEq);
    }

    function Thunk(kind, fn, args, thunk, shouldUpdate) {
        this.fn = fn;
        this.args = args;
        this.vnode = null;
        this.key = undefined;
        this.thunk = thunk;

        this.kind = kind;
        this.shouldUpdate = shouldUpdate;
    }

    Thunk.prototype.type = "immutable-thunk";
    Thunk.prototype.update = updateThunk;
    Thunk.prototype.init = initThunk;

    function shouldUpdate_refEq(current, previous) {
        if (current.kind !== previous.kind || current.fn !== previous.fn) {
            return true;
        }

        // if it's the same function, we know the number of args must match
        var cargs = current.args;
        var pargs = previous.args;

        for (var i = cargs.length; i--; ) {
            if (cargs[i] !== pargs[i]) {
                return true;
            }
        }

        return false;
    }

    function shouldUpdate_structEq(current, previous) {
        if (current.kind !== previous.kind || current.fn !== previous.fn) {
            return true;
        }

        // if it's the same function, we know the number of args must match
        var cargs = current.args;
        var pargs = previous.args;

        for (var i = cargs.length; i--; ) {
            if (eq(cargs[i], pargs[i])) {
                return true;
            }
        }

        return false;
    }

    function updateThunk(previous, domNode) {
        if (!this.shouldUpdate(this, previous)) {
            this.vnode = previous.vnode;
            return;
        }

        if (!this.vnode) {
            this.vnode = this.thunk();
        }

        var patches = diff(previous.vnode, this.vnode);
        patch(domNode, patches);
    }

    function initThunk() {
        this.vnode = this.thunk();
        return createElement(this.vnode);
    }

    return Elm.Native.Html.values = {
        node: F4(node),
        eventNode: F5(eventNode),
        text: text,
        on: F2(on),
        lazyRef : F2(lazyRef ),
        lazyRef2: F3(lazyRef2),
        lazyRef3: F4(lazyRef3),
        lazyStruct : F2(lazyStruct ),
        lazyStruct2: F3(lazyStruct2),
        lazyStruct3: F4(lazyStruct3),
        toElement: F3(toElement)
    };
};
<commit_msg>Get rid of events in the native parts for now<commit_after>
var VNode = require('vtree/vnode');
var VText = require('vtree/vtext');
var diff = require('virtual-dom/diff');
var patch = require('virtual-dom/patch');
var createElement = require('virtual-dom/create-element');

Elm.Native.Html = {};
Elm.Native.Html.make = function(elm) {
    elm.Native = elm.Native || {};
    elm.Native.Html = elm.Native.Html || {};
    if (elm.Native.Html.values) return elm.Native.Html.values;
    if ('values' in Elm.Native.Html)
        return elm.Native.Html.values = Elm.Native.Html.values;

    var newElement = Elm.Graphics.Element.make(elm).newElement;
    var List = Elm.Native.List.make(elm);
    var eq = Elm.Native.Utils.make(elm).eq;

    function node(name, attributes, properties, contents) {
        var attrs = {};
        while (attributes.ctor !== '[]') {
            var attribute = attributes._0;
            attrs[attribute._0] = attribute._1;
            attributes = attributes._1;
        }
        var props = {};
        while (properties.ctor !== '[]') {
            var property = properties._0;
            props[property._0] = property._1;
            properties = properties._1;
        }
        attrs.style = props;
        return new VNode(name, attrs, List.toArray(contents));
    }

    function DataSetHook(value) {
        if (!(this instanceof DataSetHook)) {
            return new DataSetHook(value);
        }

        this.value = value;
    }

    DataSetHook.prototype.hook = function (node, propertyName) {
        var ds = DataSet(node);
        ds[propertyName] = this.value;
    };

    function text(string) {
        return new VText(string);
    }

    function toElement(width, height, html) {
        return A3(newElement, width, height,
                  { ctor: 'Custom'
                  , type: 'evancz/elm-html'
                  , render: createElement
                  , update: update
                  , model: html
                  });
    }

    function update(node, oldModel, newModel) {
        var patches = diff(oldModel, newModel);
        node = patch(node, patches);
    }

    function lazyRef(fn, a) {
        function thunk() {
            return fn(a);
        }
        return new Thunk('ref', fn, [a], thunk, shouldUpdate_refEq);
    }

    function lazyRef2(fn, a, b) {
        function thunk() {
            return A2(fn, a, b);
        }
        return new Thunk('ref', fn, [a,b], thunk, shouldUpdate_refEq);
    }

    function lazyRef3(fn, a, b, c) {
        function thunk() {
            return A3(fn, a, b, c);
        }
        return new Thunk('ref', fn, [a,b,c], thunk, shouldUpdate_refEq);
    }

    function lazyStruct(fn, a) {
        function thunk() {
            return fn(a);
        }
        return new Thunk('struct', fn, [a], thunk, shouldUpdate_structEq);
    }

    function lazyStruct2(fn, a, b) {
        function thunk() {
            return A2(fn, a, b);
        }
        return new Thunk('struct', fn, [a,b], thunk, shouldUpdate_structEq);
    }

    function lazyStruct3(fn, a, b, c) {
        function thunk() {
            return A3(fn, a, b, c);
        }
        return new Thunk('struct', fn, [a,b,c], thunk, shouldUpdate_structEq);
    }

    function Thunk(kind, fn, args, thunk, shouldUpdate) {
        this.fn = fn;
        this.args = args;
        this.vnode = null;
        this.key = undefined;
        this.thunk = thunk;

        this.kind = kind;
        this.shouldUpdate = shouldUpdate;
    }

    Thunk.prototype.type = "immutable-thunk";
    Thunk.prototype.update = updateThunk;
    Thunk.prototype.init = initThunk;

    function shouldUpdate_refEq(current, previous) {
        if (current.kind !== previous.kind || current.fn !== previous.fn) {
            return true;
        }

        // if it's the same function, we know the number of args must match
        var cargs = current.args;
        var pargs = previous.args;

        for (var i = cargs.length; i--; ) {
            if (cargs[i] !== pargs[i]) {
                return true;
            }
        }

        return false;
    }

    function shouldUpdate_structEq(current, previous) {
        if (current.kind !== previous.kind || current.fn !== previous.fn) {
            return true;
        }

        // if it's the same function, we know the number of args must match
        var cargs = current.args;
        var pargs = previous.args;

        for (var i = cargs.length; i--; ) {
            if (eq(cargs[i], pargs[i])) {
                return true;
            }
        }

        return false;
    }

    function updateThunk(previous, domNode) {
        if (!this.shouldUpdate(this, previous)) {
            this.vnode = previous.vnode;
            return;
        }

        if (!this.vnode) {
            this.vnode = this.thunk();
        }

        var patches = diff(previous.vnode, this.vnode);
        patch(domNode, patches);
    }

    function initThunk() {
        this.vnode = this.thunk();
        return createElement(this.vnode);
    }

    return Elm.Native.Html.values = {
        node: F4(node),
        text: text,
        lazyRef : F2(lazyRef ),
        lazyRef2: F3(lazyRef2),
        lazyRef3: F4(lazyRef3),
        lazyStruct : F2(lazyStruct ),
        lazyStruct2: F3(lazyStruct2),
        lazyStruct3: F4(lazyStruct3),
        toElement: F3(toElement)
    };
};
<|endoftext|>