Skip to content

Commit e3cd132

Browse files
authored
Merge pull request #737 from mathjax/build-tools
Update build tools to work with extensions better
2 parents 611a48c + fd90884 commit e3cd132

File tree

4 files changed

+107
-71
lines changed

4 files changed

+107
-71
lines changed

components/bin/build

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ const EXPORT_PROCESS = ['let', 'const', 'var', 'function', 'class', 'namespace']
4343
/**
4444
* The relative path to the MathJax directory
4545
*/
46-
const mjPath = path.relative(process.cwd(), path.resolve(__dirname,'../../js'));
46+
const mjPath = path.relative(process.cwd(), path.resolve(__dirname, '..', '..', 'js'));
47+
const mjGlobal = path.join('..', mjPath, 'components', 'global.js');
4748

4849
/**
4950
* Read the configuration for the component
@@ -53,14 +54,14 @@ const config = JSON.parse(fs.readFileSync(process.argv[2] || 'build.json'));
5354
/**
5455
* Extract the configuration values
5556
*/
57+
const COMPONENT = path.basename(config.component || 'part'); // name of the component
5658
const TARGETS = config.targets || []; // the files to include in the component
5759
const EXCLUDE = new Map((config.exclude || []).map(name => [name, true])); // files to exclude from the component
58-
const EXCLUDESUBDIRS = config.excludeSubdirs === 'true'; // exclude subdirectories
59-
const MATHJAX = config.js || config.mathjax || mjPath; // path to the compiled .js files
60+
const EXCLUDESUBDIRS = config.excludeSubdirs === 'true'; // exclude subdirectories or not
61+
const JS = config.js || config.mathjax || mjPath; // path to the compiled .js files
6062
const LIB = config.lib || './lib'; // path to the lib directory to create
61-
const COMPONENT = path.basename(config.component || 'part'); // name of the component
62-
const GLOBAL = config.global || `../${MATHJAX}/components/global.js`; // the location of global.js
63-
const SRC = config.ts || MATHJAX.replace(/js$/, 'ts'); // path to the .ts files
63+
const GLOBAL = config.global || mjGlobal; // path to the global.js file
64+
const TS = config.ts || JS.replace(/js$/, 'ts'); // path to the .ts files
6465

