diff --git a/components/bin/build b/components/bin/build index 58f57cdcb..e045ddd0a 100755 --- a/components/bin/build +++ b/components/bin/build @@ -43,7 +43,8 @@ const EXPORT_PROCESS = ['let', 'const', 'var', 'function', 'class', 'namespace'] /** * The relative path to the MathJax directory */ -const mjPath = path.relative(process.cwd(), path.resolve(__dirname,'../../js')); +const mjPath = path.relative(process.cwd(), path.resolve(__dirname, '..', '..', 'js')); +const mjGlobal = path.join('..', mjPath, 'components', 'global.js'); /** * Read the configuration for the component @@ -53,14 +54,14 @@ const config = JSON.parse(fs.readFileSync(process.argv[2] || 'build.json')); /** * Extract the configuration values */ +const COMPONENT = path.basename(config.component || 'part'); // name of the component const TARGETS = config.targets || []; // the files to include in the component const EXCLUDE = new Map((config.exclude || []).map(name => [name, true])); // files to exclude from the component -const EXCLUDESUBDIRS = config.excludeSubdirs === 'true'; // exclude subdirectories -const MATHJAX = config.js || config.mathjax || mjPath; // path to the compiled .js files +const EXCLUDESUBDIRS = config.excludeSubdirs === 'true'; // exclude subdirectories or not +const JS = config.js || config.mathjax || mjPath; // path to the compiled .js files const LIB = config.lib || './lib'; // path to the lib directory to create -const COMPONENT = path.basename(config.component || 'part'); // name of the component -const GLOBAL = config.global || `../${MATHJAX}/components/global.js`; // the location of global.js -const SRC = config.ts || MATHJAX.replace(/js$/, 'ts'); // path to the .ts files +const GLOBAL = config.global || mjGlobal; // path to the global.js file +const TS = config.ts || JS.replace(/js$/, 'ts'); // path to the .ts files /** * The list of files that need to be added to the lib directory @@ -160,17 +161,15 @@ function processLines(file, objects) { if (objects.length === 0) return []; const dir = path.dirname(file).replace(/^\.$/, ''); const dots = dir.replace(/[^\/]+/g, '..') || '.'; - const relative = path.join(dots, '..', MATHJAX, dir, path.basename(file)).replace(/\.ts$/, '.js'); + const relative = path.join(dots, '..', JS, dir, path.basename(file)).replace(/\.ts$/, '.js'); const name = path.parse(file).name; const lines = [ '"use strict";', `Object.defineProperty(exports, '__esModule', {value: true});` ]; - let source = (dir.replace(/\//g, '.') + '.' + name).replace(/^\./, '') + let source = ((dir.replace(/\//g, '.') + '.' + name).replace(/^\./, '') + + (exists(path.resolve(JS, file.replace(/\.ts$/, ''))) ? '_ts' : '')) .replace(/\.[^.]*/g, (x) => (x.substr(1).match(/[^a-zA-Z_]/) ? '[\'' + x.substr(1) + '\']' : x)); - if (exists(path.resolve(MATHJAX, file.replace(/\.ts$/, '')))) { - source += '_ts'; - } for (const id of objects) { lines.push(`exports.${id} = MathJax._.${source}.${id};`); } @@ -273,11 +272,11 @@ function processPackage(lines, space, dir) { if (path.dirname(PACKAGE[0]) === dir) { const file = PACKAGE.shift(); const name = path.basename(file); - const relativefile = path.join('..', MATHJAX, dir, name).replace(/\.ts$/, '.js'); + const relativefile = path.join('..', JS, dir, name).replace(/\.ts$/, '.js'); const component = 'module' + (++importCount); lines.push(`import * as ${component} from '${relativefile}';`); let property = name.replace(/\.ts$/, ''); - if (property !== name && exists(path.resolve(MATHJAX, file.replace(/\.ts$/, '')))) { + if (property !== name && exists(path.resolve(JS, file.replace(/\.ts$/, '')))) { property += '_ts'; } if (property.match(/[^a-zA-Z0-9_]/)) { @@ -324,5 +323,5 @@ function rmDir(dir) { // rmDir(LIB); console.info("Processing:"); -processList(SRC, '', TARGETS); +processList(TS, '', TARGETS); processGlobal(); diff --git a/components/bin/makeAll b/components/bin/makeAll index 3e7a89144..df879f584 100755 --- a/components/bin/makeAll +++ b/components/bin/makeAll @@ -29,10 +29,20 @@ const fs = require('fs'); const path = require('path'); const {execSync} = require('child_process'); +const options = { + recursive: true +}; + /** - * Get the directories to process + * Get the directories to process and check for options */ const dirs = process.argv.slice(2); + +if (dirs[0] === '--no-subdirs') { + dirs.shift(); + options.recursive = false; +} + if (dirs.length === 0) { dirs.push('.'); } @@ -74,7 +84,9 @@ function processList(dirs) { */ function processDir(dir, action) { action(dir); - processSubdirs(dir, action); + if (options.recursive) { + processSubdirs(dir, action); + } } /** diff --git a/components/bin/pack b/components/bin/pack index ed8789ce4..d0a67b06a 100755 --- a/components/bin/pack +++ b/components/bin/pack @@ -48,7 +48,7 @@ function fileSize(file) { /** * Regular expressions for the components directory and the MathJax .js location */ -const compRE = fileRegExp(path.join(path.dirname(__dirname), 'src')); +const compRE = fileRegExp(path.dirname(__dirname)); const rootRE = fileRegExp(path.join(path.dirname(path.dirname(__dirname)), 'js')); const nodeRE = fileRegExp(path.join(path.dirname(path.dirname(__dirname)), 'node_modules')); @@ -83,7 +83,7 @@ async function webpackLib(dir) { // // Get js directory from the webpack.config.js file // - const jsdir = require(path.resolve(dir, 'webpack.config.js')).plugins[0].definitions.jsdir; + const jsdir = require(path.resolve(dir, 'webpack.config.js')).plugins[0].definitions.__JSDIR__; const jsRE = fileRegExp(jsdir); const libRE = fileRegExp(path.resolve(jsdir, '..', 'components')); @@ -103,17 +103,27 @@ async function webpackLib(dir) { .replace(/ \+ \d+ modules/, '') .replace(dirRE, '.'); } - for (const module of modules.sort((a,b) => a.name < b.name ? -1 : 1)) { + const list = []; + for (const module of modules) { if (module.moduleType.match(/javascript/)) { - const name = module.name - .replace(compRE, '[components]') - .replace(rootRE, '[mathjax]') - .replace(nodeRE, '[node]') - .replace(jsRE, '[js]') - .replace(libRE, '[lib]'); - console.log(' ' + name + fileSize(module)); + let name = module.name + .replace(compRE, '[components]') + .replace(rootRE, '[mathjax]') + .replace(nodeRE, '[node]') + .replace(jsRE, '[js]') + .replace(libRE, '[lib]'); + if (name.charAt(0) !== '.' && name.charAt(0) !== '[') { + name = path.relative(dir, name); + } + list.push(' ' + name + fileSize(module)); } } + console.log( + list + .filter(a => a.slice(2, 4) === './').sort() + .concat(list.filter(a => a.slice(2, 4) !== './').sort()) + .join('\n') + ); } catch (err) { console.error(err); } diff --git a/components/webpack.common.js b/components/webpack.common.js index a79504e35..8edfdd893 100644 --- a/components/webpack.common.js +++ b/components/webpack.common.js @@ -36,6 +36,23 @@ function quoteRE(string) { return string.replace(/([\\.{}[\]()?*^$])/g, '\\$1') } +/** + * Creates the plugin needed for including jsdir in the output + * + * @param {string} js The location of the compiled js files + * @param {string} dir The directory of the component being built + * @return {any[]} The plugin array (empty or with the conversion plugin) + */ +const PLUGINS = function (js, dir) { + const mjdir = path.resolve(__dirname, '..', 'js'); + const jsdir = path.resolve(dir, js); + + // + // Record the js directory for the pack command + // + return [new webpack.DefinePlugin({__JSDIR__: jsdir})]; +}; + /** * Creates the plugin needed for converting mathjax references to component/lib references * @@ -44,62 +61,59 @@ function quoteRE(string) { * @param {string} dir The directory of the component being built * @return {any[]} The plugin array (empty or with the conversion plugin) */ -const PLUGINS = function (js, libs, dir) { +const RESOLVE = function (js, libs, dir) { const mjdir = path.resolve(__dirname, '..', 'js'); const jsdir = path.resolve(dir, js); const mjRE = new RegExp('^(?:' + quoteRE(jsdir) + '|' + quoteRE(mjdir) + ')' + quoteRE(path.sep)); const root = path.dirname(mjdir); - const rootRE = new RegExp('^' + quoteRE(root + path.sep)); - const nodeRE = new RegExp('^' + quoteRE(path.dirname(root) + path.sep)); // - // Record the js directory for the pack command + // Add directory names to libraries // - const plugins = [new webpack.DefinePlugin({jsdir: jsdir})]; + libs = libs.map(lib => path.join(lib.charAt(0) === '.' ? dir : root, lib) + path.sep); - if (libs.length) { - plugins.push( - // - // Move mathjax references to component libraries - // - new webpack.NormalModuleReplacementPlugin( - /^[^\/]/, - function (resource) { - const request = require.resolve(resource.request.charAt(0) === '.' ? - path.resolve(resource.context, resource.request) : - resource.request); - if (!request.match(mjRE)) return; - for (const lib of libs) { - const file = request.replace(mjRE, path.join(root, lib) + path.sep); - if (fs.existsSync(file)) { - resource.request = file; - break; - } - } - } - ) + // + // Function replace imported files by ones in the specified component lib directories. + // + const replaceLibs = (resource) => { + // + // The full file name to check. + // + const request = require.resolve( + resource.request ? + resource.request.charAt(0) === '.' ? path.resolve(resource.path, resource.request) : resource.request : + resource.path ); - } - plugins.push( // - // Check for packages that should be rerouted to node_modules + // Only check files in the MathJax js directory. // - new webpack.NormalModuleReplacementPlugin( - /^[^\/]$/, - function (resource) { - const request = require.resolve(resource.request.charAt(0) === '.' ? - path.resolve(resource.context, resource.request) : - resource.request); - if (request.match(rootRE) || !request.match(nodeRE) || fs.existsSync(request)) return; - const file = request.replace(nodeRE, path.join(root, 'node_modules') + path.sep); - if (fs.existsSync(file)) { - resource.request = file; - } + if (!request.match(mjRE)) return; + // + // Loop through the libraries and see if the imported file is there. + // If so, replace the request with the library version and return. + // + for (const lib of libs) { + const file = request.replace(mjRE, lib); + if (fs.existsSync(file)) { + resource.path = file; + resource.request = undefined; + return; } - ) - ); - return plugins; -}; + } + } + + // + // A plugin that looks for files and modules to see if they need replacing with library versions. + // + class ResolveReplacementPlugin { + apply(compiler) { + compiler.hooks.file.tap(ResolveReplacementPlugin.name, replaceLibs); + compiler.hooks.module.tap(ResolveReplacementPlugin.name, replaceLibs); + } + } + + return {plugins: [new ResolveReplacementPlugin()]}; +} /** * Add babel-loader to appropriate directories @@ -150,7 +164,8 @@ const PACKAGE = function (name, js, libs, dir, dist) { filename: name + (dist === '.' ? '.min.js' : '.js') }, target: ['web', 'es5'], // needed for IE11 and old browsers - plugins: PLUGINS(js, libs, dir), + plugins: PLUGINS(js, dir), + resolve: RESOLVE(js, libs, dir), module: MODULE(dir), performance: { hints: false