Build system updates (#839)
* Add 'remove' and 'splice' actions * Destructure * Clone values applied to the schema * Move manifest modifications * Use clone * Fix destructure * Add support for inheritance * Create build function * Add createVariantManifest * Add support for command line arguments * Enable argument passing when using the build scripts
This commit is contained in:
parent
19e1f33b3f
commit
e9d6c4cc92
2
build.sh
2
build.sh
@ -1,2 +1,2 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
npm run-script build
|
npm run-script build -- "$@"
|
||||||
|
181
dev/build.js
181
dev/build.js
@ -23,6 +23,10 @@ const util = require('./yomichan-util');
|
|||||||
const {getAllFiles, getDefaultManifestAndVariants, createManifestString} = util;
|
const {getAllFiles, getDefaultManifestAndVariants, createManifestString} = util;
|
||||||
|
|
||||||
|
|
||||||
|
function clone(value) {
|
||||||
|
return JSON.parse(JSON.stringify(value));
|
||||||
|
}
|
||||||
|
|
||||||
async function createZip(directory, outputFileName, sevenZipExes=[], onUpdate=null) {
|
async function createZip(directory, outputFileName, sevenZipExes=[], onUpdate=null) {
|
||||||
for (const exe of sevenZipExes) {
|
for (const exe of sevenZipExes) {
|
||||||
try {
|
try {
|
||||||
@ -71,27 +75,27 @@ async function createJSZip(directory, outputFileName, onUpdate) {
|
|||||||
fs.writeFileSync(outputFileName, data, {encoding: null, flag: 'w'});
|
fs.writeFileSync(outputFileName, data, {encoding: null, flag: 'w'});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createModifiedManifest(manifest, modifications) {
|
function applyModifications(manifest, modifications) {
|
||||||
manifest = JSON.parse(JSON.stringify(manifest));
|
|
||||||
|
|
||||||
if (Array.isArray(modifications)) {
|
if (Array.isArray(modifications)) {
|
||||||
for (const modification of modifications) {
|
for (const modification of modifications) {
|
||||||
const {action, path: path2} = modification;
|
const {action, path: path2} = modification;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'set':
|
case 'set':
|
||||||
{
|
{
|
||||||
|
const {value: newValue} = modification;
|
||||||
const value = getObjectProperties(manifest, path2, path2.length - 1);
|
const value = getObjectProperties(manifest, path2, path2.length - 1);
|
||||||
const last = path2[path2.length - 1];
|
const last = path2[path2.length - 1];
|
||||||
value[last] = modification.value;
|
value[last] = clone(newValue);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'replace':
|
case 'replace':
|
||||||
{
|
{
|
||||||
|
const {pattern, patternFlags, replacement} = modification;
|
||||||
const value = getObjectProperties(manifest, path2, path2.length - 1);
|
const value = getObjectProperties(manifest, path2, path2.length - 1);
|
||||||
const regex = new RegExp(modification.pattern, modification.patternFlags);
|
const regex = new RegExp(pattern, patternFlags);
|
||||||
const last = path2[path2.length - 1];
|
const last = path2[path2.length - 1];
|
||||||
let value2 = value[last];
|
let value2 = value[last];
|
||||||
value2 = `${value2}`.replace(regex, modification.replacement);
|
value2 = `${value2}`.replace(regex, replacement);
|
||||||
value[last] = value2;
|
value[last] = value2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -102,6 +106,22 @@ function createModifiedManifest(manifest, modifications) {
|
|||||||
delete value[last];
|
delete value[last];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'remove':
|
||||||
|
{
|
||||||
|
const {item} = modification;
|
||||||
|
const value = getObjectProperties(manifest, path2, path2.length);
|
||||||
|
const index = value.indexOf(item);
|
||||||
|
if (index >= 0) { value.splice(index, 1); }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'splice':
|
||||||
|
{
|
||||||
|
const {start, deleteCount, items} = modification;
|
||||||
|
const value = getObjectProperties(manifest, path2, path2.length);
|
||||||
|
const itemsNew = items.map((v) => clone(v));
|
||||||
|
value.splice(start, deleteCount, ...itemsNew);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,14 +136,35 @@ function getObjectProperties(object, path2, count) {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getInheritanceChain(variant, variantMap) {
|
||||||
|
const visited = new Set();
|
||||||
|
const inheritance = [];
|
||||||
|
while (true) {
|
||||||
|
const {name, inherit} = variant;
|
||||||
|
if (visited.has(name)) { break; }
|
||||||
|
|
||||||
async function main() {
|
visited.add(name);
|
||||||
const {manifest, variants} = getDefaultManifestAndVariants();
|
inheritance.unshift(variant);
|
||||||
|
|
||||||
const rootDir = path.join(__dirname, '..');
|
if (typeof inherit !== 'string') { break; }
|
||||||
const extDir = path.join(rootDir, 'ext');
|
|
||||||
const buildDir = path.join(rootDir, 'builds');
|
const nextVariant = variantMap.get(inherit);
|
||||||
const manifestPath = path.join(extDir, 'manifest.json');
|
if (typeof nextVariant === 'undefined') { break; }
|
||||||
|
|
||||||
|
variant = nextVariant;
|
||||||
|
}
|
||||||
|
return inheritance;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createVariantManifest(manifest, variant, variantMap) {
|
||||||
|
let modifiedManifest = clone(manifest);
|
||||||
|
for (const {modifications} of getInheritanceChain(variant, variantMap)) {
|
||||||
|
modifiedManifest = applyModifications(modifiedManifest, modifications);
|
||||||
|
}
|
||||||
|
return modifiedManifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function build(manifest, buildDir, extDir, manifestPath, variantMap, variantNames) {
|
||||||
const sevenZipExes = ['7za', '7z'];
|
const sevenZipExes = ['7za', '7z'];
|
||||||
|
|
||||||
// Create build directory
|
// Create build directory
|
||||||
@ -131,7 +172,6 @@ async function main() {
|
|||||||
fs.mkdirSync(buildDir, {recursive: true});
|
fs.mkdirSync(buildDir, {recursive: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const onUpdate = (metadata) => {
|
const onUpdate = (metadata) => {
|
||||||
let message = `Progress: ${metadata.percent.toFixed(2)}%`;
|
let message = `Progress: ${metadata.percent.toFixed(2)}%`;
|
||||||
if (metadata.currentFile) {
|
if (metadata.currentFile) {
|
||||||
@ -143,30 +183,111 @@ async function main() {
|
|||||||
process.stdout.write(message);
|
process.stdout.write(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
for (const variantName of variantNames) {
|
||||||
for (const variant of variants) {
|
const variant = variantMap.get(variantName);
|
||||||
const {name, fileName, fileCopies, modifications} = variant;
|
if (typeof variant === 'undefined') { continue; }
|
||||||
process.stdout.write(`Building ${name}...\n`);
|
|
||||||
|
|
||||||
const fileNameSafe = path.basename(fileName);
|
const {name, fileName, fileCopies} = variant;
|
||||||
const modifiedManifest = createModifiedManifest(manifest, modifications);
|
process.stdout.write(`Building ${name}...\n`);
|
||||||
const fullFileName = path.join(buildDir, fileNameSafe);
|
|
||||||
fs.writeFileSync(manifestPath, createManifestString(modifiedManifest));
|
|
||||||
await createZip(extDir, fullFileName, sevenZipExes, onUpdate);
|
|
||||||
|
|
||||||
if (Array.isArray(fileCopies)) {
|
const modifiedManifest = createVariantManifest(manifest, variant, variantMap);
|
||||||
for (const fileName2 of fileCopies) {
|
|
||||||
const fileName2Safe = path.basename(fileName2);
|
const fileNameSafe = path.basename(fileName);
|
||||||
fs.copyFileSync(fullFileName, path.join(buildDir, fileName2Safe));
|
const fullFileName = path.join(buildDir, fileNameSafe);
|
||||||
}
|
fs.writeFileSync(manifestPath, createManifestString(modifiedManifest));
|
||||||
|
await createZip(extDir, fullFileName, sevenZipExes, onUpdate);
|
||||||
|
|
||||||
|
if (Array.isArray(fileCopies)) {
|
||||||
|
for (const fileName2 of fileCopies) {
|
||||||
|
const fileName2Safe = path.basename(fileName2);
|
||||||
|
fs.copyFileSync(fullFileName, path.join(buildDir, fileName2Safe));
|
||||||
}
|
}
|
||||||
|
|
||||||
process.stdout.write('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process.stdout.write('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getArs(args, argMap) {
|
||||||
|
let key = null;
|
||||||
|
let canKey = true;
|
||||||
|
let onKey = false;
|
||||||
|
for (const arg of args) {
|
||||||
|
onKey = false;
|
||||||
|
|
||||||
|
if (canKey && arg.startsWith('--')) {
|
||||||
|
if (arg.length === 2) {
|
||||||
|
canKey = false;
|
||||||
|
key = null;
|
||||||
|
onKey = false;
|
||||||
|
} else {
|
||||||
|
key = arg.substring(2);
|
||||||
|
onKey = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = argMap.get(key);
|
||||||
|
if (typeof target === 'boolean') {
|
||||||
|
argMap.set(key, true);
|
||||||
|
key = null;
|
||||||
|
} else if (typeof target === 'number') {
|
||||||
|
argMap.set(key, target + 1);
|
||||||
|
key = null;
|
||||||
|
} else if (target === null || typeof target === 'string') {
|
||||||
|
if (!onKey) {
|
||||||
|
argMap.set(key, arg);
|
||||||
|
key = null;
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(target)) {
|
||||||
|
if (!onKey) {
|
||||||
|
target.push(arg);
|
||||||
|
key = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(`Unknown argument: ${arg}`);
|
||||||
|
key = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return argMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const argv = process.argv.slice(2);
|
||||||
|
const args = getArs(argv, new Map([
|
||||||
|
['all', false],
|
||||||
|
['default', false],
|
||||||
|
['manifest', null],
|
||||||
|
[null, []]
|
||||||
|
]));
|
||||||
|
|
||||||
|
const {manifest, variants} = getDefaultManifestAndVariants();
|
||||||
|
|
||||||
|
const rootDir = path.join(__dirname, '..');
|
||||||
|
const extDir = path.join(rootDir, 'ext');
|
||||||
|
const buildDir = path.join(rootDir, 'builds');
|
||||||
|
const manifestPath = path.join(extDir, 'manifest.json');
|
||||||
|
|
||||||
|
const variantMap = new Map();
|
||||||
|
for (const variant of variants) {
|
||||||
|
variantMap.set(variant.name, variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const variantNames = (argv.length === 0 || args.get('all') ? variants.map(({name}) => name) : args.get(null));
|
||||||
|
await build(manifest, buildDir, extDir, manifestPath, variantMap, variantNames);
|
||||||
} finally {
|
} finally {
|
||||||
// Restore manifest
|
// Restore manifest
|
||||||
|
let restoreManifest = manifest;
|
||||||
|
if (!args.get('default') && args.get('manifest') !== null) {
|
||||||
|
const variant = variantMap.get(args.get('manifest'));
|
||||||
|
if (typeof variant !== 'undefined') {
|
||||||
|
restoreManifest = createVariantManifest(manifest, variant, variantMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
process.stdout.write('Restoring manifest...\n');
|
process.stdout.write('Restoring manifest...\n');
|
||||||
fs.writeFileSync(manifestPath, createManifestString(manifest));
|
fs.writeFileSync(manifestPath, createManifestString(restoreManifest));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user