stylus/tools/build-vendor.js

184 lines
5.1 KiB
JavaScript
Raw Permalink Normal View History

'use strict';
const fetch = require('node-fetch');
const fs = require('fs');
const fse = require('fs-extra');
const glob = require('glob').sync;
const path = require('path');
const KEEP_DIRECTORIES = null;
const files = {
'codemirror': [
KEEP_DIRECTORIES,
'addon/comment/comment.js',
'addon/dialog',
'addon/edit/closebrackets.js',
'addon/edit/matchbrackets.js',
'addon/fold/brace-fold.js',
'addon/fold/comment-fold.js',
'addon/fold/foldcode.js',
'addon/fold/foldgutter.*',
'addon/fold/indent-fold.js',
'addon/hint/css-hint.js',
'addon/hint/show-hint.*',
'addon/lint/css-lint.js',
'addon/lint/json-lint.js',
'addon/lint/lint.*',
'addon/scroll/annotatescrollbar.js',
'addon/search/matchesonscrollbar.*',
'addon/search/searchcursor.js',
'addon/selection/active-line.js',
'keymap/*',
'lib/*',
'mode/css',
'mode/javascript',
'mode/stylus',
],
'jsonlint': [
'lib/jsonlint.js',
'README.md -> LICENSE',
],
'less-bundle': [
'dist/less.min.js',
],
'lz-string-unsafe': [
'lz-string-unsafe.min.js',
],
'stylelint-bundle': [
'dist/stylelint-bundle.min.js',
],
'stylus-lang-bundle': [
'dist/stylus-renderer.min.js',
],
'usercss-meta': [
2022-03-31 10:56:51 +00:00
'dist/usercss-meta.js',
],
'db-to-cloud': [
2022-03-31 10:56:51 +00:00
'dist/db-to-cloud.js',
],
'webext-launch-web-auth-flow': [
2022-03-31 10:56:51 +00:00
'dist/webext-launch-web-auth-flow.js',
],
'@eight04/draggable-list': [
2022-03-31 10:56:51 +00:00
'dist/draggable-list.iife.js',
],
};
main().catch(console.error);
async function main() {
fse.emptyDirSync('vendor');
await Promise.all(Object.keys(files).map(async pkg => {
console.log(`Building ${pkg}...`);
const pkgName = getFileName(pkg);
const flatPkg = pkg === pkgName || files[pkgName]
? pkg.replace(/\//g, '-')
: pkgName;
const res = await buildFiles(pkg, flatPkg, files[pkg]);
buildLicense(pkg, flatPkg);
buildReadme(pkg, flatPkg, res);
}));
console.log('Building CodeMirror theme list...');
buildThemeList();
}
async function buildFiles(pkg, flatPkg, patterns) {
const keepDirs = patterns.includes(KEEP_DIRECTORIES);
let fetched = '';
let copied = '';
for (let pattern of patterns) {
if (pattern === KEEP_DIRECTORIES) continue;
pattern = pattern.replace('{VERSION}', require(`${pkg}/package.json`).version);
const [src, dest = !keepDirs && getFileName(src)] = pattern.split(/\s*->\s*/);
if (/^https?:/.test(src)) {
const req = await fetch(src);
if (req.status >= 400) throw new Error(`Network error ${req.status} for ${src}`);
fse.outputFileSync(`vendor/${flatPkg}/${dest}`, await req.text());
fetched += `* ${dest}: ${src}\n`;
} else {
const files = glob(`node_modules/${pkg}/${src}`);
if (!files.length) {
throw new Error(`Pattern ${src} matches no files`);
}
for (const file of files) {
2022-03-31 10:56:51 +00:00
const destPath = dest
? `vendor/${flatPkg}/${dest}`
2022-03-31 10:56:51 +00:00
: `vendor/${path.relative('node_modules', file).replace(pkg + '/', flatPkg + '/')}`;
const txt = file.endsWith('.js') && fs.readFileSync(file, 'utf8');
const txt2 = txt && txt.replace(/\n\/\/# sourceMappingURL=.*\s*$/, '\n');
const hasSM = txt && txt !== txt2;
if (hasSM) {
fse.outputFileSync(destPath, txt2);
} else {
fse.copySync(file, destPath);
}
copied += `* ${reportFile(pkg, file, dest)}${hasSM ? ' (removed sourceMappingURL)' : ''}\n`;
}
}
}
return {fetched, copied};
}
function buildLicense(pkg, flatPkg) {
const LICENSE = `vendor/${flatPkg}/LICENSE`;
if (!fs.existsSync(LICENSE)) {
const [src] = glob(`node_modules/${pkg}/LICEN[SC]E*`);
if (!src) throw new Error(`Cannot find license file for ${pkg}`);
fse.copySync(src, LICENSE);
}
}
function buildReadme(pkg, flatPkg, {fetched, copied}) {
const {name, version} = require(`${pkg}/package.json`);
fse.outputFileSync(`vendor/${flatPkg}/README.md`, [
`## ${name} v${version}`,
fetched && `Files downloaded from URL:\n${fetched}`,
copied && `Files copied from NPM (node_modules):\n${copied}`,
].filter(Boolean).join('\n\n'));
}
function buildThemeList() {
fse.outputFileSync('edit/codemirror-themes.js', deindent(`\
/* Do not edit. This file is auto-generated by build-vendor.js */
2022-03-24 14:08:04 +00:00
/* eslint-disable max-len, quotes */
'use strict';
2022-03-24 14:08:04 +00:00
window.CODEMIRROR_THEMES = {
${
2022-03-24 14:08:04 +00:00
glob('node_modules/codemirror/theme/*.css')
.sort()
.map(f =>
` '${
f.match(/([^/.]+)\.css$/i)[1].replace(/'/g, '\\&$')
}': ${
JSON.stringify(fs.readFileSync(f, 'utf8'))
},`)
.join('\n')
}
2022-03-24 14:08:04 +00:00
};
`));
}
function deindent(str) {
const indent = str.match(/^\s*/)[0];
return indent
? str.replace(new RegExp('^' + indent, 'gm'), '')
: str;
}
function getFileName(path) {
return path.split('/').pop();
}
2022-01-14 15:46:03 +00:00
function reportFile(pkg, file, dest) {
file = path.relative(`node_modules/${pkg}`, file).replace(/\\/g, '/');
if (!dest || dest === file) {
return file;
}
if (file.includes('/') && getFileName(dest) === getFileName(file)) {
file = file.replace(/[^/]+$/, '*');
}
return `${dest}: ${file}`;
}