Fix module generation

This commit is contained in:
atomiks
2018-11-11 03:20:06 +11:00
parent d096fc0fcb
commit c5f349e136
2 changed files with 130 additions and 80 deletions

View File

@ -1,7 +1,7 @@
/*
Builds the `_30s` module.
*/
// Load modules
/**
* Builds the `_30s` module in UMD and ESM formats.
* Also builds the test module file for testing snippets.
*/
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
@ -9,110 +9,159 @@ const util = require('./util');
const { rollup } = require('rollup');
const babel = require('rollup-plugin-babel');
const minify = require('rollup-plugin-babel-minify');
// Set variables for paths
const MODULE_NAME = '_30s';
const SNIPPETS_PATH = './snippets';
const SNIPPETS_ARCHIVE_PATH = './snippets_archive';
const IMPORTS = './imports.js';
const TEST_PACKAGE = './test/_30s.js';
const MODULE_NAME = '_30s';
const DIST = './dist';
// Regex for selecting code blocks
const codeRE = /```\s*js([\s\S]*?)```/;
// Read snippets, build packages
(async() => {
// Start the timer of the script
const DIST_PATH = './dist';
const ROLLUP_INPUT_FILE = './imports.temp.js';
const TEST_MODULE_FILE = './test/_30s.js';
const CODE_RE = /```\s*js([\s\S]*?)```/;
/**
* Returns the raw markdown string.
*/
function getRawSnippetString(snippetPath, snippet) {
return fs.readFileSync(path.join(snippetPath, snippet), 'utf8');
}
/**
* Returns the JavaScript code from the raw markdown string.
*/
function getCode(rawSnippetString) {
return rawSnippetString.match(CODE_RE)[1].replace('\n', '');
}
/**
* Builds the UMD + ESM files to the ./dist directory.
*/
async function doRollup() {
// Plugins
const es5 = babel({ presets: ['@babel/preset-env'] });
const min = minify({ comments: false });
const output = format => file => ({
format,
file,
name: MODULE_NAME
});
const umd = output('umd');
const esm = output('es');
const bundle = await rollup({ input: ROLLUP_INPUT_FILE });
const bundleES5 = await rollup({ input: ROLLUP_INPUT_FILE, plugins: [es5] });
const bundleES5Min = await rollup({
input: ROLLUP_INPUT_FILE,
plugins: [es5, min]
});
const baseName = `${DIST_PATH}/${MODULE_NAME}`;
// UMD ES2018
await bundle.write(umd(`${baseName}.js`));
// ESM ES2018
await bundle.write(esm(`${baseName}.esm.js`));
// UMD ES5
await bundleES5.write(umd(`${baseName}.es5.js`));
// UMD ES5 min
await bundleES5Min.write(umd(`${baseName}.es5.min.js`));
}
/**
* Starts the build process.
*/
async function build() {
console.time('Packager');
let requires = [];
let esmExportString = '';
let cjsExportString = '';
try {
const tagDatabase = fs.readFileSync('tag_database', 'utf8');
const nodeSnippets = tagDatabase.split('\n').filter(v => v.search(/:.*node/g) !== -1).map(v => v.slice(0, v.indexOf(':')));
if (!fs.existsSync(DIST_PATH)) fs.mkdirSync(DIST_PATH);
fs.writeFileSync(ROLLUP_INPUT_FILE, '');
fs.writeFileSync(TEST_MODULE_FILE, '');
// All the snippets that are Node.js-based and will break in a browser
// environment
const nodeSnippets = fs
.readFileSync('tag_database', 'utf8')
.split('\n')
.filter(v => v.search(/:.*node/g) !== -1)
.map(v => v.slice(0, v.indexOf(':')));
const snippets = fs.readdirSync(SNIPPETS_PATH);
const snippetExports = `module.exports = {${snippets.map(v => v.replace('.md', '')).join(',')}}`;
let requires = [];
let importData = '';
const archivedSnippets = fs.readdirSync(SNIPPETS_ARCHIVE_PATH).filter(v => v !== 'README.md');
const testExports = `module.exports = {${[...snippets, ...archivedSnippets].map(v => v.replace('.md', '')).join(',')}}`;
// Create `temp` and `dist` folders if they don't already exist.
if (!fs.existsSync(DIST)) fs.mkdirSync(DIST);
// Write `imports.js`
fs.writeFileSync(IMPORTS, '');
fs.writeFileSync(TEST_PACKAGE, '');
const archivedSnippets = fs
.readdirSync(SNIPPETS_ARCHIVE_PATH)
.filter(v => v !== 'README.md');
snippets.forEach(snippet => {
const snippetData = fs.readFileSync(path.join(SNIPPETS_PATH, snippet), 'utf8');
const rawSnippetString = getRawSnippetString(SNIPPETS_PATH, snippet);
const snippetName = snippet.replace('.md', '');
let code = snippetData.match(codeRE)[1].replace('\n', '');
let code = getCode(rawSnippetString);
if (nodeSnippets.includes(snippetName)) {
requires.push(code.match(/const.*=.*require\(([^\)]*)\);/g));
code = code.replace(/const.*=.*require\(([^\)]*)\);/g, '');
}
importData += code;
esmExportString += `export ${code}`;
cjsExportString += code;
});
// Write the data to the imports file
requires = [...new Set(requires.filter(Boolean).map(v => v[0].replace('require(', 'typeof require !== "undefined" && require(')))].join('\n');
fs.writeFileSync(IMPORTS, `${requires}\n\n${importData}\n\n${snippetExports}`);
archivedSnippets.forEach(snippet => {
const snippetData = fs.readFileSync(path.join(SNIPPETS_ARCHIVE_PATH, snippet), 'utf8');
let code = snippetData.match(codeRE)[1].replace('\n', '');
importData += code;
const rawSnippetString = getRawSnippetString(
SNIPPETS_ARCHIVE_PATH,
snippet
);
cjsExportString += getCode(rawSnippetString);
});
fs.writeFileSync(TEST_PACKAGE, `${requires}\n\n${importData}\n\n${testExports}`);
requires = [
...new Set(
requires
.filter(Boolean)
.map(v =>
v[0].replace(
'require(',
'typeof require !== "undefined" && require('
)
)
)
].join('\n');
fs.writeFileSync(ROLLUP_INPUT_FILE, `${requires}\n\n${esmExportString}`);
const testExports = `module.exports = {${[...snippets, ...archivedSnippets]
.map(v => v.replace('.md', ''))
.join(',')}}`;
fs.writeFileSync(
TEST_MODULE_FILE,
`${requires}\n\n${cjsExportString}\n\n${testExports}`
);
// Check Travis builds - Will skip builds on Travis if not CRON/API
if (util.isTravisCI() && util.isNotTravisCronOrAPI()) {
fs.unlink(IMPORTS);
fs.unlink(ROLLUP_INPUT_FILE);
console.log(
`${chalk.green('NOBUILD')} Module build terminated, not a cron job or a custom build!`
`${chalk.green(
'NOBUILD'
)} Module build terminated, not a cron job or a custom build!`
);
console.timeEnd('Packager');
process.exit(0);
}
// Write to the proper files and start the `rollup` script
const es5 = babel({
presets: ['@babel/preset-env']
});
const min = minify({ comments: false });
const bundle = await rollup({ input: IMPORTS });
// UMD ES2018
await bundle.write({
file: `${DIST}/${MODULE_NAME}.js`,
name: MODULE_NAME,
format: 'umd'
});
// ESM ES2018
await bundle.write({
file: `${DIST}/${MODULE_NAME}.esm.js`,
name: MODULE_NAME,
format: 'es'
});
// UMD ES5
const bundleES5 = await rollup({ input: IMPORTS, plugins: [es5] });
await bundleES5.write({
file: `${DIST}/${MODULE_NAME}.es5.js`,
name: MODULE_NAME,
format: 'umd'
});
// UMD ES5 min
const bundleES5Min = await rollup({
input: IMPORTS,
plugins: [es5, min]
});
await bundleES5Min.write({
file: `${DIST}/${MODULE_NAME}.es5.min.js`,
name: MODULE_NAME,
format: 'umd'
});
await doRollup();
// Clean up the temporary input file Rollup used for building the module
fs.unlink(ROLLUP_INPUT_FILE);
// Clean up temporary data
fs.unlink(IMPORTS);
// Log a success message
console.log(`${chalk.green('SUCCESS!')} Snippet module built!`);
// Log the time taken
console.timeEnd('Packager');
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During module creation: ${err}`);
process.exit(1);
}
})();
}
build();