6566
/**
6667
* The list of files that need to be added to the lib directory
@@ -160,17 +161,15 @@ function processLines(file, objects) {
160161
if (objects.length === 0) return [];
161162
const dir = path.dirname(file).replace(/^\.$/, '');
162163
const dots = dir.replace(/[^\/]+/g, '..') || '.';
163-
const relative = path.join(dots, '..', MATHJAX, dir, path.basename(file)).replace(/\.ts$/, '.js');
164+
const relative = path.join(dots, '..', JS, dir, path.basename(file)).replace(/\.ts$/, '.js');
164165
const name = path.parse(file).name;
165166
const lines = [
166167
'"use strict";',
167168
`Object.defineProperty(exports, '__esModule', {value: true});`
168169
];
169-
let source = (dir.replace(/\//g, '.') + '.' + name).replace(/^\./, '')
170+
let source = ((dir.replace(/\//g, '.') + '.' + name).replace(/^\./, '')
171+
+ (exists(path.resolve(JS, file.replace(/\.ts$/, ''))) ? '_ts' : ''))
170172
.replace(/\.[^.]*/g, (x) => (x.substr(1).match(/[^a-zA-Z_]/) ? '[\'' + x.substr(1) + '\']' : x));
171-
if (exists(path.resolve(MATHJAX, file.replace(/\.ts$/, '')))) {
172-
source += '_ts';
173-
}
174173
for (const id of objects) {
175174
lines.push(`exports.${id} = MathJax._.${source}.${id};`);
176175
}
@@ -273,11 +272,11 @@ function processPackage(lines, space, dir) {
273272
if (path.dirname(PACKAGE[0]) === dir) {
274273
const file = PACKAGE.shift();
275274
const name = path.basename(file);
276-
const relativefile = path.join('..', MATHJAX, dir, name).replace(/\.ts$/, '.js');
275+
const relativefile = path.join('..', JS, dir, name).replace(/\.ts$/, '.js');
277276
const component = 'module' + (++importCount);
278277
lines.push(`import * as ${component} from '${relativefile}';`);
279278
let property = name.replace(/\.ts$/, '');
280-
if (property !== name && exists(path.resolve(MATHJAX, file.replace(/\.ts$/, '')))) {
279+
if (property !== name && exists(path.resolve(JS, file.replace(/\.ts$/, '')))) {
281280
property += '_ts';
282281
}
283282
if (property.match(/[^a-zA-Z0-9_]/)) {
@@ -324,5 +323,5 @@ function rmDir(dir) {
324323
//
325324
rmDir(LIB);
326325
console.info("Processing:");
327-
processList(SRC, '', TARGETS);
326+
processList(TS, '', TARGETS);
328327
processGlobal();

components/bin/makeAll

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,20 @@ const fs = require('fs');
2929
const path = require('path');
3030
const {execSync} = require('child_process');
3131

32+
const options = {
33+
recursive: true
34+
};
35+
3236
/**
33-
* Get the directories to process
37+
* Get the directories to process and check for options
3438
*/
3539
const dirs = process.argv.slice(2);
40+
41+
if (dirs[0] === '--no-subdirs') {
42+
dirs.shift();
43+
options.recursive = false;
44+
}
45+
3646
if (dirs.length === 0) {
3747
dirs.push('.');
3848
}
@@ -74,7 +84,9 @@ function processList(dirs) {
7484
*/
7585
function processDir(dir, action) {
7686
action(dir);
77-
processSubdirs(dir, action);
87+
if (options.recursive) {
88+
processSubdirs(dir, action);
89+
}
7890
}
7991

8092
/**

components/bin/pack

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function fileSize(file) {
4848
/**
4949
* Regular expressions for the components directory and the MathJax .js location
5050
*/
51-
const compRE = fileRegExp(path.join(path.dirname(__dirname), 'src'));
51+
const compRE = fileRegExp(path.dirname(__dirname));
5252
const rootRE = fileRegExp(path.join(path.dirname(path.dirname(__dirname)), 'js'));
5353
const nodeRE = fileRegExp(path.join(path.dirname(path.dirname(__dirname)), 'node_modules'));
5454

@@ -83,7 +83,7 @@ async function webpackLib(dir) {
8383
//
8484
// Get js directory from the webpack.config.js file
8585
//
86-
const jsdir = require(path.resolve(dir, 'webpack.config.js')).plugins[0].definitions.jsdir;
86+
const jsdir = require(path.resolve(dir, 'webpack.config.js')).plugins[0].definitions.__JSDIR__;
8787
const jsRE = fileRegExp(jsdir);
8888
const libRE = fileRegExp(path.resolve(jsdir, '..', 'components'));
8989

@@ -103,17 +103,27 @@ async function webpackLib(dir) {
103103
.replace(/ \+ \d+ modules/, '')
104104
.replace(dirRE, '.');
105105
}
106-
for (const module of modules.sort((a,b) => a.name < b.name ? -1 : 1)) {
106+
const list = [];
107+
for (const module of modules) {
107108
if (module.moduleType.match(/javascript/)) {
108-
const name = module.name
109-
.replace(compRE, '[components]')
110-
.replace(rootRE, '[mathjax]')
111-
.replace(nodeRE, '[node]')
112-
.replace(jsRE, '[js]')
113-
.replace(libRE, '[lib]');
114-
console.log(' ' + name + fileSize(module));
109+
let name = module.name
110+
.replace(compRE, '[components]')
111+
.replace(rootRE, '[mathjax]')
112+
.replace(nodeRE, '[node]')
113+
.replace(jsRE, '[js]')
114+
.replace(libRE, '[lib]');
115+
if (name.charAt(0) !== '.' && name.charAt(0) !== '[') {
116+
name = path.relative(dir, name);
117+
}
118+
list.push(' ' + name + fileSize(module));
115119
}
116120
}
121+
console.log(
122+
list
123+
.filter(a => a.slice(2, 4) === './').sort()
124+
.concat(list.filter(a => a.slice(2, 4) !== './').sort())
125+
.join('\n')
126+
);
117127
} catch (err) {
118128
console.error(err);
119129
}

components/webpack.common.js

Lines changed: 60 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,23 @@ function quoteRE(string) {
3636
return string.replace(/([\\.{}[\]()?*^$])/g, '\\$1')
3737
}
3838

39+
/**
40+
* Creates the plugin needed for including jsdir in the output
41+
*
42+
* @param {string} js The location of the compiled js files
43+
* @param {string} dir The directory of the component being built
44+
* @return {any[]} The plugin array (empty or with the conversion plugin)
45+
*/
46+
const PLUGINS = function (js, dir) {
47+
const mjdir = path.resolve(__dirname, '..', 'js');
48+
const jsdir = path.resolve(dir, js);
49+
50+
//
51+
// Record the js directory for the pack command
52+
//
53+
return [new webpack.DefinePlugin({__JSDIR__: jsdir})];
54+
};
55+
3956
/**
4057
* Creates the plugin needed for converting mathjax references to component/lib references
4158
*
@@ -44,62 +61,59 @@ function quoteRE(string) {
4461
* @param {string} dir The directory of the component being built
4562
* @return {any[]} The plugin array (empty or with the conversion plugin)
4663
*/
47-
const PLUGINS = function (js, libs, dir) {
64+
const RESOLVE = function (js, libs, dir) {
4865
const mjdir = path.resolve(__dirname, '..', 'js');
4966
const jsdir = path.resolve(dir, js);
5067
const mjRE = new RegExp('^(?:' + quoteRE(jsdir) + '|' + quoteRE(mjdir) + ')' + quoteRE(path.sep));
5168
const root = path.dirname(mjdir);
52-
const rootRE = new RegExp('^' + quoteRE(root + path.sep));
53-
const nodeRE = new RegExp('^' + quoteRE(path.dirname(root) + path.sep));
5469

5570
//
56-
// Record the js directory for the pack command
71+
// Add directory names to libraries
5772
//
58-
const plugins = [new webpack.DefinePlugin({jsdir: jsdir})];
73+
libs = libs.map(lib => path.join(lib.charAt(0) === '.' ? dir : root, lib) + path.sep);
5974

60-
if (libs.length) {
61-
plugins.push(
62-
//
63-
// Move mathjax references to component libraries
64-
//
65-
new webpack.NormalModuleReplacementPlugin(
66-
/^[^\/]/,
67-
function (resource) {
68-
const request = require.resolve(resource.request.charAt(0) === '.' ?
69-
path.resolve(resource.context, resource.request) :
70-
resource.request);
71-
if (!request.match(mjRE)) return;
72-
for (const lib of libs) {
73-
const file = request.replace(mjRE, path.join(root, lib) + path.sep);
74-
if (fs.existsSync(file)) {
75-
resource.request = file;
76-
break;
77-
}
78-
}
79-
}
80-
)
75+
//
76+
// Function replace imported files by ones in the specified component lib directories.
77+
//
78+
const replaceLibs = (resource) => {
79+
//
80+
// The full file name to check.
81+
//
82+
const request = require.resolve(
83+
resource.request ?
84+
resource.request.charAt(0) === '.' ? path.resolve(resource.path, resource.request) : resource.request :
85+
resource.path
8186
);
82-
}
83-
plugins.push(
8487
//
85-
// Check for packages that should be rerouted to node_modules
88+
// Only check files in the MathJax js directory.
8689
//
87-
new webpack.NormalModuleReplacementPlugin(
88-
/^[^\/]$/,
89-
function (resource) {
90-
const request = require.resolve(resource.request.charAt(0) === '.' ?
91-
path.resolve(resource.context, resource.request) :
92-
resource.request);
93-
if (request.match(rootRE) || !request.match(nodeRE) || fs.existsSync(request)) return;
94-
const file = request.replace(nodeRE, path.join(root, 'node_modules') + path.sep);
95-
if (fs.existsSync(file)) {
96-
resource.request = file;
97-
}
90+
if (!request.match(mjRE)) return;
91+
//
92+
// Loop through the libraries and see if the imported file is there.
93+
// If so, replace the request with the library version and return.
94+
//
95+
for (const lib of libs) {
96+
const file = request.replace(mjRE, lib);
97+
if (fs.existsSync(file)) {
98+
resource.path = file;
99+
resource.request = undefined;
100+
return;
98101
}
99-
)
100-
);
101-
return plugins;
102-
};
102+
}
103+
}
104+
105+
//
106+
// A plugin that looks for files and modules to see if they need replacing with library versions.
107+
//
108+
class ResolveReplacementPlugin {
109+
apply(compiler) {
110+
compiler.hooks.file.tap(ResolveReplacementPlugin.name, replaceLibs);
111+
compiler.hooks.module.tap(ResolveReplacementPlugin.name, replaceLibs);
112+
}
113+
}
114+
115+
return {plugins: [new ResolveReplacementPlugin()]};
116+
}
103117

104118
/**
105119
* Add babel-loader to appropriate directories
@@ -150,7 +164,8 @@ const PACKAGE = function (name, js, libs, dir, dist) {
150164
filename: name + (dist === '.' ? '.min.js' : '.js')
151165
},
152166
target: ['web', 'es5'], // needed for IE11 and old browsers
153-
plugins: PLUGINS(js, libs, dir),
167+
plugins: PLUGINS(js, dir),
168+
resolve: RESOLVE(js, libs, dir),
154169
module: MODULE(dir),
155170
performance: {
156171
hints: false

0 commit comments

Comments
 (0)