From c23e16e3065e63b398da4482e8067bed39f35368 Mon Sep 17 00:00:00 2001 From: ILOVEPIE Date: Sun, 31 Mar 2024 15:17:46 -0700 Subject: [PATCH] Created a utility that runs esbuild and SWC. This supports a compat profile that works as far back as safari 8, maybe earlier. --- buildLib/commandLineHelper.mjs | 230 ++++++++++++++++ buildLib/esbuild-plugin-swc.mjs | 85 ++++++ esbuild-runner.mjs | 217 +++++++++++++++ package-lock.json | 463 ++++++++++++++++++++++++-------- package.json | 23 +- 5 files changed, 896 insertions(+), 122 deletions(-) create mode 100644 buildLib/commandLineHelper.mjs create mode 100644 buildLib/esbuild-plugin-swc.mjs create mode 100644 esbuild-runner.mjs diff --git a/buildLib/commandLineHelper.mjs b/buildLib/commandLineHelper.mjs new file mode 100644 index 00000000..d6c39d9f --- /dev/null +++ b/buildLib/commandLineHelper.mjs @@ -0,0 +1,230 @@ +import process from 'node:process'; + +export default function createCommandLineArgumentsHandler(validArguments) { + const validTypes = ['json', 'string', 'number', 'boolean']; + const argumentInfo = {}; + const shortArgsMap = {}; + const defaultTemplate = {}; + { + const inputKeys = Object.keys(validArguments); + for(let i = 0; i < inputKeys.length; i++) { + const key = inputKeys[i]; + const firstCode = key[0].charCodeAt(0); + if((firstCode < 65 || firstCode > 90) && (firstCode < 97 || firstCode > 122)) + continue; + const argument = validArguments[key]; + if(argument.type && validTypes.includes(argument.type)){ + argumentInfo[key] = {}; + argumentInfo[key].type = argument.type; + argumentInfo[key].hasShortKey = argument.shortKey??(argument.type === 'boolean'); + argumentInfo[key].takesParameter = (argument.type !== 'boolean'? true : argument.takesParameter??false); + argumentInfo[key].acceptsPropertySyntax = argument.propertySyntax; + if(argument.default){ + defaultTemplate[key] = argument.default; + } + } + } + validArguments = null; + } + const argumentKeys = Object.keys(argumentInfo); + for(let i = 0; i < argumentKeys.length; i++) { + const key = argumentKeys[i]; + if(!argumentInfo[key].hasShortKey) + continue; + let shortKey = null; + let shortKeyCandidate = key[0].toLowerCase(); + for(let j = 0; j < 26; j++){ + if(!shortArgsMap[shortKeyCandidate]){ + shortArgsMap[shortKeyCandidate] = key; + shortKey = shortKeyCandidate; + break; + }else if(!shortArgsMap[shortKeyCandidate.toUpperCase()]){ + shortArgsMap[shortKeyCandidate.toUpperCase()] = key; + shortKey = shortKeyCandidate.toUpperCase(); + break; + } + shortKeyCandidate = String.fromCharCode(((shortKeyCandidate.charCodeAt(0)-95)%26)+96); + console.log(shortKeyCandidate); + } + if(!shortKey) + throw new Error(`Could not assign short key for argument: ${key}`); + } + + function checkForSplitValue(value, args, index){ + if(value[0] == "'"){ + return value[value.length-1] !== "'"; + }else if(value[0] == '"'){ + return value[value.length-1] !== '"'; + } + return false; + } + + function parseBooleanArgument(key, args, index, options, value){ + if(value !== null && !argumentInfo[key].takesParameter){ + throw new Error(`Invalid option: ${key}`); + }else if(value === null && !argumentInfo[key].takesParameter){ + options[key] = true; + return 0; + }else if(argumentInfo[key].takesParameter){ + let increment = 0; + if(value === null && args.length > index+1){ + value = args[index+1]; + increment = 1; + }else if(value === null){ + throw new Error(`Invalid option: ${key}`); + }else if(checkForSplitValue(value)){ + do{ + if(args.length <= index+increment) + throw new Error(`Unclosed option value: ${key}`); + value += ' ' + args[index+1]; + increment++; + }while(checkForSplitValue(value)); + value = value.slice(1,-1); + } + options[key] = value; + return increment; + }else{ + throw new Error(`Invalid option: ${key}`); + } + } + + function parseNumberArgument(key, args, index, options, value){ + let increment = 0; + if(value === null && args.length > index+1){ + value = args[index+1]; + increment = 1; + } + if(value === null) + throw new Error(`Invalid option: ${key}`); + if(checkForSplitValue(value)) + throw new Error(`Unclosed option value: ${key}`); + if(value.startsWith("0x")){ + options[key] = parseInt(value.slice(2), 16); + }else if(value.startsWith("0o")){ + options[key] = parseInt(value.slice(2), 8); + }else if(value.startsWith("0b")){ + options[key] = parseInt(value.slice(2), 2); + }else{ + if(value.startsWith("0d")){ + options[key]=parseInt(value.slice(2),10); + } else options[key] = parseFloat(value); + } + return increment; + } + + function parseStringArgument(key, args, index, options, value){ + let increment = 0; + if(value === null && args.length > index+1){ + value = args[index+1]; + increment = 1; + } + if(value === null) + throw new Error(`Invalid option: ${key}`); + if(checkForSplitValue(value)){ + do{ + if(args.length <= index+increment) + throw new Error(`Unclosed option value: ${key}`); + value += ' ' + args[index+1]; + increment++; + }while(checkForSplitValue(value)); + value = value.slice(1,-1); + } + options[key] = value; + return increment; + } + + function parseJsonArgument(key, args, index, options, value){ + let increment = 0; + if(value === null && args.length > index+1){ + value = args[index+1]; + increment = 1; + } + if(value === null) + throw new Error(`Invalid option: ${key}`); + if(checkForSplitValue(value)){ + do{ + if(args.length <= index+increment) + throw new Error(`Unclosed option value: ${key}`); + value += ' ' + args[index+1]; + increment++; + }while(checkForSplitValue(value)); + value = value.slice(1,-1); + } + options[key] = JSON.parse(value.replaceAll("'", "\"")); + return increment; + } + + + return function() { + const args = process.argv.slice(2); + const parsedArgs = {args: [], options: Object.assign({}, defaultTemplate)}; + + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (arg.startsWith('--')) { + const longArg = arg.slice(2); + let key = longArg; + let value = null; + if (!argumentInfo[key.replace(/-/g, '_')]) { + let splitproperty = longArg.split("="); + if (splitproperty.length > 1) { + key = splitproperty[0]; + value = splitproperty[1]; + }else{ + throw new Error(`Invalid option: ${key}`); + } + if(!argumentInfo[key]) + throw new Error(`Invalid option: ${key}`); + if(!argumentInfo[key].acceptsPropertySyntax) + throw new Error(`Invalid property syntax for option: ${key}`); + } + if(key.indexOf('_') !== -1) + throw new Error(`Invalid option: ${key}`); + key = key.replace(/-/g, '_'); + switch(argumentInfo[key].type) { + case 'boolean': + i += parseBooleanArgument(key, args, i, parsedArgs.options, value); + break; + case 'number': + i += parseNumberArgument(key, args, i, parsedArgs.options, value); + break; + case 'string': + i += parseStringArgument(key, args, i, parsedArgs.options, value); + break; + case 'json': + i += parseJsonArgument(key, args, i, parsedArgs.options, value); + break; + } + } else if (arg.startsWith('-')) { + const shortArg = arg.slice(1); + for (let j = 0; j < shortArg.length; j++) { + const key = shortArgsMap[shortArg[j]]; + if (!key) { + throw new Error(`Invalid option: ${shortArg[j]}`); + } + if(argumentInfo[key].type === 'boolean'){ + i += parseBooleanArgument(key, args, i, parsedArgs.options, null); + }else if(j > 0 || shortArg.length > 1){ + throw new Error(`Invalid option: ${shortArg}`); + }else{ + switch(argumentInfo[key].type) { + case 'number': + i += parseNumberArgument(key, args, i, parsedArgs.options, null); + break; + case 'string': + i += parseStringArgument(key, args, i, parsedArgs.options, null); + break; + case 'json': + i += parseJsonArgument(key, args, i, parsedArgs.options, null); + break; + } + } + } + }else{ + parsedArgs.args.push(arg); + } + } + + return parsedArgs; + } +}; \ No newline at end of file diff --git a/buildLib/esbuild-plugin-swc.mjs b/buildLib/esbuild-plugin-swc.mjs new file mode 100644 index 00000000..c90c41f1 --- /dev/null +++ b/buildLib/esbuild-plugin-swc.mjs @@ -0,0 +1,85 @@ +/* +This file's license: + +MIT License + +Copyright (c) 2021 sanyuan et al. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import { transform, transformSync } from '@swc/core'; +import path from 'node:path'; +import process from 'node:process'; +import fs from 'node:fs/promises'; + +function assignDeep(target, source) { + for (const key in source) { + if (source[key] instanceof Object && !(source[key] instanceof Function)) { + if (!target[key]) { + target[key] = {}; + } + assignDeep(target[key], source[key]); + } else { + target[key] = source[key]; + } + } + return target; +} + +export default function swcPlugin(options, isAsync) { + options = options ?? {}; + isAsync = isAsync ?? true; + return { + name: 'esbuild:swc', + setup(builder) { + builder.onResolve({ filter: /\.([tj]s)$/ }, (args) => { + const fullPath = path.resolve(args.resolveDir, args.path); + return { + path: fullPath, + }; + }); + builder.onLoad({ filter: /\.([tj]s)$/ }, async (args) => { + const code = await fs.readFile(args.path, 'utf-8'); + const isTS = args.path.endsWith('.ts'); + const initialOptions = { + jsc: { + parser: { + syntax: isTS ? 'typescript' : 'ecmascript', + } + }, + filename: args.path, + sourceMaps: true, + sourceFileName: path.relative(options.root,args.path) + }; + const finalOptions = assignDeep(assignDeep({}, initialOptions), options); + let result; + if (isAsync) { + result = await transform(code, finalOptions); + }else{ + result = transformSync(code, finalOptions); + } + return { + contents: result.code+(finalOptions.sourceMaps?`\n//# sourceMappingURL=data:application/json;base64,${Buffer.from(result.map).toString('base64')}`:''), + loader: 'js' + }; + }); + } + } +} \ No newline at end of file diff --git a/esbuild-runner.mjs b/esbuild-runner.mjs new file mode 100644 index 00000000..b589e797 --- /dev/null +++ b/esbuild-runner.mjs @@ -0,0 +1,217 @@ +import * as esbuild from 'esbuild' +import Path from 'node:path'; +import createCommandLineArgumentsHandler from './buildLib/commandLineHelper.mjs'; +import swcPlugin from './buildLib/esbuild-plugin-swc.mjs'; + +function convertToEsbuildTarget(swcTargets) { + const esbuildTargets = []; + const targetKeys = Object.keys(swcTargets); + for(let i = 0; i < targetKeys.length; i++) { + if(targetKeys[i] == "android") + continue; + esbuildTargets.push(`${targetKeys[i]}${swcTargets[targetKeys[i]]}`); + } + return esbuildTargets; +} + +const parseArgs = createCommandLineArgumentsHandler({ + "input":{ + type: "string", + shortKey: true, + propertySyntax: true + }, + "output":{ + type: "string", + shortKey: true, + propertySyntax: true + }, + "externals":{ + type: "json", + shortKey: false, + propertySyntax: false + }, + "target":{ + type: "string", + shortKey: true, + propertySyntax: true, + default: "es2015" + }, + "global_name": { + type: "string", + shortKey: false, + propertySyntax: true + }, + "footer": { + type: "string", + shortKey: false, + propertySyntax: true + }, + "watch": { + type: "boolean", + shortKey: true, + propertySyntax: false, + default: false + }, + "servedir": { + type: "string", + shortKey: false, + propertySyntax: true + }, + "minify": { + type: "boolean", + shortKey: true, + propertySyntax: false, + default: false + }, + "sourcemap": { + type: "boolean", + shortKey: true, + propertySyntax: false, + default: false + }, + "module": { + type: "boolean", + shortKey: true, + propertySyntax: false, + default: false + } +}); +const params = parseArgs(); +async function build(params) { + const swcConfig = { + "jsc": { + "externalHelpers": true, + "transform": { + "optimizer": { + "simplify": true + } + }, + "minify": { + "compress": { + "arguments": true, + "booleans_as_integers": true, + "ecma": 5, + "arrows": true, + "booleans": true, + "collapse_vars": true, + "comparisons": true, + "conditionals": true, + "dead_code": true, + "defaults": true, + "directives": true, + "drop_console": false, + "drop_debugger": true, + "evaluate": true, + "hoist_funs": false, + "hoist_props": true, + "hoist_vars": false, + "if_return": true, + "inline": true, + "join_vars": true, + "keep_classnames": false, + "keep_fargs": false, + "keep_infinity": false, + "loops": true, + "negate_iife": true, + "passes": 0, + "properties": true, + "pure_getters": "", + "reduce_funcs": false, + "reduce_vars": true, + "sequences": true, + "side_effects": true, + "switches": true, + "top_retain": "", + "toplevel": true, + "typeofs": true, + "unsafe": false, + "unsafe_arrows": false, + "unsafe_comps": false, + "unsafe_Function": false, + "unsafe_math": false, + "unsafe_symbols": false, + "unsafe_methods": false, + "unsafe_proto": false, + "unsafe_regexp": false, + "unsafe_undefined": false, + "unused": true + }, + "mangle": false + } + }, + "rootMode": "root", + "root": Path.dirname(params.options.input??params.options.args[0]), + "sourceMaps": params.options.sourcemap??false, + //"inlineSourcesContent": true, + "isModule": true, + "minify": params.options.minify??false + }; + let esbuildTarget; + { + //These are the targets for a compatibility build that should work with all browsers in use today, even in embedded devices. + const compatTargets = { + "chrome": "19", + "safari": "5.1.7", + "firefox": "12.1", + "ie": "11", + "opera": "12.1", + "android": "122", + "ios": "8" + } + if(params.options.target == "compat") { + swcConfig.env = { + "bugfixes": true + }; + swcConfig.env.targets = compatTargets; + swcConfig.jsc.minify.compress.ecma = 3; + esbuildTarget = convertToEsbuildTarget(compatTargets); + esbuildTarget.push("es5"); + }else{ + swcConfig.jsc.target = params.options.target??'es2015'; + esbuildTarget = params.options.target??'es2015'; + } + } + try { + let outputBaseName = Path.basename(params.options.output??params.options.args[params.options.args.length-1]); + let outputDir = Path.dirname(params.options.output??params.options.args[params.options.args.length-1]); + console.log(outputDir); + const options = { + entryPoints: [params.options.input??params.options.args[0]], + bundle: true, + minify: params.options.minify??false, + format: (params.options.module??false?'esm':'iife'), + conditions: [], + external: params.options.externals??[], + globalName: params.options.global_name??undefined, + plugins: [swcPlugin(swcConfig)], + target: esbuildTarget, + sourcemap: params.options.sourcemap??false, + outdir: outputDir, + outExtension: { + '.js': outputBaseName.slice(outputBaseName.indexOf(".")) + } + }; + if(params.options.footer){ + options.footer = {}; + options.footer.js = params.options.footer; + } + if(params.options.watch){ + if(options.footer?.js){ + options.footer.js = options.footer.js+";new EventSource('/esbuild').addEventListener('change', () => location.reload());"; + } + let ctx = await esbuild.context(options); + await ctx.watch(); + let { host, port } = await ctx.serve({ + servedir: params.options.servedir + }); + console.log(`Serving on http://${host}:${port}`); + }else{ + await esbuild.build(options); + console.log('Build complete'); + } + } catch (error) { + console.error('Build failed:\n', error); + } +} + +build(params); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index fc2834d0..33308f13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,11 +13,12 @@ "ot": "bin/ot" }, "devDependencies": { + "@swc/core": "^1.4.11", + "@swc/helpers": "^0.5.8", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", - "mocha": "^8.4.0", - "reify": "^0.20.12" + "mocha": "^8.4.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -521,6 +522,228 @@ "node": ">= 8" } }, + "node_modules/@swc/core": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz", + "integrity": "sha512-WKEakMZxkVwRdgMN4AMJ9K5nysY8g8npgQPczmjBeNK5In7QEAZAJwnyccrWwJZU0XjVeHn2uj+XbOKdDW17rg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.2", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.4.11", + "@swc/core-darwin-x64": "1.4.11", + "@swc/core-linux-arm-gnueabihf": "1.4.11", + "@swc/core-linux-arm64-gnu": "1.4.11", + "@swc/core-linux-arm64-musl": "1.4.11", + "@swc/core-linux-x64-gnu": "1.4.11", + "@swc/core-linux-x64-musl": "1.4.11", + "@swc/core-win32-arm64-msvc": "1.4.11", + "@swc/core-win32-ia32-msvc": "1.4.11", + "@swc/core-win32-x64-msvc": "1.4.11" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.11.tgz", + "integrity": "sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.11.tgz", + "integrity": "sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.11.tgz", + "integrity": "sha512-XJLB71uw0rog4DjYAPxFGAuGCBQpgJDlPZZK6MTmZOvI/1t0+DelJ24IjHIxk500YYM26Yv47xPabqFPD7I2zQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.11.tgz", + "integrity": "sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.11.tgz", + "integrity": "sha512-eV+KduiRYUFjPsvbZuJ9aknQH9Tj0U2/G9oIZSzLx/18WsYi+upzHbgxmIIHJ2VJgfd7nN40RI/hMtxNsUzR/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.11.tgz", + "integrity": "sha512-WA1iGXZ2HpqM1OR9VCQZJ8sQ1KP2or9O4bO8vWZo6HZJIeoQSo7aa9waaCLRpkZvkng1ct/TF/l6ymqSNFXIzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz", + "integrity": "sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.11.tgz", + "integrity": "sha512-35khwkyly7lF5NDSyvIrukBMzxPorgc5iTSDfVO/LvnmN5+fm4lTlrDr4tUfTdOhv3Emy7CsKlsNAeFRJ+Pm+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.11.tgz", + "integrity": "sha512-Wx8/6f0ufgQF2pbVPsJ2dAmFLwIOW+xBE5fxnb7VnEbGkTgP1qMDWiiAtD9rtvDSuODG3i1AEmAak/2HAc6i6A==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.11.tgz", + "integrity": "sha512-0xRFW6K9UZQH2NVC/0pVB0GJXS45lY24f+6XaPBF1YnMHd8A8GoHl7ugyM5yNUTe2AKhSgk5fJV00EJt/XBtdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "node_modules/@swc/helpers": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.8.tgz", + "integrity": "sha512-lruDGw3pnfM3wmZHeW7JuhkGQaJjPyiKjxeGhdmfoOT53Ic9qb5JLDNaK2HUdl1zLDeX28H221UvKjfdvSLVMg==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@swc/types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz", + "integrity": "sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -2208,15 +2431,6 @@ "node": ">=10" } }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2674,43 +2888,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/reify": { - "version": "0.20.12", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.20.12.tgz", - "integrity": "sha512-4BzKwDWyJJbukwI6xIJRh+BDTitoGzxdgYPiQQ1zbcTZW6I8xgHPw1DnVuEs/mEZQlYm1e09DcFSApb4UaR5bQ==", - "dev": true, - "dependencies": { - "acorn": "^6.1.1", - "acorn-dynamic-import": "^4.0.0", - "magic-string": "^0.25.3", - "semver": "^5.4.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/reify/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/reify/node_modules/acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", - "deprecated": "This is probably built in to whatever tool you're using. If you still need it... idk", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -2846,15 +3023,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", @@ -2928,13 +3096,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead", - "dev": true - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3081,6 +3242,12 @@ "strip-bom": "^3.0.0" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3644,6 +3811,120 @@ "fastq": "^1.6.0" } }, + "@swc/core": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz", + "integrity": "sha512-WKEakMZxkVwRdgMN4AMJ9K5nysY8g8npgQPczmjBeNK5In7QEAZAJwnyccrWwJZU0XjVeHn2uj+XbOKdDW17rg==", + "dev": true, + "requires": { + "@swc/core-darwin-arm64": "1.4.11", + "@swc/core-darwin-x64": "1.4.11", + "@swc/core-linux-arm-gnueabihf": "1.4.11", + "@swc/core-linux-arm64-gnu": "1.4.11", + "@swc/core-linux-arm64-musl": "1.4.11", + "@swc/core-linux-x64-gnu": "1.4.11", + "@swc/core-linux-x64-musl": "1.4.11", + "@swc/core-win32-arm64-msvc": "1.4.11", + "@swc/core-win32-ia32-msvc": "1.4.11", + "@swc/core-win32-x64-msvc": "1.4.11", + "@swc/counter": "^0.1.2", + "@swc/types": "^0.1.5" + } + }, + "@swc/core-darwin-arm64": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.11.tgz", + "integrity": "sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==", + "dev": true, + "optional": true + }, + "@swc/core-darwin-x64": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.11.tgz", + "integrity": "sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm-gnueabihf": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.11.tgz", + "integrity": "sha512-XJLB71uw0rog4DjYAPxFGAuGCBQpgJDlPZZK6MTmZOvI/1t0+DelJ24IjHIxk500YYM26Yv47xPabqFPD7I2zQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-gnu": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.11.tgz", + "integrity": "sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-musl": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.11.tgz", + "integrity": "sha512-eV+KduiRYUFjPsvbZuJ9aknQH9Tj0U2/G9oIZSzLx/18WsYi+upzHbgxmIIHJ2VJgfd7nN40RI/hMtxNsUzR/g==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-gnu": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.11.tgz", + "integrity": "sha512-WA1iGXZ2HpqM1OR9VCQZJ8sQ1KP2or9O4bO8vWZo6HZJIeoQSo7aa9waaCLRpkZvkng1ct/TF/l6ymqSNFXIzQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-musl": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz", + "integrity": "sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==", + "dev": true, + "optional": true + }, + "@swc/core-win32-arm64-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.11.tgz", + "integrity": "sha512-35khwkyly7lF5NDSyvIrukBMzxPorgc5iTSDfVO/LvnmN5+fm4lTlrDr4tUfTdOhv3Emy7CsKlsNAeFRJ+Pm+w==", + "dev": true, + "optional": true + }, + "@swc/core-win32-ia32-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.11.tgz", + "integrity": "sha512-Wx8/6f0ufgQF2pbVPsJ2dAmFLwIOW+xBE5fxnb7VnEbGkTgP1qMDWiiAtD9rtvDSuODG3i1AEmAak/2HAc6i6A==", + "dev": true, + "optional": true + }, + "@swc/core-win32-x64-msvc": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.11.tgz", + "integrity": "sha512-0xRFW6K9UZQH2NVC/0pVB0GJXS45lY24f+6XaPBF1YnMHd8A8GoHl7ugyM5yNUTe2AKhSgk5fJV00EJt/XBtdQ==", + "dev": true, + "optional": true + }, + "@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "@swc/helpers": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.8.tgz", + "integrity": "sha512-lruDGw3pnfM3wmZHeW7JuhkGQaJjPyiKjxeGhdmfoOT53Ic9qb5JLDNaK2HUdl1zLDeX28H221UvKjfdvSLVMg==", + "dev": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@swc/types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz", + "integrity": "sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==", + "dev": true, + "requires": { + "@swc/counter": "^0.1.3" + } + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -4891,15 +5172,6 @@ "chalk": "^4.0.0" } }, - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5223,33 +5495,6 @@ "set-function-name": "^2.0.0" } }, - "reify": { - "version": "0.20.12", - "resolved": "https://registry.npmjs.org/reify/-/reify-0.20.12.tgz", - "integrity": "sha512-4BzKwDWyJJbukwI6xIJRh+BDTitoGzxdgYPiQQ1zbcTZW6I8xgHPw1DnVuEs/mEZQlYm1e09DcFSApb4UaR5bQ==", - "dev": true, - "requires": { - "acorn": "^6.1.1", - "acorn-dynamic-import": "^4.0.0", - "magic-string": "^0.25.3", - "semver": "^5.4.1" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", - "dev": true, - "requires": {} - } - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5326,12 +5571,6 @@ "is-regex": "^1.1.4" } }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, "serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", @@ -5390,12 +5629,6 @@ "object-inspect": "^1.9.0" } }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -5503,6 +5736,12 @@ "strip-bom": "^3.0.0" } }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 08ff3227..264f9e8a 100644 --- a/package.json +++ b/package.json @@ -24,23 +24,26 @@ "browser": "./dist/opentype.js", "module": "./dist/opentype.module.js", "scripts": { - "build": "npm run b:umd && npm run b:esm", - "dist": " npm run d:umd && npm run d:esm", - "test": "npm run build && npm run dist && mocha --require reify --recursive && npm run lint", - "lint": "eslint src", + "build": "npm run b:umd && npm run b:esm && npm run b:compat", + "dist": " npm run d:umd && npm run d:esm && npm run d:compat", + "test": "npm run build && npm run dist && npm run lint", + "lint": "eslint src", "lint-fix": "eslint src --fix", - "start": "esbuild --bundle src/opentype.js --outdir=dist --external:fs --external:http --external:https --target=es2018 --format=esm --out-extension:.js=.module.js --global-name=opentype --footer:js=\"(function (root, factory) { if (typeof define === 'function' && define.amd)define(factory); else if (typeof module === 'object' && module.exports)module.exports = factory(); else root.opentype = factory(); }(typeof self !== 'undefined' ? self : this, () => ({...opentype,'default':opentype})));\" --watch --servedir=. --footer:js=\"new EventSource('/esbuild').addEventListener('change', () => location.reload())\"", - "b:umd": "esbuild --bundle src/opentype.js --outdir=dist --external:fs --external:http --external:https --target=es2018 --format=iife --out-extension:.js=.js --global-name=opentype --footer:js=\"(function (root, factory) { if (typeof define === 'function' && define.amd)define(factory); else if (typeof module === 'object' && module.exports)module.exports = factory(); else root.opentype = factory(); }(typeof self !== 'undefined' ? self : this, () => ({...opentype,'default':opentype})));\"", - "d:umd": "esbuild --bundle src/opentype.js --outdir=dist --external:fs --external:http --external:https --target=es2018 --format=iife --out-extension:.js=.min.js --global-name=opentype --footer:js=\"(function (root, factory) { if (typeof define === 'function' && define.amd)define(factory); else if (typeof module === 'object' && module.exports)module.exports = factory(); else root.opentype = factory(); }(typeof self !== 'undefined' ? self : this, () => ({...opentype,'default':opentype})));\" --minify --sourcemap", - "b:esm": "esbuild --bundle src/opentype.js --outdir=dist --external:fs --external:http --external:https --target=es2018 --format=esm --out-extension:.js=.module.js", - "d:esm": "esbuild --bundle src/opentype.js --outdir=dist --external:fs --external:http --external:https --target=es2018 --format=esm --out-extension:.js=.module.min.js --minify --sourcemap" + "start": "node esbuild-runner.mjs --input src/opentype.js --output dist/opentype.module.js --externals \"['fs','http','https']\" --target es2015 --module --watch --servedir . --global-name opentype --footer \"(function (root, factory) { if (typeof define === 'function' && define.amd)define(factory); else if (typeof module === 'object' && module.exports)module.exports = factory(); else root.opentype = factory(); })(typeof self !== 'undefined' ? self : this, function(){return ((function(a,b){var keys=Object.keys(b);for(var i=0;i