diff --git a/.gitignore b/.gitignore index 40f3f8981..16977e7c0 100644 --- a/.gitignore +++ b/.gitignore @@ -164,4 +164,7 @@ pip-log.txt /lib /esm -node_modules \ No newline at end of file +node_modules + +# rollup visualizer +/stats.html \ No newline at end of file diff --git a/build/build.js b/build/build.js index 885fa5efc..6f80edf22 100644 --- a/build/build.js +++ b/build/build.js @@ -1,5 +1,6 @@ // const typescript = require('@rollup/plugin-typescript'); const typescript = require('rollup-plugin-typescript2'); +const replace = require('@rollup/plugin-replace'); const rollup = require('rollup'); const path = require('path'); const processs = require('process'); @@ -12,24 +13,34 @@ function current() { return (new Date()).toLocaleString(); } -const inputOption = { - input: path.resolve(__dirname, '../index.ts'), - plugins: [typescript({ - tsconfigOverride: { - compilerOptions: { - // Rollup don't use CommonJS by default. - module: 'ES2015', - sourceMap: true, - // Use the esm d.ts - declaration: false - } - } - }), progress({ - scope: { - total: 0 - } - })] -}; +function createInputOption(env, isWatch) { + return { + input: path.resolve(__dirname, '../index.ts'), + plugins: [ + typescript({ + clean: !isWatch, + tsconfigOverride: { + compilerOptions: { + // Rollup don't use CommonJS by default. + module: 'ES2015', + sourceMap: true, + // Use the esm d.ts + declaration: false + } + } + }), + replace({ + preventAssignment: true, + 'process.env.NODE_ENV': JSON.stringify(env) + }), + progress({ + scope: { + total: 0 + } + }) + ] + }; +} const outputOption = { format: 'umd', @@ -39,18 +50,17 @@ const outputOption = { }; function minify(outPath) { - const fileMinPath = outPath.replace(/.js$/, '.min.js'); const code = fs.readFileSync(outPath, 'utf-8'); const uglifyResult = UglifyJS.minify(code); if (uglifyResult.error) { throw new Error(uglifyResult.error); } - fs.writeFileSync(fileMinPath, uglifyResult.code, 'utf-8'); + fs.writeFileSync(outPath, uglifyResult.code, 'utf-8'); } if (processs.argv.includes('--watch')) { const watcher = rollup.watch({ - ...inputOption, + ...createInputOption('development', true), output: [outputOption], watch: { clearScreen: true @@ -83,13 +93,24 @@ if (processs.argv.includes('--watch')) { }); } else { + // Unminified rollup.rollup({ - ...inputOption + ...createInputOption('development', false) }).then(bundle => { - bundle.write(outputOption).then(function () { - if (process.argv.indexOf('--minify') >= 0) { - minify(outputOption.file); - } - }); + bundle.write(outputOption); }); + // Minified + if (process.argv.indexOf('--minify') >= 0) { + rollup.rollup({ + ...createInputOption('production', false) + }).then(bundle => { + const file = outputOption.file.replace(/.js$/, '.min.js'); + bundle.write(Object.assign(outputOption, { + file, + sourcemap: false + })).then(function () { + minify(file); + }); + }); + } } diff --git a/build/processLib.js b/build/processLib.js new file mode 100644 index 000000000..17d37d9be --- /dev/null +++ b/build/processLib.js @@ -0,0 +1,67 @@ +// Porcess generated lib files. +// Like adding js extension in the import statement. + +const { transformImport } = require('./transformImport'); +const globby = require('globby'); +const path = require('path'); +const fs = require('fs'); +const chalk = require('chalk'); +const rollup = require('rollup'); +const nodeResolve = require('@rollup/plugin-node-resolve').default; + +function addJsExtension(moduleName) { + // Ignore 'tslib' + if (!(moduleName.startsWith('.'))) { + return moduleName; + } + if (moduleName.endsWith('.ts')) { + // Replace ts with js + return moduleName.replace(/\.ts$/, '.js'); + } + else if (moduleName.endsWith('.js')) { + return moduleName; + } + else { + return moduleName + '.js' + } +} + +async function transform() { + const libFiles = await globby([ + '**/*.js' + ], { + cwd: path.join(__dirname, '../lib'), + absolute: true + }); + + if (libFiles.length === 0) { + throw new Error('No lib files found.') + } + + for (let file of libFiles) { + const code = fs.readFileSync(file, 'utf-8'); + fs.writeFileSync(file, transformImport(code, addJsExtension), 'utf-8'); + } + + // Transform index; + const indexFile = path.join(__dirname, '../index.js'); + fs.writeFileSync( + indexFile, + transformImport( + fs.readFileSync(indexFile, 'utf-8'), + (mduleName) => addJsExtension(mduleName).replace('./src', './lib') + ) + ) +} + +transform().then(() => { + console.log(chalk.green('Added .js extensions.')); + console.log(chalk.gray('Start testing generated libs...')); +}).then(() => { + return rollup.rollup({ + input: path.resolve(__dirname, '../index.js'), + plugins: [nodeResolve()] + }); +}).then(() => { + console.log(chalk.green('Libs can be bundled!')); +}); \ No newline at end of file diff --git a/build/transformImport.js b/build/transformImport.js new file mode 100644 index 000000000..58d6812dc --- /dev/null +++ b/build/transformImport.js @@ -0,0 +1,115 @@ +// adding js extension in the import statement. + +// Reference: +// https://regexr.com/47jlq +// https://gist.github.com/manekinekko/7e58a17bc62a9be47172 +const regexp = /((?:(?:import)|(?:export))\s+?(?:(?:(?:[\w*\s{},\/]*)\s+from\s+?)|))(?:(?:"(.*?)")|(?:'(.*?)'))([\s]*?(?:;|$|))/g; + +module.exports.transformImport = function (code, processModuleName) { + return code.replace(regexp, (str, prefix, moduleNameA, moduleNameB, postfix) => { + let moduleName = (moduleNameA === undefined ? moduleNameB : moduleNameA).trim(); + const quote = moduleNameA === undefined ? "'" : '"'; + return prefix + quote + processModuleName(moduleName) + quote + postfix; + // Not support other extensions. + }); +} + + +const testCases = `import videos from './videos/index.js' + +export default (socket, context) => { + // dynamically importing all the socket.io handler (it's dynamic import that happen at run time) + import { + something +} from "./test/okbb" + +const f = 2; + +import test from 'obb' + + +import { + Component +} from '@angular2/core'; + +import defaultMember from "module-0"; + +import * as name from "module-1 "; + +import { member } from " module-2"; + +import { member as alias } from "module-3"; + +import { member1 , member2 } from "module-4"; + +import { member1 , member2 as alias2 , member3 as alias3 } from "module-5"; + +import defaultMember, { member, member } from "module-6"; + +import defaultMember, * as name from "module-7"; + +import "module-8"; + +import "module-9" // comment no problem + +import { + AAAA, + // BBB +} from 'module-10'; + +import "module-b' // doesn't match -> the opening and closing quation mark are different + +importing hya from 'ttt' + +import fbsfrom '' + + +// Export expressions. +export { aaa }; + +export * from "module-11"; + +export { aaa } from "module-12"; + +// Should not be parsed +export default aaa; + +export function bbb () { +}; +` + +module.exports.runTest = function () { + const expected = [ + './videos/index.js', + './test/okbb', + 'obb', + '@angular2/core', + 'module-0', + 'module-1', + 'module-2', + 'module-3', + 'module-4', + 'module-5', + 'module-6', + 'module-7', + 'module-8', + 'module-9', + 'module-10', + 'module-11', + 'module-12' + ] + let cursor = 0; + module.exports.transformImport(testCases, (moduleName) => { + if (expected[cursor] !== moduleName) { + throw new Error(`Expected ${expected[cursor]}. Actual ${moduleName}`); + } + cursor++; + return moduleName; + }) + if (cursor !== expected.length) { + throw new Error('Test failed'); + } + console.log('All test passed!') +} + +// module.exports.runTest(); \ No newline at end of file diff --git a/index.d.ts b/index.d.ts index 047e18390..21fff2ecb 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,2 +1,2 @@ -export * from './lib/zrender'; -export * from './lib/export'; +export * from './src/zrender'; +export * from './src/export'; diff --git a/index.js b/index.js index a95f37b0a..256c4b514 100644 --- a/index.js +++ b/index.js @@ -1,8 +1 @@ -export * from './lib/zrender'; -export * from './lib/export'; - -import {registerPainter} from './lib/zrender'; -import CanvasPainter from './lib/canvas/Painter'; -import SVGPainter from './lib/svg/Painter'; -registerPainter('canvas', CanvasPainter); -registerPainter('svg', SVGPainter); +export * from './lib/all.js' \ No newline at end of file diff --git a/index.ts b/index.ts index 717166057..70a5e0a35 100644 --- a/index.ts +++ b/index.ts @@ -1,9 +1 @@ -export * from './src/zrender'; -export * from './src/export'; - -import {registerPainter} from './src/zrender'; -import CanvasPainter from './src/canvas/Painter'; -import SVGPainter from './src/svg/Painter'; -registerPainter('canvas', CanvasPainter); -registerPainter('svg', SVGPainter); -// import './src/vml/vml'; +export * from './lib/all'; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 36ab4dc2d..2aef283d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,46 +13,52 @@ "@babel/highlight": "^7.8.0" } }, + "@babel/compat-data": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "dev": true + }, "@babel/core": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", - "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.4", - "@babel/helpers": "^7.8.4", - "@babel/parser": "^7.8.4", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.4", - "@babel/types": "^7.8.3", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", + "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.15.8", + "@babel/generator": "^7.15.8", + "@babel/helper-compilation-targets": "^7.15.4", + "@babel/helper-module-transforms": "^7.15.8", + "@babel/helpers": "^7.15.4", + "@babel/parser": "^7.15.8", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.6", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.0", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", "source-map": "^0.5.0" }, "dependencies": { "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", "dev": true, "requires": { - "@babel/highlight": "^7.8.3" + "@babel/highlight": "^7.14.5" } }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, @@ -67,12 +73,6 @@ "supports-color": "^5.3.0" } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -91,14 +91,13 @@ } }, "@babel/generator": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", - "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", + "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", "dev": true, "requires": { - "@babel/types": "^7.8.3", + "@babel/types": "^7.15.6", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" }, "dependencies": { @@ -110,50 +109,147 @@ } } }, + "@babel/helper-compilation-targets": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", + "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.15.0", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.0" + } + }, "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", + "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-get-function-arity": "^7.15.4", + "@babel/template": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", + "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", + "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", + "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-module-imports": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", + "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", + "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.15.4", + "@babel/helper-replace-supers": "^7.15.4", + "@babel/helper-simple-access": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/helper-validator-identifier": "^7.15.7", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.6" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", + "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.15.4" } }, "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", "dev": true }, + "@babel/helper-replace-supers": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", + "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.15.4", + "@babel/helper-optimise-call-expression": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", + "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", + "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.15.4" } }, + "@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true + }, "@babel/helpers": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", - "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", + "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.4", - "@babel/types": "^7.8.3" + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/highlight": { @@ -190,11 +286,20 @@ } }, "@babel/parser": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", - "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", + "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", "dev": true }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, "@babel/plugin-syntax-bigint": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", @@ -204,6 +309,60 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", @@ -213,34 +372,70 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/template": { + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", + "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/template": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" }, "dependencies": { "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", "dev": true, "requires": { - "@babel/highlight": "^7.8.3" + "@babel/highlight": "^7.14.5" } }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, @@ -267,39 +462,39 @@ } }, "@babel/traverse": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", - "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.4", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.4", - "@babel/types": "^7.8.3", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", + "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.4", + "@babel/helper-function-name": "^7.15.4", + "@babel/helper-hoist-variables": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" + "globals": "^11.1.0" }, "dependencies": { "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", "dev": true, "requires": { - "@babel/highlight": "^7.8.3" + "@babel/highlight": "^7.14.5" } }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, @@ -326,13 +521,12 @@ } }, "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "version": "7.15.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", + "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", "dev": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", + "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" } }, @@ -342,32 +536,15 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@cnakazawa/watch": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", - "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", - "dev": true, - "requires": { - "exec-sh": "^0.3.2", - "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "@istanbuljs/load-nyc-config": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", - "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "requires": { "camelcase": "^5.3.1", "find-up": "^4.1.0", + "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" }, @@ -381,72 +558,166 @@ } }, "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, "@jest/console": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.1.0.tgz", - "integrity": "sha512-3P1DpqAMK/L07ag/Y9/Jup5iDEG9P4pRAuZiMQnU0JB3UOvCyYCjCoxr7sIA80SeyUCUKrr24fKAxVpmBgQonA==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.2.5.tgz", + "integrity": "sha512-smtlRF9vNKorRMCUtJ+yllIoiY8oFmfFG7xlzsAE76nKEwXNhjPOJIsc7Dv+AUitVt76t+KjIpUP9m98Crn2LQ==", "dev": true, "requires": { - "@jest/source-map": "^25.1.0", - "chalk": "^3.0.0", - "jest-util": "^25.1.0", + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.2.5", + "jest-util": "^27.2.5", "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "@jest/core": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-25.1.0.tgz", - "integrity": "sha512-iz05+NmwCmZRzMXvMo6KFipW7nzhbpEawrKrkkdJzgytavPse0biEnCNr2wRlyCsp3SmKaEY+SGv7YWYQnIdig==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.2.5.tgz", + "integrity": "sha512-VR7mQ+jykHN4WO3OvusRJMk4xCa2MFLipMS+43fpcRGaYrN1KwMATfVEXif7ccgFKYGy5D1TVXTNE4mGq/KMMA==", "dev": true, "requires": { - "@jest/console": "^25.1.0", - "@jest/reporters": "^25.1.0", - "@jest/test-result": "^25.1.0", - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", + "@jest/console": "^27.2.5", + "@jest/reporters": "^27.2.5", + "@jest/test-result": "^27.2.5", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", + "chalk": "^4.0.0", + "emittery": "^0.8.1", "exit": "^0.1.2", - "graceful-fs": "^4.2.3", - "jest-changed-files": "^25.1.0", - "jest-config": "^25.1.0", - "jest-haste-map": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-regex-util": "^25.1.0", - "jest-resolve": "^25.1.0", - "jest-resolve-dependencies": "^25.1.0", - "jest-runner": "^25.1.0", - "jest-runtime": "^25.1.0", - "jest-snapshot": "^25.1.0", - "jest-util": "^25.1.0", - "jest-validate": "^25.1.0", - "jest-watcher": "^25.1.0", - "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "realpath-native": "^1.1.0", + "graceful-fs": "^4.2.4", + "jest-changed-files": "^27.2.5", + "jest-config": "^27.2.5", + "jest-haste-map": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.2.5", + "jest-resolve-dependencies": "^27.2.5", + "jest-runner": "^27.2.5", + "jest-runtime": "^27.2.5", + "jest-snapshot": "^27.2.5", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", + "jest-watcher": "^27.2.5", + "micromatch": "^4.0.4", "rimraf": "^3.0.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "dependencies": { "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.21.3" } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, "rimraf": { @@ -459,156 +730,335 @@ } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } } } }, "@jest/environment": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-25.1.0.tgz", - "integrity": "sha512-cTpUtsjU4cum53VqBDlcW0E4KbQF03Cn0jckGPW/5rrE9tb+porD3+hhLtHAwhthsqfyF+bizyodTlsRA++sHg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.2.5.tgz", + "integrity": "sha512-XvUW3q6OUF+54SYFCgbbfCd/BKTwm5b2MGLoc2jINXQLKQDTCS2P2IrpPOtQ08WWZDGzbhAzVhOYta3J2arubg==", "dev": true, "requires": { - "@jest/fake-timers": "^25.1.0", - "@jest/types": "^25.1.0", - "jest-mock": "^25.1.0" + "@jest/fake-timers": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "jest-mock": "^27.2.5" } }, "@jest/fake-timers": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.1.0.tgz", - "integrity": "sha512-Eu3dysBzSAO1lD7cylZd/CVKdZZ1/43SF35iYBNV1Lvvn2Undp3Grwsv8PrzvbLhqwRzDd4zxrY4gsiHc+wygQ==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.2.5.tgz", + "integrity": "sha512-ZGUb6jg7BgwY+nmO0TW10bc7z7Hl2G/UTAvmxEyZ/GgNFoa31tY9/cgXmqcxnnZ7o5Xs7RAOz3G1SKIj8IVDlg==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.2.5", + "jest-mock": "^27.2.5", + "jest-util": "^27.2.5" + } + }, + "@jest/globals": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.2.5.tgz", + "integrity": "sha512-naRI537GM+enFVJQs6DcwGYPn/0vgJNb06zGVbzXfDfe/epDPV73hP1vqO37PqSKDeOXM2KInr6ymYbL1HTP7g==", "dev": true, "requires": { - "@jest/types": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-mock": "^25.1.0", - "jest-util": "^25.1.0", - "lolex": "^5.0.0" + "@jest/environment": "^27.2.5", + "@jest/types": "^27.2.5", + "expect": "^27.2.5" } }, "@jest/reporters": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-25.1.0.tgz", - "integrity": "sha512-ORLT7hq2acJQa8N+NKfs68ZtHFnJPxsGqmofxW7v7urVhzJvpKZG9M7FAcgh9Ee1ZbCteMrirHA3m5JfBtAaDg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.2.5.tgz", + "integrity": "sha512-zYuR9fap3Q3mxQ454VWF8I6jYHErh368NwcKHWO2uy2fwByqBzRHkf9j2ekMDM7PaSTWcLBSZyd7NNxR1iHxzQ==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^25.1.0", - "@jest/environment": "^25.1.0", - "@jest/test-result": "^25.1.0", - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", + "@jest/console": "^27.2.5", + "@jest/test-result": "^27.2.5", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.2", + "graceful-fs": "^4.2.4", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^4.0.3", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.0", - "jest-haste-map": "^25.1.0", - "jest-resolve": "^25.1.0", - "jest-runtime": "^25.1.0", - "jest-util": "^25.1.0", - "jest-worker": "^25.1.0", - "node-notifier": "^6.0.0", + "istanbul-reports": "^3.0.2", + "jest-haste-map": "^27.2.5", + "jest-resolve": "^27.2.5", + "jest-util": "^27.2.5", + "jest-worker": "^27.2.5", "slash": "^3.0.0", "source-map": "^0.6.0", - "string-length": "^3.1.0", + "string-length": "^4.0.1", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^4.0.1" + "v8-to-istanbul": "^8.1.0" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "jest-worker": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz", - "integrity": "sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", + "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", "dev": true, "requires": { + "@types/node": "*", "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } } } }, "@jest/source-map": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.1.0.tgz", - "integrity": "sha512-ohf2iKT0xnLWcIUhL6U6QN+CwFWf9XnrM2a6ybL9NXxJjgYijjLSitkYHIdzkd8wFliH73qj/+epIpTiWjRtAA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz", + "integrity": "sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.2.3", + "graceful-fs": "^4.2.4", "source-map": "^0.6.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + } } }, "@jest/test-result": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.1.0.tgz", - "integrity": "sha512-FZzSo36h++U93vNWZ0KgvlNuZ9pnDnztvaM7P/UcTx87aPDotG18bXifkf1Ji44B7k/eIatmMzkBapnAzjkJkg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.2.5.tgz", + "integrity": "sha512-ub7j3BrddxZ0BdSnM5JCF6cRZJ/7j3wgdX0+Dtwhw2Po+HKsELCiXUTvh+mgS4/89mpnU1CPhZxe2mTvuLPJJg==", "dev": true, "requires": { - "@jest/console": "^25.1.0", - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", + "@jest/console": "^27.2.5", + "@jest/types": "^27.2.5", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-25.1.0.tgz", - "integrity": "sha512-WgZLRgVr2b4l/7ED1J1RJQBOharxS11EFhmwDqknpknE0Pm87HLZVS2Asuuw+HQdfQvm2aXL2FvvBLxOD1D0iw==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.2.5.tgz", + "integrity": "sha512-8j8fHZRfnjbbdMitMAGFKaBZ6YqvFRFJlMJzcy3v75edTOqc7RY65S9JpMY6wT260zAcL2sTQRga/P4PglCu3Q==", "dev": true, "requires": { - "@jest/test-result": "^25.1.0", - "jest-haste-map": "^25.1.0", - "jest-runner": "^25.1.0", - "jest-runtime": "^25.1.0" + "@jest/test-result": "^27.2.5", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-runtime": "^27.2.5" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + } } }, "@jest/transform": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.1.0.tgz", - "integrity": "sha512-4ktrQ2TPREVeM+KxB4zskAT84SnmG1vaz4S+51aTefyqn3zocZUnliLLm5Fsl85I3p/kFPN4CRp1RElIfXGegQ==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.2.5.tgz", + "integrity": "sha512-29lRtAHHYGALbZOx343v0zKmdOg4Sb0rsA1uSv0818bvwRhs3TyElOmTVXlrw0v1ZTqXJCAH/cmoDXimBhQOJQ==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^25.1.0", + "@jest/types": "^27.2.5", "babel-plugin-istanbul": "^6.0.0", - "chalk": "^3.0.0", + "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.3", - "jest-haste-map": "^25.1.0", - "jest-regex-util": "^25.1.0", - "jest-util": "^25.1.0", - "micromatch": "^4.0.2", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-regex-util": "^27.0.6", + "jest-util": "^27.2.5", + "micromatch": "^4.0.4", "pirates": "^4.0.1", - "realpath-native": "^1.1.0", "slash": "^3.0.0", "source-map": "^0.6.1", "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + } } }, "@jest/types": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.1.0.tgz", - "integrity": "sha512-VpOtt7tCrgvamWZh1reVsGADujKigBUFTi19mlRjqEGsE8qH4r3s+skY33dNdXOwyZIvuftZ5tqdF1IgsMejMA==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0" + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "@microsoft/api-extractor": { @@ -729,24 +1179,106 @@ "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", - "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "dependencies": { + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + } + } + }, + "@rollup/plugin-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.0.0.tgz", + "integrity": "sha512-3c7JCbMuYXM4PbPWT4+m/4Y6U60SgsnDT/cCyAyUKwFHg7pTSfsSQzIpETha3a3ig6OdOKzZz87D9ZXIK3qsDg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + } + } + }, "@sinonjs/commons": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", - "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "requires": { "type-detect": "4.0.8" } }, + "@sinonjs/fake-timers": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.0.1.tgz", + "integrity": "sha512-AU7kwFxreVd6OAXcAFlKSmZquiRUU0FvYm44k1Y1QbK7Co4m0aqfGMhjykIeQp/H6rcl+nFmj0zfdUcGVs9Dew==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, "@types/argparse": { "version": "1.0.33", "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.33.tgz", @@ -754,9 +1286,9 @@ "dev": true }, "@types/babel__core": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.4.tgz", - "integrity": "sha512-c/5MuRz5HM4aizqL5ViYfW4iEnmfPcfbH4Xa6GgLT21dMc1NGeNnuS6egHheOmP+kCJ9CAzC4pv4SDCWTnRkbg==", + "version": "7.1.16", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz", + "integrity": "sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -767,18 +1299,18 @@ } }, "@types/babel__generator": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", - "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", + "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", "dev": true, "requires": { "@babel/types": "^7.0.0" } }, "@types/babel__template": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", - "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -786,9 +1318,9 @@ } }, "@types/babel__traverse": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz", - "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", + "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -806,10 +1338,19 @@ "integrity": "sha512-K1DPVvnBCPxzD+G51/cxVIoc2X8uUVl1zpJeE6iKcgHMj4+tbat5Xu4TjV7v2QSDbIeAfLi2hIk+u2+s0MlpUQ==", "dev": true }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", "dev": true }, "@types/istanbul-lib-report": { @@ -822,23 +1363,22 @@ } }, "@types/istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "*", "@types/istanbul-lib-report": "*" } }, "@types/jest": { - "version": "25.1.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-25.1.2.tgz", - "integrity": "sha512-EsPIgEsonlXmYV7GzUqcvORsSS9Gqxw/OvkGwHfAdpjduNRxMlhsav0O5Kb0zijc/eXSO/uW6SJt9nwull8AUQ==", + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.2.tgz", + "integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==", "dev": true, "requires": { - "jest-diff": "^25.1.0", - "pretty-format": "^25.1.0" + "jest-diff": "^27.0.0", + "pretty-format": "^27.0.0" } }, "@types/json-schema": { @@ -853,25 +1393,40 @@ "integrity": "sha512-Jg1F+bmxcpENHP23sVKkNuU3uaxPnsBMW0cLjleiikFKomJQbsn0Cqk2yDvQArqzZN6ABfBkZ0To7pQ8sLdWDg==", "dev": true }, + "@types/prettier": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.1.tgz", + "integrity": "sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw==", + "dev": true + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/stack-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", - "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "@types/yargs": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.3.tgz", - "integrity": "sha512-XCMQRK6kfpNBixHLyHUsGmXrpEmFFxzMrcnSXFMziHd8CoNJo8l16FkHyQq4x+xbM7E2XL83/O78OD8u+iZTdQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", - "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, "@typescript-eslint/eslint-plugin": { @@ -1021,6 +1576,12 @@ "tsutils": "^3.21.0" }, "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -1030,6 +1591,26 @@ "ms": "2.1.2" } }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -1101,6 +1682,15 @@ "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", @@ -1135,9 +1725,9 @@ } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -1153,24 +1743,6 @@ "sprintf-js": "~1.0.2" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, "array-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", @@ -1183,12 +1755,6 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -1204,12 +1770,6 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -1222,12 +1782,6 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -1241,18 +1795,61 @@ "dev": true }, "babel-jest": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-25.1.0.tgz", - "integrity": "sha512-tz0VxUhhOE2y+g8R2oFrO/2VtVjA1lkJeavlhExuRBg3LdNJY9gwQ+Vcvqt9+cqy71MCTJhewvTB7Qtnnr9SWg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.2.5.tgz", + "integrity": "sha512-GC9pWCcitBhSuF7H3zl0mftoKizlswaF0E3qi+rPL417wKkCB0d+Sjjb0OfXvxj7gWiBf497ldgRMii68Xz+2g==", "dev": true, "requires": { - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", - "@types/babel__core": "^7.1.0", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^25.1.0", - "chalk": "^3.0.0", + "babel-preset-jest": "^27.2.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + } } }, "babel-plugin-istanbul": { @@ -1269,23 +1866,45 @@ } }, "babel-plugin-jest-hoist": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.1.0.tgz", - "integrity": "sha512-oIsopO41vW4YFZ9yNYoLQATnnN46lp+MZ6H4VvPKFkcc2/fkl3CfE/NZZSmnEIEsJRmJAgkVEK0R7Zbl50CpTw==", + "version": "27.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.2.0.tgz", + "integrity": "sha512-TOux9khNKdi64mW+0OIhcmbAn75tTlzKhxmiNXevQaPbrBYK7YKjP1jl6NHTJ6XR5UgUrJbCnWlKVnJn29dfjw==", "dev": true, "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", "@types/babel__traverse": "^7.0.6" } }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, "babel-preset-jest": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-25.1.0.tgz", - "integrity": "sha512-eCGn64olaqwUMaugXsTtGAM2I0QTahjEtnRu0ql8Ie+gDWAc1N6wqN0k2NilnyTunM69Pad7gJY7LOtwLimoFQ==", + "version": "27.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.2.0.tgz", + "integrity": "sha512-z7MgQ3peBwN5L5aCqBKnF6iqdlvZvFUQynEhu0J+X9nHLU72jO3iY331lcYrg+AssJ8q7xsv5/3AICzVmJ/wvg==", "dev": true, "requires": { - "@babel/plugin-syntax-bigint": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "babel-plugin-jest-hoist": "^25.1.0" + "babel-plugin-jest-hoist": "^27.2.0", + "babel-preset-current-node-syntax": "^1.0.0" } }, "balanced-match": { @@ -1294,61 +1913,6 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -1383,21 +1947,17 @@ "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", "dev": true }, - "browser-resolve": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "browserslist": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.4.tgz", + "integrity": "sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ==", "dev": true, "requires": { - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } + "caniuse-lite": "^1.0.30001265", + "electron-to-chromium": "^1.3.867", + "escalade": "^3.1.1", + "node-releases": "^2.0.0", + "picocolors": "^1.0.0" } }, "bs-logger": { @@ -1419,27 +1979,16 @@ } }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } + "builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true }, "callsites": { "version": "3.1.0", @@ -1453,14 +2002,11 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, - "capture-exit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", - "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", - "dev": true, - "requires": { - "rsvp": "^4.8.4" - } + "caniuse-lite": { + "version": "1.0.30001267", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001267.tgz", + "integrity": "sha512-r1mjTzAuJ9W8cPBGbbus8E0SKcUP7gn03R14Wk8FlAlqhH9hroy9nLqmpuXlfKEw/oILW+FGz47ipXV2O7x8lg==", + "dev": true }, "caseless": { "version": "0.12.0", @@ -1505,6 +2051,12 @@ } } }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -1512,33 +2064,16 @@ "dev": true }, "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", + "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", "dev": true }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } + "cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true }, "cli-cursor": { "version": "2.1.0", @@ -1556,20 +2091,20 @@ "dev": true }, "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "wrap-ansi": "^7.0.0" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "emoji-regex": { @@ -1585,23 +2120,23 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } } } @@ -1613,21 +2148,11 @@ "dev": true }, "collect-v8-coverage": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.0.tgz", - "integrity": "sha512-VKIhJgvk8E1W28m5avZ2Gv2Ruv5YiF56ug2oclvaG9md69BuZImMG2sk9g7QNKLUbtYAKQjXjYxbYZVUlMMKmQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1670,12 +2195,6 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1683,9 +2202,9 @@ "dev": true }, "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -1699,12 +2218,6 @@ } } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1784,22 +2297,16 @@ "ms": "^2.1.1" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, "decimal.js": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.0.tgz", "integrity": "sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==", "dev": true }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, "deep-is": { @@ -1808,55 +2315,11 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true }, "delayed-stream": { "version": "1.0.0", @@ -1871,9 +2334,9 @@ "dev": true }, "diff-sequences": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.1.0.tgz", - "integrity": "sha512-nFIfVk5B/NStCsJ+zaPO4vYuLjlzQ6uFvPxzYyHlejNZ/UGa7G/n7peOXVrVNvRuyfstt+mZQYGpjxg9Z6N8Kw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", "dev": true }, "dir-glob": { @@ -1913,50 +2376,29 @@ "safer-buffer": "^2.1.0" } }, + "electron-to-chromium": { + "version": "1.3.870", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.870.tgz", + "integrity": "sha512-PiJMshfq6PL+i1V+nKLwhHbCKeD8eAz8rvO9Cwk/7cChOHJBtufmjajLyYLsSRHguRFiOCVx3XzJLeZsIAYfSA==", + "dev": true + }, + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", @@ -2136,120 +2578,111 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "exec-sh": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", - "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==", - "dev": true - }, "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "ms": "2.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "mimic-fn": "^2.1.0" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "shebang-regex": "^3.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, "expect": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-25.1.0.tgz", - "integrity": "sha512-wqHzuoapQkhc3OKPlrpetsfueuEiMf3iWh0R8+duCu9PIjXoP7HgD5aeypwTnXUAjC8aMsiVDaWwlbJ1RlQ38g==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.2.5.tgz", + "integrity": "sha512-ZrO0w7bo8BgGoP/bLz+HDCI+0Hfei9jUSZs5yI/Wyn9VkG9w8oJ7rHRgYj+MA7yqqFa0IwHA3flJzZtYugShJA==", "dev": true, "requires": { - "@jest/types": "^25.1.0", - "ansi-styles": "^4.0.0", - "jest-get-type": "^25.1.0", - "jest-matcher-utils": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-regex-util": "^25.1.0" + "@jest/types": "^27.2.5", + "ansi-styles": "^5.0.0", + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-regex-util": "^27.0.6" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true } } @@ -2260,27 +2693,6 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -2292,71 +2704,6 @@ "tmp": "^0.0.33" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -2370,17 +2717,27 @@ "dev": true }, "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } } }, "fast-json-stable-stringify": { @@ -2396,9 +2753,9 @@ "dev": true }, "fastq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", - "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -2478,12 +2835,6 @@ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2501,15 +2852,6 @@ "mime-types": "^2.1.12" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, "fs-extra": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", @@ -2528,9 +2870,9 @@ "dev": true }, "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, @@ -2547,9 +2889,9 @@ "dev": true }, "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "get-caller-file": { @@ -2558,19 +2900,16 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, "getpass": { @@ -2626,9 +2965,9 @@ }, "dependencies": { "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true } } @@ -2639,13 +2978,6 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, - "growly": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true, - "optional": true - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -2677,64 +3009,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "html-encoding-sniffer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.0.tgz", @@ -2745,11 +3019,22 @@ } }, "html-escaper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", - "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -2761,10 +3046,20 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, "iconv-lite": { @@ -2793,9 +3088,9 @@ } }, "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", + "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", "dev": true, "requires": { "pkg-dir": "^4.2.0", @@ -2873,98 +3168,24 @@ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", "dev": true }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz", + "integrity": "sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "ci-info": "^3.1.1" } }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "has": "^1.0.3" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2992,20 +3213,23 @@ "is-extglob": "^2.1.1" } }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, "is-promise": { "version": "2.1.0", @@ -3013,67 +3237,24 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", - "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", - "dev": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -3081,21 +3262,18 @@ "dev": true }, "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.2.tgz", + "integrity": "sha512-o5+eTUYzCJ11/+JhW5/FUCdfsdoYVdQ/8I/OveE2XsjehYn5DdeSnNQAbjYaO8gQ6hvGTN6GM6ddQqpTVG5j8g==", "dev": true }, "istanbul-lib-instrument": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz", - "integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, "requires": { "@babel/core": "^7.7.5", - "@babel/parser": "^7.7.5", - "@babel/template": "^7.7.4", - "@babel/traverse": "^7.7.4", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.0.0", "semver": "^6.3.0" @@ -3113,9 +3291,9 @@ } }, "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "requires": { "debug": "^4.1.1", @@ -3124,9 +3302,9 @@ } }, "istanbul-reports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.0.tgz", - "integrity": "sha512-2osTcC8zcOSUkImzN2EWQta3Vdi4WjjKw99P2yWx5mLnigAM0Rd5uYFn1cf2i/Ois45GkNjaoTqc5CxgMSX80A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.5.tgz", + "integrity": "sha512-5+19PlhnGabNWB7kOFnuxT8H3T/iIyQzIbQMxXsURmmvKg86P2sbkrGOT77VnHw0Qr0gc2XzRaRfMZYYbSQCJQ==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -3134,659 +3312,1469 @@ } }, "jest": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-25.1.0.tgz", - "integrity": "sha512-FV6jEruneBhokkt9MQk0WUFoNTwnF76CLXtwNMfsc0um0TlB/LG2yxUd0KqaFjEJ9laQmVWQWS0sG/t2GsuI0w==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.2.5.tgz", + "integrity": "sha512-vDMzXcpQN4Ycaqu+vO7LX8pZwNNoKMhc+gSp6q1D8S6ftRk8gNW8cni3YFxknP95jxzQo23Lul0BI2FrWgnwYQ==", "dev": true, "requires": { - "@jest/core": "^25.1.0", + "@jest/core": "^27.2.5", "import-local": "^3.0.2", - "jest-cli": "^25.1.0" + "jest-cli": "^27.2.5" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, "jest-cli": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-25.1.0.tgz", - "integrity": "sha512-p+aOfczzzKdo3AsLJlhs8J5EW6ffVidfSZZxXedJ0mHPBOln1DccqFmGCoO8JWd4xRycfmwy1eoQkMsF8oekPg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.2.5.tgz", + "integrity": "sha512-XzfcOXi5WQrXqFYsDxq5RDOKY4FNIgBgvgf3ZBz4e/j5/aWep5KnsAYH5OFPMdX/TP/LFsYQMRH7kzJUMh6JKg==", "dev": true, "requires": { - "@jest/core": "^25.1.0", - "@jest/test-result": "^25.1.0", - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", + "@jest/core": "^27.2.5", + "@jest/test-result": "^27.2.5", + "@jest/types": "^27.2.5", + "chalk": "^4.0.0", "exit": "^0.1.2", + "graceful-fs": "^4.2.4", "import-local": "^3.0.2", - "is-ci": "^2.0.0", - "jest-config": "^25.1.0", - "jest-util": "^25.1.0", - "jest-validate": "^25.1.0", + "jest-config": "^27.2.5", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", "prompts": "^2.0.1", - "realpath-native": "^1.1.0", - "yargs": "^15.0.0" + "yargs": "^16.2.0" } } } }, "jest-changed-files": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-25.1.0.tgz", - "integrity": "sha512-bdL1aHjIVy3HaBO3eEQeemGttsq1BDlHgWcOjEOIAcga7OOEGWHD2WSu8HhL7I1F0mFFyci8VKU4tRNk+qtwDA==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.2.5.tgz", + "integrity": "sha512-jfnNJzF89csUKRPKJ4MwZ1SH27wTmX2xiAIHUHrsb/OYd9Jbo4/SXxJ17/nnx6RIifpthk3Y+LEeOk+/dDeGdw==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "execa": "^5.0.0", + "throat": "^6.0.1" + } + }, + "jest-circus": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.2.5.tgz", + "integrity": "sha512-eyL9IcrAxm3Saq3rmajFCwpaxaRMGJ1KJs+7hlTDinXpJmeR3P02bheM3CYohE7UfwOBmrFMJHjgo/WPcLTM+Q==", "dev": true, "requires": { - "@jest/types": "^25.1.0", - "execa": "^3.2.0", - "throat": "^5.0.0" + "@jest/environment": "^27.2.5", + "@jest/test-result": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.2.5", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.2.5", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-runtime": "^27.2.5", + "jest-snapshot": "^27.2.5", + "jest-util": "^27.2.5", + "pretty-format": "^27.2.5", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" }, "dependencies": { - "cross-spawn": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", - "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "color-convert": "^2.0.1" } }, - "execa": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", - "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "p-finally": "^2.0.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "pump": "^3.0.0" + "color-name": "~1.1.4" } }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + } + } + }, + "jest-config": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.2.5.tgz", + "integrity": "sha512-QdENtn9b5rIIYGlbDNEcgY9LDL5kcokJnXrp7x8AGjHob/XFqw1Z6p+gjfna2sUulQsQ3ce2Fvntnv+7fKYDhQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^27.2.5", + "@jest/types": "^27.2.5", + "babel-jest": "^27.2.5", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "jest-circus": "^27.2.5", + "jest-environment-jsdom": "^27.2.5", + "jest-environment-node": "^27.2.5", + "jest-get-type": "^27.0.6", + "jest-jasmine2": "^27.2.5", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.2.5", + "jest-runner": "^27.2.5", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", + "micromatch": "^4.0.4", + "pretty-format": "^27.2.5" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "path-key": "^3.0.0" + "color-convert": "^2.0.1" } }, - "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "mimic-fn": "^2.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "p-finally": { + "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", - "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "shebang-regex": "^3.0.0" + "color-name": "~1.1.4" } }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { - "isexe": "^2.0.0" + "braces": "^3.0.1", + "picomatch": "^2.2.3" } + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true } } }, - "jest-config": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-25.1.0.tgz", - "integrity": "sha512-tLmsg4SZ5H7tuhBC5bOja0HEblM0coS3Wy5LTCb2C8ZV6eWLewHyK+3qSq9Bi29zmWQ7ojdCd3pxpx4l4d2uGw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^25.1.0", - "@jest/types": "^25.1.0", - "babel-jest": "^25.1.0", - "chalk": "^3.0.0", - "glob": "^7.1.1", - "jest-environment-jsdom": "^25.1.0", - "jest-environment-node": "^25.1.0", - "jest-get-type": "^25.1.0", - "jest-jasmine2": "^25.1.0", - "jest-regex-util": "^25.1.0", - "jest-resolve": "^25.1.0", - "jest-util": "^25.1.0", - "jest-validate": "^25.1.0", - "micromatch": "^4.0.2", - "pretty-format": "^25.1.0", - "realpath-native": "^1.1.0" - } - }, "jest-diff": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.1.0.tgz", - "integrity": "sha512-nepXgajT+h017APJTreSieh4zCqnSHEJ1iT8HDlewu630lSJ4Kjjr9KNzm+kzGwwcpsDE6Snx1GJGzzsefaEHw==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.2.5.tgz", + "integrity": "sha512-7gfwwyYkeslOOVQY4tVq5TaQa92mWfC9COsVYMNVYyJTOYAqbIkoD3twi5A+h+tAPtAelRxkqY6/xu+jwTr0dA==", "dev": true, "requires": { - "chalk": "^3.0.0", - "diff-sequences": "^25.1.0", - "jest-get-type": "^25.1.0", - "pretty-format": "^25.1.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "jest-docblock": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-25.1.0.tgz", - "integrity": "sha512-370P/mh1wzoef6hUKiaMcsPtIapY25suP6JqM70V9RJvdKLrV4GaGbfUseUVk4FZJw4oTZ1qSCJNdrClKt5JQA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.0.6.tgz", + "integrity": "sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-25.1.0.tgz", - "integrity": "sha512-R9EL8xWzoPySJ5wa0DXFTj7NrzKpRD40Jy+zQDp3Qr/2QmevJgkN9GqioCGtAJ2bW9P/MQRznQHQQhoeAyra7A==", - "dev": true, - "requires": { - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", - "jest-get-type": "^25.1.0", - "jest-util": "^25.1.0", - "pretty-format": "^25.1.0" - } - }, - "jest-environment-jsdom": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-25.1.0.tgz", - "integrity": "sha512-ILb4wdrwPAOHX6W82GGDUiaXSSOE274ciuov0lztOIymTChKFtC02ddyicRRCdZlB5YSrv3vzr1Z5xjpEe1OHQ==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.2.5.tgz", + "integrity": "sha512-HUPWIbJT0bXarRwKu/m7lYzqxR4GM5EhKOsu0z3t0SKtbFN6skQhpAUADM4qFShBXb9zoOuag5lcrR1x/WM+Ag==", "dev": true, "requires": { - "@jest/environment": "^25.1.0", - "@jest/fake-timers": "^25.1.0", - "@jest/types": "^25.1.0", - "jest-mock": "^25.1.0", - "jest-util": "^25.1.0", - "jsdom": "^15.1.1" + "@jest/types": "^27.2.5", + "chalk": "^4.0.0", + "jest-get-type": "^27.0.6", + "jest-util": "^27.2.5", + "pretty-format": "^27.2.5" }, "dependencies": { - "data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" + "color-convert": "^2.0.1" } }, - "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "webidl-conversions": "^4.0.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "html-encoding-sniffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", - "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "jest-environment-jsdom": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.2.5.tgz", + "integrity": "sha512-QtRpOh/RQKuXniaWcoFE2ElwP6tQcyxHu0hlk32880g0KczdonCs5P1sk5+weu/OVzh5V4Bt1rXuQthI01mBLg==", + "dev": true, + "requires": { + "@jest/environment": "^27.2.5", + "@jest/fake-timers": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "jest-mock": "^27.2.5", + "jest-util": "^27.2.5", + "jsdom": "^16.6.0" + }, + "dependencies": { + "abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "acorn": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", + "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "dev": true + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", "dev": true, "requires": { - "whatwg-encoding": "^1.0.1" + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" } }, "jsdom": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.2.1.tgz", - "integrity": "sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^7.1.0", - "acorn-globals": "^4.3.2", - "array-equal": "^1.0.0", - "cssom": "^0.4.1", - "cssstyle": "^2.0.0", - "data-urls": "^1.1.0", - "domexception": "^1.0.1", - "escodegen": "^1.11.1", - "html-encoding-sniffer": "^1.0.2", + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.0", - "parse5": "5.1.0", - "pn": "^1.1.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.7", - "saxes": "^3.1.9", - "symbol-tree": "^3.2.2", - "tough-cookie": "^3.0.1", - "w3c-hr-time": "^1.0.1", - "w3c-xmlserializer": "^1.1.2", - "webidl-conversions": "^4.0.2", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^7.0.0", - "ws": "^7.0.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", "xml-name-validator": "^3.0.0" } }, "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, "saxes": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", - "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", "dev": true, "requires": { - "xmlchars": "^2.1.1" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" } }, "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "^2.1.1" } }, - "w3c-xmlserializer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", - "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", "dev": true, "requires": { - "domexception": "^1.0.1", - "webidl-conversions": "^4.0.2", - "xml-name-validator": "^3.0.0" + "browser-process-hrtime": "^1.0.0" } }, "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", "dev": true }, "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" } + }, + "ws": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "dev": true } } }, "jest-environment-node": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-25.1.0.tgz", - "integrity": "sha512-U9kFWTtAPvhgYY5upnH9rq8qZkj6mYLup5l1caAjjx9uNnkLHN2xgZy5mo4SyLdmrh/EtB9UPpKFShvfQHD0Iw==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.2.5.tgz", + "integrity": "sha512-0o1LT4grm7iwrS8fIoLtwJxb/hoa3GsH7pP10P02Jpj7Mi4BXy65u46m89vEM2WfD1uFJQ2+dfDiWZNA2e6bJg==", "dev": true, "requires": { - "@jest/environment": "^25.1.0", - "@jest/fake-timers": "^25.1.0", - "@jest/types": "^25.1.0", - "jest-mock": "^25.1.0", - "jest-util": "^25.1.0" + "@jest/environment": "^27.2.5", + "@jest/fake-timers": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "jest-mock": "^27.2.5", + "jest-util": "^27.2.5" } }, "jest-get-type": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.1.0.tgz", - "integrity": "sha512-yWkBnT+5tMr8ANB6V+OjmrIJufHtCAqI5ic2H40v+tRqxDmE0PGnIiTyvRWFOMtmVHYpwRqyazDbTnhpjsGvLw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", + "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", "dev": true }, "jest-haste-map": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.1.0.tgz", - "integrity": "sha512-/2oYINIdnQZAqyWSn1GTku571aAfs8NxzSErGek65Iu5o8JYb+113bZysRMcC/pjE5v9w0Yz+ldbj9NxrFyPyw==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.2.5.tgz", + "integrity": "sha512-pzO+Gw2WLponaSi0ilpzYBE0kuVJstoXBX8YWyUebR8VaXuX4tzzn0Zp23c/WaETo7XYTGv2e8KdnpiskAFMhQ==", "dev": true, "requires": { - "@jest/types": "^25.1.0", + "@jest/types": "^27.2.5", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "fsevents": "^2.1.2", - "graceful-fs": "^4.2.3", - "jest-serializer": "^25.1.0", - "jest-util": "^25.1.0", - "jest-worker": "^25.1.0", - "micromatch": "^4.0.2", - "sane": "^4.0.3", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^27.0.6", + "jest-serializer": "^27.0.6", + "jest-util": "^27.2.5", + "jest-worker": "^27.2.5", + "micromatch": "^4.0.4", "walker": "^1.0.7" }, "dependencies": { + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "jest-worker": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz", - "integrity": "sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", + "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", "dev": true, "requires": { + "@types/node": "*", "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" + "supports-color": "^8.0.0" + } + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } }, "jest-jasmine2": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-25.1.0.tgz", - "integrity": "sha512-GdncRq7jJ7sNIQ+dnXvpKO2MyP6j3naNK41DTTjEAhLEdpImaDA9zSAZwDhijjSF/D7cf4O5fdyUApGBZleaEg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.2.5.tgz", + "integrity": "sha512-hdxY9Cm/CjLqu2tXeAoQHPgA4vcqlweVXYOg1+S9FeFdznB9Rti+eEBKDDkmOy9iqr4Xfbq95OkC4NFbXXPCAQ==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^25.1.0", - "@jest/source-map": "^25.1.0", - "@jest/test-result": "^25.1.0", - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", + "@jest/environment": "^27.2.5", + "@jest/source-map": "^27.0.6", + "@jest/test-result": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^25.1.0", + "expect": "^27.2.5", "is-generator-fn": "^2.0.0", - "jest-each": "^25.1.0", - "jest-matcher-utils": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-runtime": "^25.1.0", - "jest-snapshot": "^25.1.0", - "jest-util": "^25.1.0", - "pretty-format": "^25.1.0", - "throat": "^5.0.0" + "jest-each": "^27.2.5", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-runtime": "^27.2.5", + "jest-snapshot": "^27.2.5", + "jest-util": "^27.2.5", + "pretty-format": "^27.2.5", + "throat": "^6.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "jest-leak-detector": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-25.1.0.tgz", - "integrity": "sha512-3xRI264dnhGaMHRvkFyEKpDeaRzcEBhyNrOG5oT8xPxOyUAblIAQnpiR3QXu4wDor47MDTiHbiFcbypdLcLW5w==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.2.5.tgz", + "integrity": "sha512-HYsi3GUR72bYhOGB5C5saF9sPdxGzSjX7soSQS+BqDRysc7sPeBwPbhbuT8DnOpijnKjgwWQ8JqvbmReYnt3aQ==", "dev": true, "requires": { - "jest-get-type": "^25.1.0", - "pretty-format": "^25.1.0" + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" } }, "jest-matcher-utils": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.1.0.tgz", - "integrity": "sha512-KGOAFcSFbclXIFE7bS4C53iYobKI20ZWleAdAFun4W1Wz1Kkej8Ng6RRbhL8leaEvIOjGXhGf/a1JjO8bkxIWQ==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz", + "integrity": "sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg==", "dev": true, "requires": { - "chalk": "^3.0.0", - "jest-diff": "^25.1.0", - "jest-get-type": "^25.1.0", - "pretty-format": "^25.1.0" + "chalk": "^4.0.0", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "jest-message-util": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.1.0.tgz", - "integrity": "sha512-Nr/Iwar2COfN22aCqX0kCVbXgn8IBm9nWf4xwGr5Olv/KZh0CZ32RKgZWMVDXGdOahicM10/fgjdimGNX/ttCQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^25.1.0", - "@jest/types": "^25.1.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^3.0.0", - "micromatch": "^4.0.2", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.2.5.tgz", + "integrity": "sha512-ggXSLoPfIYcbmZ8glgEJZ8b+e0Msw/iddRmgkoO7lDAr9SmI65IIfv7VnvTnV4FGnIIUIjzM+fHRHO5RBvyAbQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.2.5", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "pretty-format": "^27.2.5", "slash": "^3.0.0", - "stack-utils": "^1.0.1" + "stack-utils": "^2.0.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "jest-mock": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.1.0.tgz", - "integrity": "sha512-28/u0sqS+42vIfcd1mlcg4ZVDmSUYuNvImP4X2lX5hRMLW+CN0BeiKVD4p+ujKKbSPKd3rg/zuhCF+QBLJ4vag==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.2.5.tgz", + "integrity": "sha512-HiMB3LqE9RzmeMzZARi2Bz3NoymxyP0gCid4y42ca1djffNtYFKgI220aC1VP1mUZ8rbpqZbHZOJ15093bZV/Q==", "dev": true, "requires": { - "@jest/types": "^25.1.0" + "@jest/types": "^27.2.5", + "@types/node": "*" } }, "jest-pnp-resolver": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", - "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", "dev": true }, "jest-regex-util": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.1.0.tgz", - "integrity": "sha512-9lShaDmDpqwg+xAd73zHydKrBbbrIi08Kk9YryBEBybQFg/lBWR/2BDjjiSE7KIppM9C5+c03XiDaZ+m4Pgs1w==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", "dev": true }, "jest-resolve": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.1.0.tgz", - "integrity": "sha512-XkBQaU1SRCHj2Evz2Lu4Czs+uIgJXWypfO57L7JYccmAXv4slXA6hzNblmcRmf7P3cQ1mE7fL3ABV6jAwk4foQ==", - "dev": true, - "requires": { - "@jest/types": "^25.1.0", - "browser-resolve": "^1.11.3", - "chalk": "^3.0.0", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.2.5.tgz", + "integrity": "sha512-q5irwS3oS73SKy3+FM/HL2T7WJftrk9BRzrXF92f7net5HMlS7lJMg/ZwxLB4YohKqjSsdksEw7n/jvMxV7EKg==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "chalk": "^4.0.0", + "escalade": "^3.1.1", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", + "resolve": "^1.20.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + } } }, "jest-resolve-dependencies": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-25.1.0.tgz", - "integrity": "sha512-Cu/Je38GSsccNy4I2vL12ZnBlD170x2Oh1devzuM9TLH5rrnLW1x51lN8kpZLYTvzx9j+77Y5pqBaTqfdzVzrw==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.2.5.tgz", + "integrity": "sha512-BSjefped31bcvvCh++/pN9ueqqN1n0+p8/58yScuWfklLm2tbPbS9d251vJhAy0ZI2pL/0IaGhOTJrs9Y4FJlg==", "dev": true, "requires": { - "@jest/types": "^25.1.0", - "jest-regex-util": "^25.1.0", - "jest-snapshot": "^25.1.0" + "@jest/types": "^27.2.5", + "jest-regex-util": "^27.0.6", + "jest-snapshot": "^27.2.5" } }, "jest-runner": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-25.1.0.tgz", - "integrity": "sha512-su3O5fy0ehwgt+e8Wy7A8CaxxAOCMzL4gUBftSs0Ip32S0epxyZPDov9Znvkl1nhVOJNf4UwAsnqfc3plfQH9w==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.2.5.tgz", + "integrity": "sha512-n41vw9RLg5TKAnEeJK9d6pGOsBOpwE89XBniK+AD1k26oIIy3V7ogM1scbDjSheji8MUPC9pNgCrZ/FHLVDNgg==", "dev": true, "requires": { - "@jest/console": "^25.1.0", - "@jest/environment": "^25.1.0", - "@jest/test-result": "^25.1.0", - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", + "@jest/console": "^27.2.5", + "@jest/environment": "^27.2.5", + "@jest/test-result": "^27.2.5", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", "exit": "^0.1.2", - "graceful-fs": "^4.2.3", - "jest-config": "^25.1.0", - "jest-docblock": "^25.1.0", - "jest-haste-map": "^25.1.0", - "jest-jasmine2": "^25.1.0", - "jest-leak-detector": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-resolve": "^25.1.0", - "jest-runtime": "^25.1.0", - "jest-util": "^25.1.0", - "jest-worker": "^25.1.0", + "graceful-fs": "^4.2.4", + "jest-docblock": "^27.0.6", + "jest-environment-jsdom": "^27.2.5", + "jest-environment-node": "^27.2.5", + "jest-haste-map": "^27.2.5", + "jest-leak-detector": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-resolve": "^27.2.5", + "jest-runtime": "^27.2.5", + "jest-util": "^27.2.5", + "jest-worker": "^27.2.5", "source-map-support": "^0.5.6", - "throat": "^5.0.0" + "throat": "^6.0.1" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "jest-worker": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz", - "integrity": "sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", + "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", "dev": true, "requires": { + "@types/node": "*", "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } } } }, "jest-runtime": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-25.1.0.tgz", - "integrity": "sha512-mpPYYEdbExKBIBB16ryF6FLZTc1Rbk9Nx0ryIpIMiDDkOeGa0jQOKVI/QeGvVGlunKKm62ywcioeFVzIbK03bA==", - "dev": true, - "requires": { - "@jest/console": "^25.1.0", - "@jest/environment": "^25.1.0", - "@jest/source-map": "^25.1.0", - "@jest/test-result": "^25.1.0", - "@jest/transform": "^25.1.0", - "@jest/types": "^25.1.0", - "@types/yargs": "^15.0.0", - "chalk": "^3.0.0", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.2.5.tgz", + "integrity": "sha512-N0WRZ3QszKyZ3Dm27HTBbBuestsSd3Ud5ooVho47XZJ8aSKO/X1Ag8M1dNx9XzfGVRNdB/xCA3lz8MJwIzPLLA==", + "dev": true, + "requires": { + "@jest/console": "^27.2.5", + "@jest/environment": "^27.2.5", + "@jest/fake-timers": "^27.2.5", + "@jest/globals": "^27.2.5", + "@jest/source-map": "^27.0.6", + "@jest/test-result": "^27.2.5", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", "exit": "^0.1.2", "glob": "^7.1.3", - "graceful-fs": "^4.2.3", - "jest-config": "^25.1.0", - "jest-haste-map": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-mock": "^25.1.0", - "jest-regex-util": "^25.1.0", - "jest-resolve": "^25.1.0", - "jest-snapshot": "^25.1.0", - "jest-util": "^25.1.0", - "jest-validate": "^25.1.0", - "realpath-native": "^1.1.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-mock": "^27.2.5", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.2.5", + "jest-snapshot": "^27.2.5", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", "slash": "^3.0.0", "strip-bom": "^4.0.0", - "yargs": "^15.0.0" + "yargs": "^16.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + } } }, "jest-serializer": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.1.0.tgz", - "integrity": "sha512-20Wkq5j7o84kssBwvyuJ7Xhn7hdPeTXndnwIblKDR2/sy1SUm6rWWiG9kSCgJPIfkDScJCIsTtOKdlzfIHOfKA==", - "dev": true + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz", + "integrity": "sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==", + "dev": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.4" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + } + } }, "jest-snapshot": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.1.0.tgz", - "integrity": "sha512-xZ73dFYN8b/+X2hKLXz4VpBZGIAn7muD/DAg+pXtDzDGw3iIV10jM7WiHqhCcpDZfGiKEj7/2HXAEPtHTj0P2A==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.2.5.tgz", + "integrity": "sha512-2/Jkn+VN6Abwz0llBltZaiJMnL8b1j5Bp/gRIxe9YR3FCEh9qp0TXVV0dcpTGZ8AcJV1SZGQkczewkI9LP5yGw==", "dev": true, "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/parser": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", "@babel/types": "^7.0.0", - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", - "expect": "^25.1.0", - "jest-diff": "^25.1.0", - "jest-get-type": "^25.1.0", - "jest-matcher-utils": "^25.1.0", - "jest-message-util": "^25.1.0", - "jest-resolve": "^25.1.0", - "mkdirp": "^0.5.1", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.2.5", + "graceful-fs": "^4.2.4", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "jest-haste-map": "^27.2.5", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-resolve": "^27.2.5", + "jest-util": "^27.2.5", "natural-compare": "^1.4.0", - "pretty-format": "^25.1.0", - "semver": "^7.1.1" + "pretty-format": "^27.2.5", + "semver": "^7.3.2" }, "dependencies": { - "semver": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", - "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, "jest-util": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.1.0.tgz", - "integrity": "sha512-7did6pLQ++87Qsj26Fs/TIwZMUFBXQ+4XXSodRNy3luch2DnRXsSnmpVtxxQ0Yd6WTipGpbhh2IFP1mq6/fQGw==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", "dev": true, "requires": { - "@jest/types": "^25.1.0", - "chalk": "^3.0.0", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1" + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + } } }, "jest-validate": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-25.1.0.tgz", - "integrity": "sha512-kGbZq1f02/zVO2+t1KQGSVoCTERc5XeObLwITqC6BTRH3Adv7NZdYqCpKIZLUgpLXf2yISzQ465qOZpul8abXA==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.2.5.tgz", + "integrity": "sha512-XgYtjS89nhVe+UfkbLgcm+GgXKWgL80t9nTcNeejyO3t0Sj/yHE8BtIJqjZu9NXQksYbGImoQRXmQ1gP+Guffw==", "dev": true, "requires": { - "@jest/types": "^25.1.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "jest-get-type": "^25.1.0", + "@jest/types": "^27.2.5", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.0.6", "leven": "^3.1.0", - "pretty-format": "^25.1.0" + "pretty-format": "^27.2.5" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "jest-watcher": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-25.1.0.tgz", - "integrity": "sha512-Q9eZ7pyaIr6xfU24OeTg4z1fUqBF/4MP6J801lyQfg7CsnZ/TCzAPvCfckKdL5dlBBEKBeHV0AdyjFZ5eWj4ig==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.2.5.tgz", + "integrity": "sha512-umV4qGozg2Dn6DTTtqAh9puPw+DGLK9AQas7+mWjiK8t0fWMpxKg8ZXReZw7L4C88DqorsGUiDgwHNZ+jkVrkQ==", "dev": true, "requires": { - "@jest/test-result": "^25.1.0", - "@jest/types": "^25.1.0", + "@jest/test-result": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "jest-util": "^25.1.0", - "string-length": "^3.1.0" + "chalk": "^4.0.0", + "jest-util": "^27.2.5", + "string-length": "^4.0.1" }, "dependencies": { "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "color-name": "~1.1.4" } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true } } }, @@ -3905,18 +4893,18 @@ "dev": true }, "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minimist": "^1.2.5" }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true } } @@ -3942,12 +4930,6 @@ "verror": "1.10.0" } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -4009,15 +4991,6 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4027,6 +5000,15 @@ "yallist": "^4.0.0" } }, + "magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, "make-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", @@ -4037,9 +5019,9 @@ } }, "make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "makeerror": { @@ -4051,21 +5033,6 @@ "tmpl": "1.0.x" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4079,13 +5046,21 @@ "dev": true }, "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { "braces": "^3.0.1", - "picomatch": "^2.0.5" + "picomatch": "^2.2.3" + }, + "dependencies": { + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + } } }, "mime-db": { @@ -4124,27 +5099,6 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -4166,25 +5120,6 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4209,19 +5144,11 @@ "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", "dev": true }, - "node-notifier": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-6.0.0.tgz", - "integrity": "sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==", - "dev": true, - "optional": true, - "requires": { - "growly": "^1.3.0", - "is-wsl": "^2.1.1", - "semver": "^6.3.0", - "shellwords": "^0.1.1", - "which": "^1.3.1" - } + "node-releases": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.0.tgz", + "integrity": "sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA==", + "dev": true }, "normalize-path": { "version": "3.0.0", @@ -4230,12 +5157,20 @@ "dev": true }, "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "requires": { - "path-key": "^2.0.0" + "path-key": "^3.0.0" + }, + "dependencies": { + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + } } }, "nwsapi": { @@ -4250,89 +5185,6 @@ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4371,18 +5223,6 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "p-each-series": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", - "integrity": "sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, "p-limit": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", @@ -4422,12 +5262,6 @@ "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", "dev": true }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4464,6 +5298,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", @@ -4494,12 +5334,6 @@ "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", "dev": true }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -4507,46 +5341,27 @@ "dev": true }, "pretty-format": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.1.0.tgz", - "integrity": "sha512-46zLRSGLd02Rp+Lhad9zzuNZ+swunitn8zIpfD2B4OPCRLXbM87RJT2aBLBWYOznNUML/2l/ReMyWNC80PJBUQ==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.2.5.tgz", + "integrity": "sha512-+nYn2z9GgicO9JiqmY25Xtq8SYfZ/5VCpEU3pppHHNAhd1y+ZXxmNPd1evmNcAd6Hz4iBV2kf0UpGth5A/VJ7g==", "dev": true, "requires": { - "@jest/types": "^25.1.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true } } @@ -4558,13 +5373,13 @@ "dev": true }, "prompts": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.1.tgz", - "integrity": "sha512-qIP2lQyCwYbdzcqHIUi2HAxiWixhoM9OdLCWf8txXsapC/X9YdsCoeyRIXE/GP+Q0J37Q7+XN/MFqbUa7IzXNA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "requires": { "kleur": "^3.0.3", - "sisteransi": "^1.0.4" + "sisteransi": "^1.0.5" } }, "psl": { @@ -4573,16 +5388,6 @@ "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", "dev": true }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -4602,54 +5407,17 @@ "dev": true }, "react-is": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", - "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "realpath-native": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", - "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", - "dev": true, - "requires": { - "util.promisify": "^1.0.0" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -4734,12 +5502,6 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "resolve": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", @@ -4772,12 +5534,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -4788,12 +5544,6 @@ "signal-exit": "^3.0.2" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4873,12 +5623,6 @@ "estree-walker": "^0.6.1" } }, - "rsvp": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", - "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", - "dev": true - }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -4905,183 +5649,27 @@ "requires": { "tslib": "^1.9.0" }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sane": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", - "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", - "dev": true, - "requires": { - "@cnakazawa/watch": "^1.0.3", - "anymatch": "^2.0.0", - "capture-exit": "^2.0.0", - "exec-sh": "^0.3.2", - "execa": "^1.0.0", - "fb-watchman": "^2.0.0", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } } } }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "saxes": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/saxes/-/saxes-4.0.2.tgz", @@ -5103,35 +5691,6 @@ "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "dev": true }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -5147,13 +5706,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true, - "optional": true - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -5161,9 +5713,9 @@ "dev": true }, "sisteransi": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.4.tgz", - "integrity": "sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, "slash": { @@ -5183,178 +5735,28 @@ "is-fullwidth-code-point": "^2.0.0" } }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", + "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "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 }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -5379,29 +5781,19 @@ } }, "stack-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", - "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "escape-string-regexp": "^2.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true } } }, @@ -5412,13 +5804,30 @@ "dev": true }, "string-length": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", - "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "requires": { - "astral-regex": "^1.0.0", - "strip-ansi": "^5.2.0" + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } } }, "string-width": { @@ -5442,26 +5851,6 @@ } } }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -5485,12 +5874,6 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -5521,9 +5904,9 @@ } }, "supports-hyperlinks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz", - "integrity": "sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", "dev": true, "requires": { "has-flag": "^4.0.0", @@ -5580,12 +5963,12 @@ }, "dependencies": { "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.21.3" } } } @@ -5608,9 +5991,9 @@ "dev": true }, "throat": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", - "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, "through": { @@ -5635,9 +6018,9 @@ } }, "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "to-fast-properties": { @@ -5646,38 +6029,6 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5708,42 +6059,28 @@ } }, "ts-jest": { - "version": "25.2.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-25.2.0.tgz", - "integrity": "sha512-VaRdb0da46eorLfuHEFf0G3d+jeREcV+Wb/SvW71S4y9Oe8SHWU+m1WY/3RaMknrBsnvmVH0/rRjT8dkgeffNQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.0.6.tgz", + "integrity": "sha512-XWkEBbrkyUWJdK9FwiCVdBZ7ZmT7sxcKtyVEZNmo7u8eQw6NHmtYEM2WpkX9VfnRI0DjSr6INfEHC9vCFhsFnQ==", "dev": true, "requires": { "bs-logger": "0.x", - "buffer-from": "1.x", "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", "json5": "2.x", "lodash.memoize": "4.x", "make-error": "1.x", - "mkdirp": "0.x", - "resolve": "1.x", - "semver": "^5.5", - "yargs-parser": "10.x" + "semver": "7.x", + "yargs-parser": "20.x" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "lru-cache": "^6.0.0" } } } @@ -5801,9 +6138,9 @@ "dev": true }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, "typedarray-to-buffer": { @@ -5816,9 +6153,9 @@ } }, "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", + "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", "dev": true }, "uglify-js": { @@ -5827,64 +6164,12 @@ "integrity": "sha512-Esj5HG5WAyrLIdYU74Z3JdG2PxdIusvj6IWHMtlyESxc7kcDz7zYlYjpnSokn1UbpV0d/QX9fan7gkCNd/9BQA==", "dev": true }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -5894,30 +6179,6 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - } - }, "uuid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", @@ -5931,9 +6192,9 @@ "dev": true }, "v8-to-istanbul": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.2.tgz", - "integrity": "sha512-G9R+Hpw0ITAmPSr47lSlc5A1uekSYzXxTMlFxso2xoffwo4jQnzbv1p9yXIinO8UMZKfAFewaCHwWvnH4Jb4Ug==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz", + "integrity": "sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -6034,12 +6295,6 @@ "isexe": "^2.0.0" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -6047,9 +6302,9 @@ "dev": true }, "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { "ansi-styles": "^4.0.0", @@ -6058,18 +6313,17 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -6101,23 +6355,23 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } } } @@ -6138,9 +6392,9 @@ } }, "write-file-atomic": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", - "integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "requires": { "imurmurhash": "^0.1.4", @@ -6168,9 +6422,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { @@ -6180,28 +6434,24 @@ "dev": true }, "yargs": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.1.0.tgz", - "integrity": "sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^16.1.0" + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "emoji-regex": { @@ -6217,36 +6467,32 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } } } }, "yargs-parser": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", - "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true }, "z-schema": { "version": "3.18.4", diff --git a/package.json b/package.json index 4a603db66..394200ad1 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,13 @@ { "name": "zrender", "version": "5.2.1", - "description": "A lightweight canvas library.", + "description": "A lightweight graphic library providing 2d draw for Apache ECharts", "keywords": [ "canvas", - "2d" + "svg", + "2d", + "html5", + "vector-graphics" ], "repository": { "type": "git", @@ -17,9 +20,9 @@ "prepare:nightly": "node build/prepareNightly.js", "prepare:nightly-next": "node build/prepareNightly.js --next", "build:bundle": "node build/build.js", - "build:lib": "npx tsc -m ES2015 --outDir lib", + "build:lib": "npx tsc -m ES2015 --outDir lib && node build/processLib.js", "watch:bundle": "node build/build.js --watch", - "watch:lib": "npx tsc -w -m ES2015 --outDir lib", + "watch:lib": "npx tsc-watch -m ES2015 --outDir lib --synchronousWatchDirectory --onSuccess \"node build/processLib.js\"", "test": "npx jest --config test/ut/jest.config.js", "lint": "npx eslint src/**/*.ts" }, @@ -36,20 +39,23 @@ ], "devDependencies": { "@microsoft/api-extractor": "^7.7.2", - "@types/jest": "^25.1.2", + "@rollup/plugin-node-resolve": "^11.0.0", + "@rollup/plugin-replace": "^3.0.0", + "@types/jest": "^27.0.2", "@typescript-eslint/eslint-plugin": "^4.9.1", "@typescript-eslint/parser": "^4.9.1", "chalk": "^3.0.0", "commander": "2.11.0", "eslint": "6.3.0", "fs-extra": "4.0.2", - "jest": "^25.1.0", + "globby": "^11.0.4", + "jest": "^27.2.5", "jsdom": "^16.0.0", "rollup": "^1.28.0", "rollup-plugin-typescript2": "^0.25.3", "rollup-plugin-uglify": "^6.0.4", - "ts-jest": "^25.2.0", - "typescript": "4.3.5", + "ts-jest": "^27.0.6", + "typescript": "^4.4.3", "uglify-js": "^3.10.0" } } diff --git a/src/Element.ts b/src/Element.ts index 633ad290a..eb87cc5f9 100644 --- a/src/Element.ts +++ b/src/Element.ts @@ -1,4 +1,4 @@ -import Transformable from './core/Transformable'; +import Transformable, {TRANSFORMABLE_PROPS, TransformProp} from './core/Transformable'; import { AnimationEasing } from './animation/easing'; import Animator, {cloneValue} from './animation/Animator'; import { ZRenderType } from './zrender'; @@ -20,14 +20,16 @@ import { logError, mixin, isArrayLike, - isTypedArray + isTypedArray, + isGradientObject, + filter, + reduce } from './core/util'; import Polyline from './graphic/shape/Polyline'; import Group from './graphic/Group'; import Point from './core/Point'; import { LIGHT_LABEL_COLOR, DARK_LABEL_COLOR } from './config'; import { parse, stringify } from './tool/color'; -import env from './core/env'; import { REDRAW_BIT } from './graphic/constants'; export interface ElementAnimateConfig { @@ -229,7 +231,7 @@ interface ElementEventHandlerProps { ondrop: ElementEventCallback } -export interface ElementProps extends Partial { +export interface ElementProps extends Partial, Partial> { name?: string ignore?: boolean isGroup?: boolean @@ -238,15 +240,6 @@ export interface ElementProps extends Partial { silent?: boolean ignoreClip?: boolean - // From transform - x?: number - y?: number - scaleX?: number - scaleY?: number - originX?: number - originY?: number - rotation?: number - globalScaleRatio?: number textConfig?: ElementTextConfig @@ -265,17 +258,11 @@ export interface ElementProps extends Partial { export const PRESERVED_NORMAL_STATE = '__zr_normal__'; // export const PRESERVED_MERGED_STATE = '__zr_merged__'; -const PRIMARY_STATES_KEYS = ['x', 'y', 'scaleX', 'scaleY', 'originX', 'originY', 'rotation', 'ignore'] as const; -const DEFAULT_ANIMATABLE_MAP: Partial> = { - x: true, - y: true, - scaleX: true, - scaleY: true, - originX: true, - originY: true, - rotation: true, - ignore: false -}; +const PRIMARY_STATES_KEYS = (TRANSFORMABLE_PROPS as any).concat(['ignore']) as [TransformProp, 'ignore']; +const DEFAULT_ANIMATABLE_MAP = reduce(TRANSFORMABLE_PROPS, (obj, key) => { + obj[key] = true; + return obj; +}, {ignore: false} as Partial>); export type ElementStatePropNames = (typeof PRIMARY_STATES_KEYS)[number] | 'textConfig'; export type ElementState = Pick & ElementCommonState @@ -765,7 +752,8 @@ class Element { const animator = this.animators[i]; const fromStateTransition = animator.__fromStateTransition; // Ignore animation from state transition(except normal). - if (fromStateTransition && fromStateTransition !== PRESERVED_NORMAL_STATE) { + // Ignore loop animation. + if (animator.getLoop() || fromStateTransition && fromStateTransition !== PRESERVED_NORMAL_STATE) { continue; } @@ -775,7 +763,7 @@ class Element { const target = targetName ? (normalState as any)[targetName] : normalState; // Only save keys that are changed by the states. - animator.saveFinalToTarget(target); + animator.saveTo(target); } } @@ -1174,10 +1162,13 @@ class Element { for (let i = 0; i < this.animators.length; i++) { const animator = this.animators[i]; const targetName = animator.targetName; - animator.__changeFinalValue(targetName - ? ((state || normalState) as any)[targetName] - : (state || normalState) - ); + // Ignore loop animation + if (!animator.getLoop()) { + animator.__changeFinalValue(targetName + ? ((state || normalState) as any)[targetName] + : (state || normalState) + ); + } } } @@ -1196,11 +1187,17 @@ class Element { */ private _attachComponent(componentEl: Element) { if (componentEl.__zr && !componentEl.__hostTarget) { - throw new Error('Text element has been added to zrender.'); + if (process.env.NODE_ENV !== 'production') { + throw new Error('Text element has been added to zrender.'); + } + return; } if (componentEl === this) { - throw new Error('Recursive component attachment.'); + if (process.env.NODE_ENV !== 'production') { + throw new Error('Recursive component attachment.'); + } + return; } const zr = this.__zr; @@ -1277,9 +1274,10 @@ class Element { if (previousTextContent && previousTextContent !== textEl) { this.removeTextContent(); } - - if (textEl.__zr && !textEl.__hostTarget) { - throw new Error('Text element has been added to zrender.'); + if (process.env.NODE_ENV !== 'production') { + if (textEl.__zr && !textEl.__hostTarget) { + throw new Error('Text element has been added to zrender.'); + } } textEl.innerTransformable = new Transformable(); @@ -1454,26 +1452,30 @@ class Element { * * @param path The key to fetch value from object. Mostly style or shape. * @param loop Whether to loop animation. + * @param allowDiscreteAnimation Whether to allow discrete animation * @example: * el.animate('style', false) * .when(1000, {x: 10} ) * .done(function(){ // Animation done }) * .start() */ - animate(key?: string, loop?: boolean) { + animate(key?: string, loop?: boolean, allowDiscreteAnimation?: boolean) { let target = key ? (this as any)[key] : this; - if (!target) { - logError( - 'Property "' - + key - + '" is not existed in element ' - + this.id - ); - return; + if (process.env.NODE_ENV !== 'production') { + if (!target) { + logError( + 'Property "' + + key + + '" is not existed in element ' + + this.id + ); + return; + } } - const animator = new Animator(target, loop); + const animator = new Animator(target, loop, allowDiscreteAnimation); + key && (animator.targetName = key); this.addAnimator(animator, key); return animator; } @@ -1616,13 +1618,15 @@ class Element { const elProto = Element.prototype; elProto.type = 'element'; elProto.name = ''; - elProto.ignore = false; - elProto.silent = false; - elProto.isGroup = false; - elProto.draggable = false; - elProto.dragging = false; - elProto.ignoreClip = false; + + elProto.ignore = + elProto.silent = + elProto.isGroup = + elProto.draggable = + elProto.dragging = + elProto.ignoreClip = elProto.__inHover = false; + elProto.__dirty = REDRAW_BIT; @@ -1642,7 +1646,9 @@ class Element { ) { Object.defineProperty(elProto, key, { get() { - logDeprecatedError(key, xKey, yKey); + if (process.env.NODE_ENV !== 'production') { + logDeprecatedError(key, xKey, yKey); + } if (!this[privateKey]) { const pos: number[] = this[privateKey] = []; enhanceArray(this, pos); @@ -1650,7 +1656,9 @@ class Element { return this[privateKey]; }, set(pos: number[]) { - logDeprecatedError(key, xKey, yKey); + if (process.env.NODE_ENV !== 'production') { + logDeprecatedError(key, xKey, yKey); + } this[xKey] = pos[0]; this[yKey] = pos[1]; this[privateKey] = pos; @@ -1676,7 +1684,10 @@ class Element { }); } } - if (Object.defineProperty && (!(env as any).browser.ie || (env as any).browser.version > 8)) { + if (Object.defineProperty + // Just don't support ie8 + // && (!(env as any).browser.ie || (env as any).browser.version > 8) + ) { createLegacyProperty('position', '_legacyPos', 'x', 'y'); createLegacyProperty('scale', '_legacyScale', 'scaleX', 'scaleY'); createLegacyProperty('origin', '_legacyOrigin', 'originX', 'originY'); @@ -1755,7 +1766,10 @@ function animateTo( if (abortedCb) { animator.aborted(abortedCb); } - animator.start(cfg.easing, cfg.force); + if (cfg.force) { + animator.duration(cfg.duration); + } + animator.start(cfg.easing); } return animators; @@ -1814,38 +1828,63 @@ function copyValue(target: Dictionary, source: Dictionary, key: string } } +function isValueSame(val1: any, val2: any) { + return val1 === val2 + // Only check 1 dimension array + || isArrayLike(val1) && isArrayLike(val2) && is1DArraySame(val1, val2); +} + +function is1DArraySame(arr0: ArrayLike, arr1: ArrayLike) { + const len = arr0.length; + if (len !== arr1.length) { + return false; + } + for (let i = 0; i < len; i++) { + if (arr0[i] !== arr1[i]) { + return false; + } + } + return true; +} + function animateToShallow( animatable: Element, topKey: string, - source: Dictionary, + animateObj: Dictionary, target: Dictionary, cfg: ElementAnimateConfig, animationProps: Dictionary | true, animators: Animator[], reverse: boolean // If `true`, animate from the `target` to current state. ) { - const animatableKeys: string[] = []; - const changedKeys: string[] = []; const targetKeys = keys(target); const duration = cfg.duration; const delay = cfg.delay; const additive = cfg.additive; const setToFinal = cfg.setToFinal; const animateAll = !isObject(animationProps); + // Find last animator animating same prop. + const existsAnimators = animatable.animators; + + let animationKeys: string[] = []; for (let k = 0; k < targetKeys.length; k++) { const innerKey = targetKeys[k] as string; + const targetVal = target[innerKey]; - if (source[innerKey] != null - && target[innerKey] != null // Can't animate between null value. assign directly. For example. stroke animate from #fff to null. + if ( + targetVal != null && animateObj[innerKey] != null && (animateAll || (animationProps as Dictionary)[innerKey]) ) { - if (isObject(target[innerKey]) && !isArrayLike(target[innerKey])) { + if (isObject(targetVal) + && !isArrayLike(targetVal) + && !isGradientObject(targetVal) + ) { if (topKey) { // logError('Only support 1 depth nest object animation.'); // Assign directly. // TODO richText? if (!reverse) { - source[innerKey] = target[innerKey]; + animateObj[innerKey] = targetVal; animatable.updateDuringAnimation(topKey); } continue; @@ -1853,8 +1892,8 @@ function animateToShallow( animateToShallow( animatable, innerKey, - source[innerKey], - target[innerKey], + animateObj[innerKey], + targetVal, cfg, animationProps && (animationProps as Dictionary)[innerKey], animators, @@ -1862,50 +1901,50 @@ function animateToShallow( ); } else { - animatableKeys.push(innerKey); - changedKeys.push(innerKey); + animationKeys.push(innerKey); } } else if (!reverse) { // Assign target value directly. - source[innerKey] = target[innerKey]; + animateObj[innerKey] = targetVal; animatable.updateDuringAnimation(topKey); // Previous animation will be stopped on the changed keys. // So direct assign is also included. - changedKeys.push(innerKey); + animationKeys.push(innerKey); } } - const keyLen = animatableKeys.length; - - if (keyLen > 0 - // cfg.force is mainly for keep invoking onframe and ondone callback even if animation is not necessary. - // So if there is already has animators. There is no need to create another animator if not necessary. - // Or it will always add one more with empty target. - || (cfg.force && !animators.length) - ) { - // Find last animator animating same prop. - const existsAnimators = animatable.animators; - let existsAnimatorsOnSameTarget: Animator[] = []; + let keyLen = animationKeys.length; + // Stop previous animations on the same property. + if (!additive && keyLen) { + // Stop exists animation on specific tracks. Only one animator available for each property. + // TODO Should invoke previous animation callback? for (let i = 0; i < existsAnimators.length; i++) { - // Use key string instead object reference because ref may be changed. - if (existsAnimators[i].targetName === topKey) { - existsAnimatorsOnSameTarget.push(existsAnimators[i]); - } - } - - if (!additive && existsAnimatorsOnSameTarget.length) { - // Stop exists animation on specific tracks. Only one animator available for each property. - // TODO Should invoke previous animation callback? - for (let i = 0; i < existsAnimatorsOnSameTarget.length; i++) { - const allAborted = existsAnimatorsOnSameTarget[i].stopTracks(changedKeys); + const animator = existsAnimators[i]; + if (animator.targetName === topKey) { + const allAborted = animator.stopTracks(animationKeys); if (allAborted) { // This animator can't be used. - const idx = indexOf(existsAnimators, existsAnimatorsOnSameTarget[i]); + const idx = indexOf(existsAnimators, animator); existsAnimators.splice(idx, 1); } } } + } + // Ignore values not changed. + // NOTE: Must filter it after previous animation stopped + // and make sure the value to compare is using initial frame if animation is not started yet when setToFinal is used. + if (!cfg.force) { + animationKeys = filter(animationKeys, key => !isValueSame(target[key], animateObj[key])); + keyLen = animationKeys.length; + } + + if (keyLen > 0 + // cfg.force is mainly for keep invoking onframe and ondone callback even if animation is not necessary. + // So if there is already has animators. There is no need to create another animator if not necessary. + // Or it will always add one more with empty target. + || (cfg.force && !animators.length) + ) { let revertedSource: Dictionary; let reversedTarget: Dictionary; let sourceClone: Dictionary; @@ -1915,8 +1954,8 @@ function animateToShallow( revertedSource = {}; } for (let i = 0; i < keyLen; i++) { - const innerKey = animatableKeys[i]; - reversedTarget[innerKey] = source[innerKey]; + const innerKey = animationKeys[i]; + reversedTarget[innerKey] = animateObj[innerKey]; if (setToFinal) { revertedSource[innerKey] = target[innerKey]; } @@ -1927,39 +1966,43 @@ function animateToShallow( // to prevent the "final" values from being read in any other places (like other running // animator during callbacks). // But if `setToFinal: true` this feature can not be satisfied. - source[innerKey] = target[innerKey]; + animateObj[innerKey] = target[innerKey]; } } } else if (setToFinal) { sourceClone = {}; for (let i = 0; i < keyLen; i++) { - const innerKey = animatableKeys[i]; + const innerKey = animationKeys[i]; // NOTE: Must clone source after the stopTracks. The property may be modified in stopTracks. - sourceClone[innerKey] = cloneValue(source[innerKey]); + sourceClone[innerKey] = cloneValue(animateObj[innerKey]); // Use copy, not change the original reference // Copy from target to source. - copyValue(source, target, innerKey); + copyValue(animateObj, target, innerKey); } } - const animator = new Animator(source, false, additive ? existsAnimatorsOnSameTarget : null); + const animator = new Animator(animateObj, false, false, additive ? filter( + // Use key string instead object reference because ref may be changed. + existsAnimators, animator => animator.targetName === topKey + ) : null); + animator.targetName = topKey; if (cfg.scope) { animator.scope = cfg.scope; } if (setToFinal && revertedSource) { - animator.whenWithKeys(0, revertedSource, animatableKeys); + animator.whenWithKeys(0, revertedSource, animationKeys); } if (sourceClone) { - animator.whenWithKeys(0, sourceClone, animatableKeys); + animator.whenWithKeys(0, sourceClone, animationKeys); } animator.whenWithKeys( duration == null ? 500 : duration, reverse ? reversedTarget : target, - animatableKeys + animationKeys ).delay(delay || 0); animatable.addAnimator(animator, topKey); diff --git a/src/Handler.ts b/src/Handler.ts index f41f87e53..8acf0522f 100644 --- a/src/Handler.ts +++ b/src/Handler.ts @@ -131,7 +131,6 @@ const handlerNames = [ type HandlerName = 'click' |'dblclick' |'mousewheel' |'mouseout' | 'mouseup' |'mousedown' |'mousemove' |'contextmenu'; - // TODO draggable class Handler extends Eventful { diff --git a/src/PainterBase.ts b/src/PainterBase.ts index c4eedeb49..fa42c37ad 100644 --- a/src/PainterBase.ts +++ b/src/PainterBase.ts @@ -1,5 +1,3 @@ -import Path from './graphic/Path'; -import ZRImage from './graphic/Image'; import { GradientObject } from './graphic/Gradient'; import { PatternObject } from './graphic/Pattern'; import { Dictionary } from './core/types'; @@ -13,7 +11,11 @@ export interface PainterBase { type: string - root: HTMLElement + // root will be undefined if ssr is true + root?: HTMLElement + + // If ssr only + ssrOnly?: boolean // constructor(dom: HTMLElement, storage: Storage, opts: PainterOption, id: number): void @@ -21,6 +23,9 @@ export interface PainterBase { refresh(): void clear(): void + // must be given if ssr is true. + renderToString?(): string; + getType: () => string getWidth(): number @@ -31,7 +36,6 @@ export interface PainterBase { getViewportRootOffset: () => {offsetLeft: number, offsetTop: number} refreshHover(): void - pathToImage(e: Path, dpr: number): ZRImage configLayer(zlevel: number, config: Dictionary): void setBackgroundColor(backgroundColor: string | GradientObject | PatternObject): void diff --git a/src/Storage.ts b/src/Storage.ts index 2abd1fcb8..72228c3fa 100644 --- a/src/Storage.ts +++ b/src/Storage.ts @@ -22,12 +22,6 @@ function logInvalidZError() { function shapeCompareFunc(a: Displayable, b: Displayable) { if (a.zlevel === b.zlevel) { if (a.z === b.z) { - // if (a.z2 === b.z2) { - // // FIXME Slow has renderidx compare - // // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement - // // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012 - // return a.__renderidx - b.__renderidx; - // } return a.z2 - b.z2; } return a.z - b.z; @@ -85,7 +79,7 @@ export default class Storage { displayList.length = this._displayListLen; - env.canvasSupported && timsort(displayList, shapeCompareFunc); + timsort(displayList, shapeCompareFunc); } private _updateAndAddDisplayable( diff --git a/src/all.ts b/src/all.ts new file mode 100644 index 000000000..cb7eae50b --- /dev/null +++ b/src/all.ts @@ -0,0 +1,8 @@ +export * from './zrender'; +export * from './export'; + +import {registerPainter} from './zrender'; +import CanvasPainter from './canvas/Painter'; +import SVGPainter from './svg/Painter'; +registerPainter('canvas', CanvasPainter); +registerPainter('svg', SVGPainter); diff --git a/src/animation/Animation.ts b/src/animation/Animation.ts index a1c31850e..cf2ec8569 100644 --- a/src/animation/Animation.ts +++ b/src/animation/Animation.ts @@ -11,15 +11,16 @@ import requestAnimationFrame from './requestAnimationFrame'; import Animator from './Animator'; import Clip from './Clip'; +export function getTime() { + return new Date().getTime(); +} interface Stage { update?: () => void } -type OnframeCallback = (deltaTime: number) => void interface AnimationOption { stage?: Stage - onframe?: OnframeCallback } /** * @example @@ -37,24 +38,22 @@ interface AnimationOption { * x: 100, * y: 100 * }) - * .start('spline'); + * .start(); */ export default class Animation extends Eventful { stage: Stage - onframe: OnframeCallback - // Use linked list to store clip - private _clipsHead: Clip - private _clipsTail: Clip + private _head: Clip + private _tail: Clip - private _running: boolean = false + private _running = false - private _time: number = 0 - private _pausedTime: number = 0 - private _pauseStart: number = 0 + private _time = 0 + private _pausedTime = 0 + private _pauseStart = 0 private _paused = false; @@ -64,8 +63,6 @@ export default class Animation extends Eventful { opts = opts || {}; this.stage = opts.stage || {}; - - this.onframe = opts.onframe || function () {}; } /** @@ -77,14 +74,14 @@ export default class Animation extends Eventful { this.removeClip(clip); } - if (!this._clipsHead) { - this._clipsHead = this._clipsTail = clip; + if (!this._head) { + this._head = this._tail = clip; } else { - this._clipsTail.next = clip; - clip.prev = this._clipsTail; + this._tail.next = clip; + clip.prev = this._tail; clip.next = null; - this._clipsTail = clip; + this._tail = clip; } clip.animation = this; } @@ -112,14 +109,14 @@ export default class Animation extends Eventful { } else { // Is head - this._clipsHead = next; + this._head = next; } if (next) { next.prev = prev; } else { // Is tail - this._clipsTail = prev; + this._tail = prev; } clip.next = clip.prev = clip.animation = null; } @@ -136,9 +133,9 @@ export default class Animation extends Eventful { } update(notTriggerFrameAndStageUpdate?: boolean) { - const time = new Date().getTime() - this._pausedTime; + const time = getTime() - this._pausedTime; const delta = time - this._time; - let clip = this._clipsHead; + let clip = this._head; while (clip) { // Save the nextClip before step. @@ -146,7 +143,7 @@ export default class Animation extends Eventful { const nextClip = clip.next; let finished = clip.step(time, delta); if (finished) { - clip.ondestroy && clip.ondestroy(); + clip.ondestroy(); this.removeClip(clip); clip = nextClip; } @@ -158,7 +155,6 @@ export default class Animation extends Eventful { this._time = time; if (!notTriggerFrameAndStageUpdate) { - this.onframe(delta); // 'frame' should be triggered before stage, because upper application // depends on the sequence (e.g., echarts-stream and finish @@ -176,9 +172,7 @@ export default class Animation extends Eventful { function step() { if (self._running) { - requestAnimationFrame(step); - !self._paused && self.update(); } } @@ -194,7 +188,7 @@ export default class Animation extends Eventful { return; } - this._time = new Date().getTime(); + this._time = getTime(); this._pausedTime = 0; this._startLoop(); @@ -212,7 +206,7 @@ export default class Animation extends Eventful { */ pause() { if (!this._paused) { - this._pauseStart = new Date().getTime(); + this._pauseStart = getTime(); this._paused = true; } } @@ -222,7 +216,7 @@ export default class Animation extends Eventful { */ resume() { if (this._paused) { - this._pausedTime += (new Date().getTime()) - this._pauseStart; + this._pausedTime += getTime() - this._pauseStart; this._paused = false; } } @@ -231,7 +225,7 @@ export default class Animation extends Eventful { * Clear animation. */ clear() { - let clip = this._clipsHead; + let clip = this._head; while (clip) { let nextClip = clip.next; @@ -239,14 +233,14 @@ export default class Animation extends Eventful { clip = nextClip; } - this._clipsHead = this._clipsTail = null; + this._head = this._tail = null; } /** * Whether animation finished. */ isFinished() { - return this._clipsHead == null; + return this._head == null; } /** @@ -254,7 +248,7 @@ export default class Animation extends Eventful { */ // TODO Gap animate(target: T, options: { - loop?: boolean // Whether loop animation. + loop?: boolean // Whether loop animation }) { options = options || {}; diff --git a/src/animation/Animator.ts b/src/animation/Animator.ts index e65dcc971..b4536d2a4 100644 --- a/src/animation/Animator.ts +++ b/src/animation/Animator.ts @@ -4,25 +4,41 @@ import Clip from './Clip'; import * as color from '../tool/color'; -import {isArrayLike, keys, logError} from '../core/util'; +import {eqNaN, extend, isArrayLike, isFunction, isGradientObject, isNumber, isString, keys, logError, map} from '../core/util'; import {ArrayLike, Dictionary} from '../core/types'; -import { AnimationEasing } from './easing'; +import easingFuncs, { AnimationEasing } from './easing'; import Animation from './Animation'; +import { createCubicEasingFunc } from './cubicEasing'; +import { isLinearGradient, isRadialGradient } from '../svg/helper'; type NumberArray = ArrayLike type InterpolatableType = string | number | NumberArray | NumberArray[]; -const arraySlice = Array.prototype.slice; +interface ParsedColorStop { + color: number[], + offset: number +}; -export function interpolateNumber(p0: number, p1: number, percent: number): number { - return (p1 - p0) * percent + p0; +interface ParsedGradientObject { + colorStops: ParsedColorStop[] + x: number + y: number + global: boolean } - -export function step(p0: any, p1: any, percent: number): any { - return percent > 0.5 ? p1 : p0; +interface ParsedLinearGradientObject extends ParsedGradientObject { + x2: number + y2: number } +interface ParsedRadialGradientObject extends ParsedGradientObject { + r: number +} + +const arraySlice = Array.prototype.slice; -export function interpolate1DArray( +function interpolateNumber(p0: number, p1: number, percent: number): number { + return (p1 - p0) * percent + p0; +} +function interpolate1DArray( out: NumberArray, p0: NumberArray, p1: NumberArray, @@ -33,9 +49,10 @@ export function interpolate1DArray( for (let i = 0; i < len; i++) { out[i] = interpolateNumber(p0[i], p1[i], percent); } + return out; } -export function interpolate2DArray( +function interpolate2DArray( out: NumberArray[], p0: NumberArray[], p1: NumberArray[], @@ -52,6 +69,7 @@ export function interpolate2DArray( out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent); } } + return out; } function add1DArray( @@ -85,12 +103,28 @@ function add2DArray( } return out; } + +function fillColorStops(val0: ParsedColorStop[], val1: ParsedColorStop[]) { + const len0 = val0.length; + const len1 = val1.length; + + const shorterArr = len0 > len1 ? val1 : val0; + const shorterLen = Math.min(len0, len1); + const last = shorterArr[shorterLen - 1] || { color: [0, 0, 0, 0], offset: 0 }; + for (let i = shorterLen; i < Math.max(len0, len1); i++) { + // Use last color stop to fill the shorter array + shorterArr.push({ + offset: last.offset, + color: last.color.slice() + }); + } +} // arr0 is source array, arr1 is target array. // Do some preprocess to avoid error happened when interpolating from arr0 to arr1 function fillArray( val0: NumberArray | NumberArray[], val1: NumberArray | NumberArray[], - arrDim: number + arrDim: 1 | 2 ) { // TODO Handling different length TypedArray let arr0 = val0 as (number | number[])[]; @@ -132,82 +166,6 @@ function fillArray( } } -function is1DArraySame(arr0: NumberArray, arr1: NumberArray) { - const len = arr0.length; - if (len !== arr1.length) { - return false; - } - for (let i = 0; i < len; i++) { - if (arr0[i] !== arr1[i]) { - return false; - } - } - return true; -} - - -/** - * Catmull Rom interpolate number - */ -function catmullRomInterpolate( - p0: number, p1: number, p2: number, p3: number, t: number, t2: number, t3: number -) { - const v0 = (p2 - p0) * 0.5; - const v1 = (p3 - p1) * 0.5; - return (2 * (p1 - p2) + v0 + v1) * t3 - + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 - + v0 * t + p1; -} -/** - * Catmull Rom interpolate 1D array - */ -function catmullRomInterpolate1DArray( - out: NumberArray, - p0: NumberArray, - p1: NumberArray, - p2: NumberArray, - p3: NumberArray, - t: number, - t2: number, - t3: number -) { - const len = p0.length; - for (let i = 0; i < len; i++) { - out[i] = catmullRomInterpolate( - p0[i], p1[i], p2[i], p3[i], t, t2, t3 - ); - } -} - -/** - * Catmull Rom interpolate 2D array - */ -function catmullRomInterpolate2DArray( - out: NumberArray[], - p0: NumberArray[], - p1: NumberArray[], - p2: NumberArray[], - p3: NumberArray[], - t: number, - t2: number, - t3: number -) { - const len = p0.length; - const len2 = p0[0].length; - for (let i = 0; i < len; i++) { - if (!out[i]) { - out[1] = []; - } - for (let j = 0; j < len2; j++) { - out[i][j] = catmullRomInterpolate( - p0[i][j], p1[i][j], p2[i][j], p3[i][j], - t, t2, t3 - ); - } - } -} - - export function cloneValue(value: InterpolatableType) { if (isArrayLike(value)) { const len = value.length; @@ -226,57 +184,81 @@ export function cloneValue(value: InterpolatableType) { } function rgba2String(rgba: number[]): string { - rgba[0] = Math.floor(rgba[0]); - rgba[1] = Math.floor(rgba[1]); - rgba[2] = Math.floor(rgba[2]); + rgba[0] = Math.floor(rgba[0]) || 0; + rgba[1] = Math.floor(rgba[1]) || 0; + rgba[2] = Math.floor(rgba[2]) || 0; + rgba[3] = rgba[3] == null ? 1 : rgba[3]; return 'rgba(' + rgba.join(',') + ')'; } -function guessArrayDim(value: ArrayLike): number { +function guessArrayDim(value: ArrayLike): 1 | 2 { return isArrayLike(value && (value as ArrayLike)[0]) ? 2 : 1; } +const VALUE_TYPE_NUMBER = 0; +const VALUE_TYPE_1D_ARRAY = 1; +const VALUE_TYPE_2D_ARRAY = 2; +const VALUE_TYPE_COLOR = 3; +const VALUE_TYPE_LINEAR_GRADIENT = 4; +const VALUE_TYPE_RADIAL_GRADIENT = 5; +// Other value type that can only use discrete animation. +const VALUE_TYPE_UNKOWN = 6; + +type ValueType = 0 | 1 | 2 | 3 | 4 | 5 | 6; + type Keyframe = { time: number value: unknown percent: number + // Raw value for discrete animation. + rawValue: unknown + easing?: AnimationEasing // Raw easing + easingFunc?: (percent: number) => number additiveValue?: unknown } + +function isGradientValueType(valType: ValueType): valType is 4 | 5 { + return valType === VALUE_TYPE_LINEAR_GRADIENT || valType === VALUE_TYPE_RADIAL_GRADIENT; +} +function isArrayValueType(valType: ValueType): valType is 1 | 2 { + return valType === VALUE_TYPE_1D_ARRAY || valType === VALUE_TYPE_2D_ARRAY; +} + + let tmpRgba: number[] = [0, 0, 0, 0]; + class Track { keyframes: Keyframe[] = [] - maxTime: number = 0 propName: string - /** - * If use spline interpolate - */ - useSpline: boolean + valType: ValueType - // Larger than 0 if value is array - arrDim: number = 0 - isValueColor: boolean + discrete: boolean = false - interpolable: boolean = true + _invalid: boolean = false; private _finished: boolean private _needsSort: boolean = false - private _isAllValueEqual = true - private _additiveTrack: Track // Temporal storage for interpolated additive value. private _additiveValue: unknown // Info for run - private _lastFrame = 0 - private _lastFramePercent = 0 + /** + * Last frame + */ + private _lastFr = 0 + /** + * Percent of last frame. + */ + private _lastFrP = 0 constructor(propName: string) { this.propName = propName; @@ -296,103 +278,96 @@ class Track { } needsAnimate() { - return !this._isAllValueEqual - && this.keyframes.length >= 2 - && this.interpolable - && this.maxTime > 0; + return this.keyframes.length >= 1; } getAdditiveTrack() { return this._additiveTrack; } - addKeyframe(time: number, value: unknown) { - if (time >= this.maxTime) { - this.maxTime = time; - } - else { - this._needsSort = true; - } + addKeyframe(time: number, rawValue: unknown, easing?: AnimationEasing) { + this._needsSort = true; let keyframes = this.keyframes; - let len = keyframes.length; - if (this.interpolable) { - // Handling values only if it's possible to be interpolated. - if (isArrayLike(value)) { - let arrayDim = guessArrayDim(value); - if (len > 0 && this.arrDim !== arrayDim) { // Two values has differnt dimension. - this.interpolable = false; - return; - } - // Not a number array. - if (arrayDim === 1 && typeof value[0] !== 'number' - || arrayDim === 2 && typeof value[0][0] !== 'number') { - this.interpolable = false; - return; - } - if (len > 0) { - let lastFrame = keyframes[len - 1]; - - // For performance consideration. only check 1d array - if (this._isAllValueEqual) { - if (arrayDim === 1) { - if (!is1DArraySame(value, lastFrame.value as number[])) { - this._isAllValueEqual = false; - } - } - else { - this._isAllValueEqual = false; - } - } - } - this.arrDim = arrayDim; + let discrete = false; + let valType: ValueType = VALUE_TYPE_UNKOWN; + let value = rawValue; + + // Handling values only if it's possible to be interpolated. + if (isArrayLike(rawValue)) { + let arrayDim = guessArrayDim(rawValue); + valType = arrayDim; + // Not a number array. + if (arrayDim === 1 && !isNumber(rawValue[0]) + || arrayDim === 2 && !isNumber(rawValue[0][0])) { + discrete = true; } - else { - if (this.arrDim > 0) { // Previous value is array. - this.interpolable = false; - return; + } + else { + if (isNumber(rawValue) && !eqNaN(rawValue)) { + valType = VALUE_TYPE_NUMBER; + } + else if (isString(rawValue)) { + if (!isNaN(+rawValue)) { // Can be string number like '2' + valType = VALUE_TYPE_NUMBER; } - - if (typeof value === 'string') { - const colorArray = color.parse(value); + else { + const colorArray = color.parse(rawValue); if (colorArray) { value = colorArray; - this.isValueColor = true; - } - else { - this.interpolable = false; + valType = VALUE_TYPE_COLOR; } } - else if (typeof value !== 'number' || isNaN(value)) { - this.interpolable = false; - return; + } + else if (isGradientObject(rawValue)) { + // TODO Color to gradient or gradient to color. + const parsedGradient = extend({}, value) as unknown as ParsedGradientObject; + parsedGradient.colorStops = map(rawValue.colorStops, colorStop => ({ + offset: colorStop.offset, + color: color.parse(colorStop.color) + })); + if (isLinearGradient(rawValue)) { + valType = VALUE_TYPE_LINEAR_GRADIENT; } - - if (this._isAllValueEqual && len > 0) { - let lastFrame = keyframes[len - 1]; - if (this.isValueColor && !is1DArraySame(lastFrame.value as number[], value as number[])) { - this._isAllValueEqual = false; - } - else if (lastFrame.value !== value) { - this._isAllValueEqual = false; - } + else if (isRadialGradient(rawValue)) { + valType = VALUE_TYPE_RADIAL_GRADIENT; } + value = parsedGradient; } } - const kf = { + if (len === 0) { + // Inference type from the first keyframe. + this.valType = valType; + } + // Not same value type or can't be interpolated. + else if (valType !== this.valType || valType === VALUE_TYPE_UNKOWN) { + discrete = true; + } + + this.discrete = this.discrete || discrete; + + const kf: Keyframe = { time, value, + rawValue, percent: 0 }; + if (easing) { + // Save the raw easing name to be used in css animation output + kf.easing = easing; + kf.easingFunc = isFunction(easing) + ? easing + : easingFuncs[easing] || createCubicEasingFunc(easing); + } // Not check if value equal here. - this.keyframes.push(kf); + keyframes.push(kf); return kf; } - prepare(additiveTrack?: Track) { + prepare(maxTime: number, additiveTrack?: Track) { let kfs = this.keyframes; if (this._needsSort) { // Sort keyframe as ascending @@ -401,26 +376,42 @@ class Track { }); } - const arrDim = this.arrDim; + const valType = this.valType; const kfsLen = kfs.length; const lastKf = kfs[kfsLen - 1]; + const isDiscrete = this.discrete; + const isArr = isArrayValueType(valType); + const isGradient = isGradientValueType(valType); for (let i = 0; i < kfsLen; i++) { - kfs[i].percent = kfs[i].time / this.maxTime; - - if (arrDim > 0 && i !== kfsLen - 1) { - // Align array with target frame. - fillArray(kfs[i].value as NumberArray, lastKf.value as NumberArray, arrDim); + const kf = kfs[i]; + const value = kf.value; + const lastValue = lastKf.value; + kf.percent = kf.time / maxTime; + if (!isDiscrete) { + if (isArr && i !== kfsLen - 1) { + // Align array with target frame. + fillArray(value as NumberArray, lastValue as NumberArray, valType); + } + else if (isGradient) { + fillColorStops( + (value as ParsedLinearGradientObject).colorStops, + (lastValue as ParsedLinearGradientObject).colorStops + ); + } } } // Only apply additive animaiton on INTERPOLABLE SAME TYPE values. - if (additiveTrack + if ( + !isDiscrete + // TODO support gradient + && valType !== VALUE_TYPE_RADIAL_GRADIENT + && additiveTrack // If two track both will be animated and have same value format. && this.needsAnimate() && additiveTrack.needsAnimate() - && arrDim === additiveTrack.arrDim - && this.isValueColor === additiveTrack.isValueColor + && valType === additiveTrack.valType && !additiveTrack._finished ) { this._additiveTrack = additiveTrack; @@ -428,30 +419,17 @@ class Track { const startValue = kfs[0].value; // Calculate difference for (let i = 0; i < kfsLen; i++) { - if (arrDim === 0) { - if (this.isValueColor) { - kfs[i].additiveValue = - add1DArray([], kfs[i].value as NumberArray, startValue as NumberArray, -1); - } - else { - kfs[i].additiveValue = kfs[i].value as number - (startValue as number); - } + if (valType === VALUE_TYPE_NUMBER) { + kfs[i].additiveValue = kfs[i].value as number - (startValue as number); } - else if (arrDim === 1) { - kfs[i].additiveValue = add1DArray( - [], - kfs[i].value as NumberArray, - startValue as NumberArray, - -1 - ); + else if (valType === VALUE_TYPE_COLOR) { + kfs[i].additiveValue = + add1DArray([], kfs[i].value as NumberArray, startValue as NumberArray, -1); } - else if (arrDim === 2) { - kfs[i].additiveValue = add2DArray( - [], - kfs[i].value as NumberArray[], - startValue as NumberArray[], - -1 - ); + else if (isArrayValueType(valType)) { + kfs[i].additiveValue = valType === VALUE_TYPE_1D_ARRAY + ? add1DArray([], kfs[i].value as NumberArray, startValue as NumberArray, -1) + : add2DArray([], kfs[i].value as NumberArray[], startValue as NumberArray[], -1); } } } @@ -469,159 +447,149 @@ class Track { const isAdditive = this._additiveTrack != null; const valueKey = isAdditive ? 'additiveValue' : 'value'; + const valType = this.valType; const keyframes = this.keyframes; - const kfsNum = this.keyframes.length; + const kfsNum = keyframes.length; const propName = this.propName; - const arrDim = this.arrDim; - const isValueColor = this.isValueColor; + const isValueColor = valType === VALUE_TYPE_COLOR; // Find the range keyframes // kf1-----kf2---------current--------kf3 // find kf2 and kf3 and do interpolation let frameIdx; - // In the easing function like elasticOut, percent may less than 0 - if (percent < 0) { - frameIdx = 0; + const lastFrame = this._lastFr; + const mathMin = Math.min; + let frame; + let nextFrame; + if (kfsNum === 1) { + frame = nextFrame = keyframes[0]; } - else if (percent < this._lastFramePercent) { - // Start from next key - // PENDING start from lastFrame ? - const start = Math.min(this._lastFrame + 1, kfsNum - 1); - for (frameIdx = start; frameIdx >= 0; frameIdx--) { - if (keyframes[frameIdx].percent <= percent) { - break; + else { + // In the easing function like elasticOut, percent may less than 0 + if (percent < 0) { + frameIdx = 0; + } + else if (percent < this._lastFrP) { + // Start from next key + // PENDING start from lastFrame ? + const start = mathMin(lastFrame + 1, kfsNum - 1); + for (frameIdx = start; frameIdx >= 0; frameIdx--) { + if (keyframes[frameIdx].percent <= percent) { + break; + } } + frameIdx = mathMin(frameIdx, kfsNum - 2); } - // PENDING really need to do this ? - frameIdx = Math.min(frameIdx, kfsNum - 2); - } - else { - for (frameIdx = this._lastFrame; frameIdx < kfsNum; frameIdx++) { - if (keyframes[frameIdx].percent > percent) { - break; + else { + for (frameIdx = lastFrame; frameIdx < kfsNum; frameIdx++) { + if (keyframes[frameIdx].percent > percent) { + break; + } } + frameIdx = mathMin(frameIdx - 1, kfsNum - 2); } - frameIdx = Math.min(frameIdx - 1, kfsNum - 2); + + nextFrame = keyframes[frameIdx + 1]; + frame = keyframes[frameIdx]; } - let nextFrame = keyframes[frameIdx + 1]; - let frame = keyframes[frameIdx]; // Defensive coding. if (!(frame && nextFrame)) { return; } - this._lastFrame = frameIdx; - this._lastFramePercent = percent; + this._lastFr = frameIdx; + this._lastFrP = percent; + const interval = (nextFrame.percent - frame.percent); + let w = interval === 0 ? 1 : mathMin((percent - frame.percent) / interval, 1); - const range = (nextFrame.percent - frame.percent); - if (range === 0) { - return; + // Apply different easing of each keyframe. + // Use easing specified in target frame. + if (nextFrame.easingFunc) { + w = nextFrame.easingFunc(w); } - const w = (percent - frame.percent) / range; // If value is arr let targetArr = isAdditive ? this._additiveValue : (isValueColor ? tmpRgba : target[propName]); - if ((arrDim > 0 || isValueColor) && !targetArr) { + if ((isArrayValueType(valType) || isValueColor) && !targetArr) { targetArr = this._additiveValue = []; } - if (this.useSpline) { - const p1 = keyframes[frameIdx][valueKey]; - const p0 = keyframes[frameIdx === 0 ? frameIdx : frameIdx - 1][valueKey]; - const p2 = keyframes[frameIdx > kfsNum - 2 ? kfsNum - 1 : frameIdx + 1][valueKey]; - const p3 = keyframes[frameIdx > kfsNum - 3 ? kfsNum - 1 : frameIdx + 2][valueKey]; - - if (arrDim > 0) { - arrDim === 1 - ? catmullRomInterpolate1DArray( - targetArr as NumberArray, - p0 as NumberArray, - p1 as NumberArray, - p2 as NumberArray, - p3 as NumberArray, - w, w * w, w * w * w - ) - : catmullRomInterpolate2DArray( - targetArr as NumberArray[], - p0 as NumberArray[], p1 as NumberArray[], p2 as NumberArray[], p3 as NumberArray[], - w, w * w, w * w * w - ); - } - else if (isValueColor) { - catmullRomInterpolate1DArray( - targetArr, - p0 as NumberArray, p1 as NumberArray, p2 as NumberArray, p3 as NumberArray, - w, w * w, w * w * w + + if (this.discrete) { + // use raw value without parse in discrete animation. + target[propName] = w < 1 ? frame.rawValue : nextFrame.rawValue; + } + else if (isArrayValueType(valType)) { + valType === VALUE_TYPE_1D_ARRAY + ? interpolate1DArray( + targetArr as NumberArray, + frame[valueKey] as NumberArray, + nextFrame[valueKey] as NumberArray, + w + ) + : interpolate2DArray( + targetArr as NumberArray[], + frame[valueKey] as NumberArray[], + nextFrame[valueKey] as NumberArray[], + w + ); + } + else if (isGradientValueType(valType)) { + const val = frame[valueKey] as ParsedGradientObject; + const nextVal = nextFrame[valueKey] as ParsedGradientObject; + const isLinearGradient = valType === VALUE_TYPE_LINEAR_GRADIENT; + target[propName] = { + type: isLinearGradient ? 'linear' : 'radial', + x: interpolateNumber(val.x, nextVal.x, w), + y: interpolateNumber(val.y, nextVal.y, w), + // TODO performance + colorStops: map(val.colorStops, (colorStop, idx) => { + const nextColorStop = nextVal.colorStops[idx]; + return { + offset: interpolateNumber(colorStop.offset, nextColorStop.offset, w), + color: rgba2String(interpolate1DArray( + [] as number[], colorStop.color, nextColorStop.color, w + ) as number[]) + }; + }), + global: nextVal.global + }; + if (isLinearGradient) { + // Linear + target[propName].x2 = interpolateNumber( + (val as ParsedLinearGradientObject).x2, (nextVal as ParsedLinearGradientObject).x2, w + ); + target[propName].y2 = interpolateNumber( + (val as ParsedLinearGradientObject).y2, (nextVal as ParsedLinearGradientObject).y2, w ); - if (!isAdditive) { // Convert to string later:) - target[propName] = rgba2String(targetArr); - } } else { - let value; - if (!this.interpolable) { - // String is step(0.5) - // value = step(p1, p2, w); - value = p2; - } - else { - value = catmullRomInterpolate( - p0 as number, p1 as number, p2 as number, p3 as number, - w, w * w, w * w * w - ); - } - if (isAdditive) { - this._additiveValue = value; - } - else { - target[propName] = value; - } + // Radial + target[propName].r = interpolateNumber( + (val as ParsedRadialGradientObject).r, (nextVal as ParsedRadialGradientObject).r, w + ); } } - else { - if (arrDim > 0) { - arrDim === 1 - ? interpolate1DArray( - targetArr as NumberArray, - frame[valueKey] as NumberArray, - nextFrame[valueKey] as NumberArray, - w - ) - : interpolate2DArray( - targetArr as NumberArray[], - frame[valueKey] as NumberArray[], - nextFrame[valueKey] as NumberArray[], - w - ); + else if (isValueColor) { + interpolate1DArray( + targetArr, + frame[valueKey] as NumberArray, + nextFrame[valueKey] as NumberArray, + w + ); + if (!isAdditive) { // Convert to string later:) + target[propName] = rgba2String(targetArr); } - else if (isValueColor) { - interpolate1DArray( - targetArr, - frame[valueKey] as NumberArray, - nextFrame[valueKey] as NumberArray, - w - ); - if (!isAdditive) { // Convert to string later:) - target[propName] = rgba2String(targetArr); - } + } + else { + const value = interpolateNumber(frame[valueKey] as number, nextFrame[valueKey] as number, w); + if (isAdditive) { + this._additiveValue = value; } else { - let value; - if (!this.interpolable) { - // String is step(0.5) - value = step(frame[valueKey], nextFrame[valueKey], w); - } - else { - value = interpolateNumber(frame[valueKey] as number, nextFrame[valueKey] as number, w); - } - if (isAdditive) { - this._additiveValue = value; - } - else { - target[propName] = value; - } + target[propName] = value; } } @@ -632,26 +600,24 @@ class Track { } private _addToTarget(target: any) { - const arrDim = this.arrDim; + const valType = this.valType; const propName = this.propName; const additiveValue = this._additiveValue; - if (arrDim === 0) { - if (this.isValueColor) { - // TODO reduce unnecessary parse - color.parse(target[propName], tmpRgba); - add1DArray(tmpRgba, tmpRgba, additiveValue as NumberArray, 1); - target[propName] = rgba2String(tmpRgba); - } - else { - // Add a difference value based on the change of previous frame. - target[propName] = target[propName] + additiveValue; - } + if (valType === VALUE_TYPE_NUMBER) { + // Add a difference value based on the change of previous frame. + target[propName] = target[propName] + additiveValue; + } + else if (valType === VALUE_TYPE_COLOR) { + // TODO reduce unnecessary parse + color.parse(target[propName], tmpRgba); + add1DArray(tmpRgba, tmpRgba, additiveValue as NumberArray, 1); + target[propName] = rgba2String(tmpRgba); } - else if (arrDim === 1) { + else if (valType === VALUE_TYPE_1D_ARRAY) { add1DArray(target[propName], target[propName], additiveValue as NumberArray, 1); } - else if (arrDim === 2) { + else if (valType === VALUE_TYPE_2D_ARRAY) { add2DArray(target[propName], target[propName], additiveValue as NumberArray[], 1); } } @@ -681,16 +647,30 @@ export default class Animator { private _target: T private _loop: boolean - private _delay = 0 + private _delay: number private _maxTime = 0 - // Some status - private _paused = false + /** + * If force run regardless of empty tracks when duration is set. + */ + private _force: boolean; + + /** + * If animator is paused + * @default false + */ + private _paused: boolean // 0: Not started // 1: Invoked started // 2: Has been run for at least one frame. private _started = 0 + /** + * If allow discrete animation + * @default false + */ + private _allowDiscrete: boolean + private _additiveAnimators: Animator[] private _doneCbs: DoneCallback[] @@ -700,7 +680,12 @@ export default class Animator { private _clip: Clip = null - constructor(target: T, loop: boolean, additiveTo?: Animator[]) { + constructor( + target: T, + loop: boolean, + allowDiscreteAnimation?: boolean, // If doing discrete animation on the values can't be interpolated + additiveTo?: Animator[] + ) { this._target = target; this._loop = loop; if (loop && additiveTo) { @@ -708,6 +693,20 @@ export default class Animator { return; } this._additiveAnimators = additiveTo; + + this._allowDiscrete = allowDiscreteAnimation; + } + + getMaxTime() { + return this._maxTime; + } + + getDelay() { + return this._delay; + } + + getLoop() { + return this._loop; } getTarget() { @@ -725,16 +724,17 @@ export default class Animator { /** * Set Animation keyframe - * @param time 关键帧时间,单位是ms - * @param props 关键帧的属性值,key-value表示 + * @param time time of keyframe in ms + * @param props key-value props of keyframe. + * @param easing */ - when(time: number, props: Dictionary) { - return this.whenWithKeys(time, props, keys(props) as string[]); + when(time: number, props: Dictionary, easing?: AnimationEasing) { + return this.whenWithKeys(time, props, keys(props) as string[], easing); } // Fast path for add keyframes of aniamteTo - whenWithKeys(time: number, props: Dictionary, propNames: string[]) { + whenWithKeys(time: number, props: Dictionary, propNames: string[], easing?: AnimationEasing) { const tracks = this._tracks; for (let i = 0; i < propNames.length; i++) { const propName = propNames[i]; @@ -746,10 +746,11 @@ export default class Animator { let initialValue; const additiveTrack = this._getAdditiveTrack(propName); if (additiveTrack) { - const lastFinalKf = additiveTrack.keyframes[additiveTrack.keyframes.length - 1]; + const addtiveTrackKfs = additiveTrack.keyframes; + const lastFinalKf = addtiveTrackKfs[addtiveTrackKfs.length - 1]; // Use the last state of additived animator. initialValue = lastFinalKf && lastFinalKf.value; - if (additiveTrack.isValueColor && initialValue) { + if (additiveTrack.valType === VALUE_TYPE_COLOR && initialValue) { // Convert to rgba string initialValue = rgba2String(initialValue as number[]); } @@ -762,18 +763,18 @@ export default class Animator { // zrLog('Invalid property ' + propName); continue; } - // If time is 0 + // If time is <= 0 // Then props is given initialize value + // Note: initial percent can be negative, which means the initial value is before the animation start. // Else // Initialize value from current prop value - if (time !== 0) { - track.addKeyframe(0, cloneValue(initialValue)); + if (time > 0) { + track.addKeyframe(0, cloneValue(initialValue), easing); } this._trackKeys.push(propName); } - // PENDING - track.addKeyframe(time, cloneValue(props[propName])); + track.addKeyframe(time, cloneValue(props[propName]), easing); } this._maxTime = Math.max(this._maxTime, time); return this; @@ -793,6 +794,18 @@ export default class Animator { return !!this._paused; } + /** + * Set duration of animator. + * Will run this duration regardless the track max time or if trackes exits. + * @param duration + * @returns + */ + duration(duration: number) { + this._maxTime = duration; + this._force = true; + return this; + } + private _doneCallback() { this._setTracksFinished(); // Clear clip @@ -849,10 +862,9 @@ export default class Animator { /** * Start the animation * @param easing - * @param forceAnimate * @return */ - start(easing?: AnimationEasing, forceAnimate?: boolean) { + start(easing?: AnimationEasing) { if (this._started > 0) { return; } @@ -860,30 +872,37 @@ export default class Animator { const self = this; - let tracks: Track[] = []; + const tracks: Track[] = []; + const maxTime = this._maxTime || 0; for (let i = 0; i < this._trackKeys.length; i++) { const propName = this._trackKeys[i]; const track = this._tracks[propName]; const additiveTrack = this._getAdditiveTrack(propName); const kfs = track.keyframes; - track.prepare(additiveTrack); + const kfsNum = kfs.length; + track.prepare(maxTime, additiveTrack); if (track.needsAnimate()) { - tracks.push(track); - } - else if (!track.interpolable) { - const lastKf = kfs[kfs.length - 1]; - // Set final value. - if (lastKf) { - (self._target as any)[track.propName] = lastKf.value; + // Set value directly if discrete animation is not allowed. + if (!this._allowDiscrete && track.discrete) { + const lastKf = kfs[kfsNum - 1]; + // Set final value. + if (lastKf) { + // use raw value without parse. + (self._target as any)[track.propName] = lastKf.rawValue; + } + track.setFinished(); + } + else { + tracks.push(track); } } } // Add during callback on the last clip - if (tracks.length || forceAnimate) { + if (tracks.length || this._force) { const clip = new Clip({ - life: this._maxTime, + life: maxTime, loop: this._loop, - delay: this._delay, + delay: this._delay || 0, onframe(percent: number) { self._started = 2; // Remove additived animator if it's finished. @@ -907,6 +926,7 @@ export default class Animator { // Because target may be changed. tracks[i].step(self._target, percent); } + const onframeList = self._onframeCbs; if (onframeList) { for (let i = 0; i < onframeList.length; i++) { @@ -924,8 +944,8 @@ export default class Animator { this.animation.addClip(clip); } - if (easing && easing !== 'spline') { - clip.easing = easing; + if (easing) { + clip.setEasing(easing); } } else { @@ -1006,6 +1026,10 @@ export default class Animator { return this._tracks[propName]; } + getTracks() { + return map(this._trackKeys, key => this._tracks[key]); + } + /** * Return true if animator is not available anymore. */ @@ -1018,11 +1042,11 @@ export default class Animator { for (let i = 0; i < propNames.length; i++) { const track = tracks[propNames[i]]; - if (track) { + if (track && !track.isFinished()) { if (forwardToLast) { track.step(this._target, 1); } - // If the track has not been run for at least wrong frame. + // If the track has not been run for at least one frame. // The property may be stayed at the final state. when setToFinal is set true. // For example: // Animate x from 0 to 100, then animate to 150 immediately. @@ -1053,8 +1077,16 @@ export default class Animator { * Save values of final state to target. * It is mainly used in state mangement. When state is switching during animation. * We need to save final state of animation to the normal state. Not interpolated value. + * + * @param target + * @param trackKeys + * @param firstOrLast If save first frame or last frame */ - saveFinalToTarget(target: T, trackKeys?: readonly string[]) { + saveTo( + target: T, + trackKeys?: readonly string[], + firstOrLast?: boolean + ) { if (!target) { // DO nothing if target is not given. return; } @@ -1068,15 +1100,11 @@ export default class Animator { continue; } const kfs = track.keyframes; - const lastKf = kfs[kfs.length - 1]; - if (lastKf) { + const kf = kfs[firstOrLast ? 0 : kfs.length - 1]; + if (kf) { // TODO CLONE? - let val: unknown = cloneValue(lastKf.value as any); - if (track.isValueColor) { - val = rgba2String(val as number[]); - } - - (target as any)[propName] = val; + // Use raw value without parse. + (target as any)[propName] = cloneValue(kf.rawValue as any); } } } @@ -1101,9 +1129,10 @@ export default class Animator { track.addKeyframe(lastKf.time, finalProps[propName]); // Prepare again. - track.prepare(track.getAdditiveTrack()); + track.prepare(this._maxTime, track.getAdditiveTrack()); } } } +} -} \ No newline at end of file +export type AnimatorTrack = Track; \ No newline at end of file diff --git a/src/animation/Clip.ts b/src/animation/Clip.ts index caddaf561..0acf6bf40 100644 --- a/src/animation/Clip.ts +++ b/src/animation/Clip.ts @@ -4,7 +4,6 @@ * @config life(1000) 动画时长 * @config delay(0) 动画延迟时间 * @config loop(true) - * @config gap(0) 循环的间隔时间 * @config onframe * @config easing(optional) * @config ondestroy(optional) @@ -15,6 +14,8 @@ import easingFuncs, {AnimationEasing} from './easing'; import type Animation from './Animation'; +import { isFunction, noop } from '../core/util'; +import { createCubicEasingFunc } from './cubicEasing'; type OnframeCallback = (percent: number) => void; type ondestroyCallback = () => void @@ -27,7 +28,6 @@ export interface ClipProps { life?: number delay?: number loop?: boolean - gap?: number easing?: AnimationEasing onframe?: OnframeCallback @@ -37,13 +37,10 @@ export interface ClipProps { export default class Clip { - // 生命周期 private _life: number - // 延时 private _delay: number - private _initialized: boolean = false - // 开始时间 + private _inited: boolean = false private _startTime = 0 // 开始时间单位毫秒 private _pausedTime = 0 @@ -52,8 +49,9 @@ export default class Clip { animation: Animation loop: boolean - gap: number + easing: AnimationEasing + easingFunc: (p: number) => number // For linked list. Readonly next: Clip @@ -66,29 +64,23 @@ export default class Clip { constructor(opts: ClipProps) { this._life = opts.life || 1000; - this._delay = opts.delay || 0; - // this._startTime = new Date().getTime() + this._delay; - - // 是否循环 - this.loop = opts.loop == null ? false : opts.loop; + this.loop = opts.loop || false; - this.gap = opts.gap || 0; + this.onframe = opts.onframe || noop; + this.ondestroy = opts.ondestroy || noop; + this.onrestart = opts.onrestart || noop; - this.easing = opts.easing || 'linear'; - - this.onframe = opts.onframe; - this.ondestroy = opts.ondestroy; - this.onrestart = opts.onrestart; + opts.easing && this.setEasing(opts.easing); } step(globalTime: number, deltaTime: number): boolean { // Set startTime on first step, or _startTime may has milleseconds different between clips // PENDING - if (!this._initialized) { + if (!this._inited) { this._startTime = globalTime + this._delay; - this._initialized = true; + this._inited = true; } if (this._paused) { @@ -96,7 +88,9 @@ export default class Clip { return; } - let percent = (globalTime - this._startTime - this._pausedTime) / this._life; + const life = this._life; + let elapsedTime = globalTime - this._startTime - this._pausedTime; + let percent = elapsedTime / life; // PENDING: Not begin yet. Still run the loop. // In the case callback needs to be invoked. @@ -108,20 +102,20 @@ export default class Clip { percent = Math.min(percent, 1); - const easing = this.easing; - const easingFunc = typeof easing === 'string' - ? easingFuncs[easing as keyof typeof easingFuncs] : easing; - const schedule = typeof easingFunc === 'function' - ? easingFunc(percent) - : percent; + const easingFunc = this.easingFunc; + const schedule = easingFunc ? easingFunc(percent) : percent; - this.onframe && this.onframe(schedule); + this.onframe(schedule); // 结束 if (percent === 1) { if (this.loop) { - this._restart(globalTime); - this.onrestart && this.onrestart(); + // Restart + const remainder = elapsedTime % life; + this._startTime = globalTime - remainder; + this._pausedTime = 0; + + this.onrestart(); } else { return true; @@ -131,12 +125,6 @@ export default class Clip { return false; } - private _restart(globalTime: number) { - const remainder = (globalTime - this._startTime - this._pausedTime) % this._life; - this._startTime = globalTime - remainder + this.gap; - this._pausedTime = 0; - } - pause() { this._paused = true; } @@ -144,4 +132,11 @@ export default class Clip { resume() { this._paused = false; } + + setEasing(easing: AnimationEasing) { + this.easing = easing; + this.easingFunc = isFunction(easing) + ? easing + : easingFuncs[easing] || createCubicEasingFunc(easing); + } } \ No newline at end of file diff --git a/src/animation/cubicEasing.ts b/src/animation/cubicEasing.ts new file mode 100644 index 000000000..bc5d10e2a --- /dev/null +++ b/src/animation/cubicEasing.ts @@ -0,0 +1,27 @@ +import { cubicAt, cubicRootAt } from '../core/curve'; +import { trim } from '../core/util'; + +const regexp = /cubic-bezier\(([0-9,\.e ]+)\)/; + +export function createCubicEasingFunc(cubicEasingStr: string) { + const cubic = cubicEasingStr && regexp.exec(cubicEasingStr); + if (cubic) { + const points = cubic[1].split(','); + const a = +trim(points[0]); + const b = +trim(points[1]); + const c = +trim(points[2]); + const d = +trim(points[3]); + + if (isNaN(a + b + c + d)) { + return; + } + + const roots: number[] = []; + return (p: number) => { + return p <= 0 + ? 0 : p >= 1 + ? 1 + : cubicRootAt(0, a, c, 1, p, roots) && cubicAt(0, b, d, 1, roots[0]); + }; + } +} \ No newline at end of file diff --git a/src/animation/easing.ts b/src/animation/easing.ts index b6e75f7ee..e240ee18d 100644 --- a/src/animation/easing.ts +++ b/src/animation/easing.ts @@ -6,9 +6,9 @@ type easingFunc = (percent: number) => number; -export type AnimationEasing = keyof typeof easing | easingFunc | 'spline'; +export type AnimationEasing = keyof typeof easingFuncs | easingFunc; -const easing = { +const easingFuncs = { /** * @param {number} k * @return {number} @@ -315,7 +315,7 @@ const easing = { * @return {number} */ bounceIn(k: number) { - return 1 - easing.bounceOut(1 - k); + return 1 - easingFuncs.bounceOut(1 - k); }, /** * @param {number} k @@ -341,10 +341,11 @@ const easing = { */ bounceInOut(k: number) { if (k < 0.5) { - return easing.bounceIn(k * 2) * 0.5; + return easingFuncs.bounceIn(k * 2) * 0.5; } - return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5; + return easingFuncs.bounceOut(k * 2 - 1) * 0.5 + 0.5; } }; -export default easing; \ No newline at end of file + +export default easingFuncs; \ No newline at end of file diff --git a/src/animation/requestAnimationFrame.ts b/src/animation/requestAnimationFrame.ts index 11b6c728d..629ce7616 100644 --- a/src/animation/requestAnimationFrame.ts +++ b/src/animation/requestAnimationFrame.ts @@ -1,14 +1,17 @@ +import env from '../core/env'; + type RequestAnimationFrameType = typeof window.requestAnimationFrame let requestAnimationFrame: RequestAnimationFrameType; requestAnimationFrame = ( - typeof window !== 'undefined' + env.hasGlobalWindow && ( (window.requestAnimationFrame && window.requestAnimationFrame.bind(window)) // https://github.com/ecomfe/zrender/issues/189#issuecomment-224919809 || ((window as any).msRequestAnimationFrame && (window as any).msRequestAnimationFrame.bind(window)) || (window as any).mozRequestAnimationFrame + // @ts-ignore || window.webkitRequestAnimationFrame ) ) || function (func: Parameters[0]): number { diff --git a/src/canvas/Layer.ts b/src/canvas/Layer.ts index 2e76a71e1..100ea80b9 100644 --- a/src/canvas/Layer.ts +++ b/src/canvas/Layer.ts @@ -11,13 +11,10 @@ import { createCanvasPattern } from './graphic'; import Displayable from '../graphic/Displayable'; import BoundingRect from '../core/BoundingRect'; import { REDRAW_BIT } from '../graphic/constants'; - -function returnFalse() { - return false; -} +import { platformApi } from '../core/platform'; function createDom(id: string, painter: CanvasPainter, dpr: number) { - const newDom = util.createCanvas(); + const newDom = platformApi.createCanvas(); const width = painter.getWidth(); const height = painter.getHeight(); @@ -127,23 +124,15 @@ export default class Layer extends Eventful { const domStyle = dom.style; if (domStyle) { // Not in node - dom.onselectstart = returnFalse; // 避免页面选中的尴尬 - domStyle.webkitUserSelect = 'none'; - domStyle.userSelect = 'none'; - domStyle.webkitTapHighlightColor = 'rgba(0,0,0,0)'; - (domStyle as any)['-webkit-touch-callout'] = 'none'; + util.disableUserSelect(dom); + dom.onselectstart = () => false; domStyle.padding = '0'; domStyle.margin = '0'; domStyle.borderWidth = '0'; } - this.domBack = null; - this.ctxBack = null; - this.painter = painter; - this.config = null; - this.dpr = dpr; } diff --git a/src/canvas/Painter.ts b/src/canvas/Painter.ts index 5f69a4427..4bc818182 100644 --- a/src/canvas/Painter.ts +++ b/src/canvas/Painter.ts @@ -2,19 +2,18 @@ import {devicePixelRatio} from '../config'; import * as util from '../core/util'; import Layer, { LayerConfig } from './Layer'; import requestAnimationFrame from '../animation/requestAnimationFrame'; -import ZRImage from '../graphic/Image'; import env from '../core/env'; import Displayable from '../graphic/Displayable'; -import { WXCanvasRenderingContext, ZRCanvasRenderingContext } from '../core/types'; +import { WXCanvasRenderingContext } from '../core/types'; import { GradientObject } from '../graphic/Gradient'; import { ImagePatternObject } from '../graphic/Pattern'; import Storage from '../Storage'; import { brush, BrushScope, brushSingle } from './graphic'; import { PainterBase } from '../PainterBase'; import BoundingRect from '../core/BoundingRect'; -import IncrementalDisplayable from '../graphic/IncrementalDisplayable'; -import Path from '../graphic/Path'; import { REDRAW_BIT } from '../graphic/constants'; +import { getSize } from './helper'; +import type IncrementalDisplayable from '../graphic/IncrementalDisplayable'; const HOVER_LAYER_ZLEVEL = 1e5; const CANVAS_ZLEVEL = 314159; @@ -22,9 +21,6 @@ const CANVAS_ZLEVEL = 314159; const EL_AFTER_INCREMENTAL_INC = 0.01; const INCREMENTAL_INC = 0.001; -function parseInt10(val: string) { - return parseInt(val, 10); -} function isLayerValid(layer: Layer) { if (!layer) { @@ -141,11 +137,8 @@ export default class CanvasPainter implements PainterBase { const rootStyle = root.style; if (rootStyle) { - rootStyle.webkitTapHighlightColor = 'transparent'; - rootStyle.webkitUserSelect = 'none'; - rootStyle.userSelect = 'none'; - (rootStyle as any)['-webkit-touch-callout'] = 'none'; - + // @ts-ignore + util.disableUserSelect(root); root.innerHTML = ''; } @@ -161,8 +154,8 @@ export default class CanvasPainter implements PainterBase { const layers = this._layers; if (!singleCanvas) { - this._width = this._getSize(0); - this._height = this._getSize(1); + this._width = getSize(root, 0, opts); + this._height = getSize(root, 1, opts); const domRoot = this._domRoot = createRoot( this._width, this._height @@ -401,7 +394,7 @@ export default class CanvasPainter implements PainterBase { const clearColor = layer.zlevel === this._zlevelList[0] ? this._backgroundColor : null; - // All elements in this layer are cleared. + // All elements in this layer are removed. if (layer.__startIndex === layer.__endIndex) { layer.clear(false, clearColor, repaintRects); } @@ -576,12 +569,16 @@ export default class CanvasPainter implements PainterBase { let i = -1; if (layersMap[zlevel]) { - util.logError('ZLevel ' + zlevel + ' has been used already'); + if (process.env.NODE_ENV !== 'production') { + util.logError('ZLevel ' + zlevel + ' has been used already'); + } return; } // Check if is a valid layer if (!isLayerValid(layer)) { - util.logError('Layer of zlevel ' + zlevel + ' is not valid'); + if (process.env.NODE_ENV !== 'production') { + util.logError('Layer of zlevel ' + zlevel + ' is not valid'); + } return; } @@ -860,11 +857,12 @@ export default class CanvasPainter implements PainterBase { // Save input w/h const opts = this._opts; + const root = this.root; width != null && (opts.width = width); height != null && (opts.height = height); - width = this._getSize(0); - height = this._getSize(1); + width = getSize(root, 0, opts); + height = getSize(root, 1, opts); domRoot.style.display = ''; @@ -976,88 +974,4 @@ export default class CanvasPainter implements PainterBase { getHeight() { return this._height; } - - _getSize(whIdx: number) { - const opts = this._opts; - const wh = ['width', 'height'][whIdx] as 'width' | 'height'; - const cwh = ['clientWidth', 'clientHeight'][whIdx] as 'clientWidth' | 'clientHeight'; - const plt = ['paddingLeft', 'paddingTop'][whIdx] as 'paddingLeft' | 'paddingTop'; - const prb = ['paddingRight', 'paddingBottom'][whIdx] as 'paddingRight' | 'paddingBottom'; - - if (opts[wh] != null && opts[wh] !== 'auto') { - return parseFloat(opts[wh] as string); - } - - const root = this.root; - // IE8 does not support getComputedStyle, but it use VML. - const stl = document.defaultView.getComputedStyle(root); - - return ( - (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) - - (parseInt10(stl[plt]) || 0) - - (parseInt10(stl[prb]) || 0) - ) | 0; - } - - pathToImage(path: Path, dpr?: number): ZRImage { - dpr = dpr || this.dpr; - - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - const rect = path.getBoundingRect(); - const style = path.style; - const shadowBlurSize = style.shadowBlur * dpr; - const shadowOffsetX = style.shadowOffsetX * dpr; - const shadowOffsetY = style.shadowOffsetY * dpr; - const lineWidth = path.hasStroke() ? style.lineWidth : 0; - - const leftMargin = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize); - const rightMargin = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize); - const topMargin = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize); - const bottomMargin = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize); - const width = rect.width + leftMargin + rightMargin; - const height = rect.height + topMargin + bottomMargin; - - canvas.width = width * dpr; - canvas.height = height * dpr; - - ctx.scale(dpr, dpr); - ctx.clearRect(0, 0, width, height); - (ctx as ZRCanvasRenderingContext).dpr = dpr; - - const pathTransform = { - x: path.x, - y: path.y, - scaleX: path.scaleX, - scaleY: path.scaleY, - rotation: path.rotation, - originX: path.originX, - originY: path.originY - }; - path.x = leftMargin - rect.x; - path.y = topMargin - rect.y; - path.rotation = 0; - path.scaleX = 1; - path.scaleY = 1; - path.updateTransform(); - if (path) { - brush(ctx, path, { - inHover: false, - viewWidth: this._width, - viewHeight: this._height - }, true); - } - - const imgShape = new ZRImage({ - style: { - x: 0, - y: 0, - image: canvas - } - }); - - util.extend(path, pathTransform); - - return imgShape; - } }; \ No newline at end of file diff --git a/src/canvas/dashStyle.ts b/src/canvas/dashStyle.ts new file mode 100644 index 000000000..657eb36d4 --- /dev/null +++ b/src/canvas/dashStyle.ts @@ -0,0 +1,32 @@ +import { isArray, isNumber, map } from '../core/util'; +import Path from '../graphic/Path'; +import TSpan from '../graphic/TSpan'; + +export function normalizeLineDash(lineType: any, lineWidth?: number): number[] | false { + if (!lineType || lineType === 'solid' || !(lineWidth > 0)) { + return null; + } + return lineType === 'dashed' + ? [4 * lineWidth, 2 * lineWidth] + : lineType === 'dotted' + ? [lineWidth] + : isNumber(lineType) + ? [lineType] : isArray(lineType) ? lineType : null; +} +export function getLineDash(el: Path | TSpan): [number[] | false, number] { + const style = el.style; + + let lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth); + let lineDashOffset = style.lineDashOffset; + + if (lineDash) { + const lineScale = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1; + if (lineScale && lineScale !== 1) { + lineDash = map(lineDash, function (rawVal) { + return rawVal / lineScale; + }); + lineDashOffset /= lineScale; + } + } + return [lineDash, lineDashOffset]; +} \ No newline at end of file diff --git a/src/canvas/graphic.ts b/src/canvas/graphic.ts index a16d9d3d5..a6effc80f 100644 --- a/src/canvas/graphic.ts +++ b/src/canvas/graphic.ts @@ -10,12 +10,12 @@ import { getCanvasGradient, isClipPathChanged } from './helper'; import Path, { PathStyleProps } from '../graphic/Path'; import ZRImage, { ImageStyleProps } from '../graphic/Image'; import TSpan, {TSpanStyleProps} from '../graphic/TSpan'; -import { DEFAULT_FONT } from '../contain/text'; import { MatrixArray } from '../core/matrix'; -import { map } from '../core/util'; -import { normalizeLineDash } from '../graphic/helper/dashStyle'; -import IncrementalDisplayable from '../graphic/IncrementalDisplayable'; +import { RADIAN_TO_DEGREE } from '../core/util'; +import { getLineDash } from './dashStyle'; import { REDRAW_BIT, SHAPE_CHANGED_BIT } from '../graphic/constants'; +import type IncrementalDisplayable from '../graphic/IncrementalDisplayable'; +import { DEFAULT_FONT } from '../core/platform'; const pathProxyForDraw = new PathProxy(true); @@ -79,7 +79,7 @@ export function createCanvasPattern( ) { const matrix = new DOMMatrix(); matrix.translateSelf((pattern.x || 0), (pattern.y || 0)); - matrix.rotateSelf(0, 0, (pattern.rotation || 0) / Math.PI * 180); + matrix.rotateSelf(0, 0, (pattern.rotation || 0) * RADIAN_TO_DEGREE); matrix.scaleSelf((pattern.scaleX || 1), (pattern.scaleY || 1)); canvasPattern.setTransform(matrix); } @@ -105,6 +105,7 @@ function brushPath(ctx: CanvasRenderingContext2D, el: Path, style: PathStyleProp } const path = el.path || pathProxyForDraw; + const dirtyFlag = el.__dirty; if (!inBatch) { const fill = style.fill; @@ -123,9 +124,10 @@ function brushPath(ctx: CanvasRenderingContext2D, el: Path, style: PathStyleProp if (hasFillGradient || hasStrokeGradient) { rect = el.getBoundingRect(); } + // Update gradient because bounding rect may changed if (hasFillGradient) { - fillGradient = el.__dirty + fillGradient = dirtyFlag ? getCanvasGradient(ctx, fill as (LinearGradientObject | RadialGradientObject), rect) : el.__canvasFillGradient; // No need to clear cache when fill is not gradient. @@ -133,21 +135,21 @@ function brushPath(ctx: CanvasRenderingContext2D, el: Path, style: PathStyleProp el.__canvasFillGradient = fillGradient; } if (hasStrokeGradient) { - strokeGradient = el.__dirty + strokeGradient = dirtyFlag ? getCanvasGradient(ctx, stroke as (LinearGradientObject | RadialGradientObject), rect) : el.__canvasStrokeGradient; el.__canvasStrokeGradient = strokeGradient; } if (hasFillPattern) { // Pattern might be null if image not ready (even created from dataURI) - fillPattern = (el.__dirty || !el.__canvasFillPattern) + fillPattern = (dirtyFlag || !el.__canvasFillPattern) ? createCanvasPattern(ctx, fill as ImagePatternObject, el) : el.__canvasFillPattern; el.__canvasFillPattern = fillPattern; } if (hasStrokePattern) { // Pattern might be null if image not ready (even created from dataURI) - strokePattern = (el.__dirty || !el.__canvasStrokePattern) + strokePattern = (dirtyFlag || !el.__canvasStrokePattern) ? createCanvasPattern(ctx, stroke as ImagePatternObject, el) : el.__canvasStrokePattern; el.__canvasStrokePattern = fillPattern; @@ -180,34 +182,19 @@ function brushPath(ctx: CanvasRenderingContext2D, el: Path, style: PathStyleProp } } - let lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth); - let lineDashOffset = style.lineDashOffset; - - const ctxLineDash = !!ctx.setLineDash; - // Update path sx, sy const scale = el.getGlobalScale(); path.setScale(scale[0], scale[1], el.segmentIgnoreThreshold); - if (lineDash) { - const lineScale = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1; - if (lineScale && lineScale !== 1) { - lineDash = map(lineDash, function (rawVal) { - return rawVal / lineScale; - }); - lineDashOffset /= lineScale; - } + let lineDash; + let lineDashOffset; + if (ctx.setLineDash && style.lineDash) { + [lineDash, lineDashOffset] = getLineDash(el); } let needsRebuild = true; - // Proxy context - // Rebuild path in following 2 cases - // 1. Path is dirty - // 2. Path needs javascript implemented lineDash stroking. - // In this case, lineDash information will not be saved in PathProxy - if (firstDraw || (el.__dirty & SHAPE_CHANGED_BIT) - || (lineDash && !ctxLineDash && hasStroke) - ) { + + if (firstDraw || (dirtyFlag & SHAPE_CHANGED_BIT)) { path.setDPR((ctx as any).dpr); if (strokePart) { // Use rebuildPath for percent stroke, so no context. @@ -219,12 +206,6 @@ function brushPath(ctx: CanvasRenderingContext2D, el: Path, style: PathStyleProp } path.reset(); - // Setting line dash before build path - if (lineDash && !ctxLineDash) { - path.setLineDash(lineDash); - path.setLineDashOffset(lineDashOffset); - } - el.buildPath(path, el.shape, inBatch); path.toStatic(); @@ -237,7 +218,7 @@ function brushPath(ctx: CanvasRenderingContext2D, el: Path, style: PathStyleProp path.rebuildPath(ctx, strokePart ? strokePercent : 1); } - if (lineDash && ctxLineDash) { + if (lineDash) { ctx.setLineDash(lineDash); ctx.lineDashOffset = lineDashOffset; } @@ -261,7 +242,7 @@ function brushPath(ctx: CanvasRenderingContext2D, el: Path, style: PathStyleProp } } - if (lineDash && ctxLineDash) { + if (lineDash) { // PENDING // Remove lineDash ctx.setLineDash([]); @@ -335,23 +316,15 @@ function brushText(ctx: CanvasRenderingContext2D, el: TSpan, style: TSpanStylePr ctx.textAlign = style.textAlign; ctx.textBaseline = style.textBaseline; - let hasLineDash; - if (ctx.setLineDash) { - let lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth); - let lineDashOffset = style.lineDashOffset; - if (lineDash) { - const lineScale = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1; - if (lineScale && lineScale !== 1) { - lineDash = map(lineDash, function (rawVal) { - return rawVal / lineScale; - }); - lineDashOffset /= lineScale; - } - ctx.setLineDash(lineDash); - ctx.lineDashOffset = lineDashOffset; - - hasLineDash = true; - } + let lineDash; + let lineDashOffset; + if (ctx.setLineDash && style.lineDash) { + [lineDash, lineDashOffset] = getLineDash(el); + } + + if (lineDash) { + ctx.setLineDash(lineDash); + ctx.lineDashOffset = lineDashOffset; } if (style.strokeFirst) { @@ -371,7 +344,7 @@ function brushText(ctx: CanvasRenderingContext2D, el: TSpan, style: TSpanStylePr } } - if (hasLineDash) { + if (lineDash) { // Remove lineDash ctx.setLineDash([]); } @@ -772,13 +745,14 @@ export function brush( bindImageStyle(ctx, el as ZRImage, prevEl as ZRImage, forceSetStyle, scope); brushImage(ctx, el as ZRImage, style); } - else if (el instanceof IncrementalDisplayable) { + // Assume it's a IncrementalDisplayable + else if ((el as IncrementalDisplayable).getTemporalDisplayables) { if (scope.lastDrawType !== DRAW_TYPE_INCREMENTAL) { forceSetStyle = true; scope.lastDrawType = DRAW_TYPE_INCREMENTAL; } - brushIncremental(ctx, el, scope); + brushIncremental(ctx, el as IncrementalDisplayable, scope); } } diff --git a/src/canvas/helper.ts b/src/canvas/helper.ts index 598dfd68d..ec6cb721e 100644 --- a/src/canvas/helper.ts +++ b/src/canvas/helper.ts @@ -86,4 +86,32 @@ export function isClipPathChanged(clipPaths: Path[], prevClipPaths: Path[]): boo } } return false; +} + +function parseInt10(val: string) { + return parseInt(val, 10); +} +export function getSize( + root: HTMLElement, + whIdx: number, + opts: { width?: number | string, height?: number | string} +) { + + const wh = ['width', 'height'][whIdx] as 'width' | 'height'; + const cwh = ['clientWidth', 'clientHeight'][whIdx] as 'clientWidth' | 'clientHeight'; + const plt = ['paddingLeft', 'paddingTop'][whIdx] as 'paddingLeft' | 'paddingTop'; + const prb = ['paddingRight', 'paddingBottom'][whIdx] as 'paddingRight' | 'paddingBottom'; + + if (opts[wh] != null && opts[wh] !== 'auto') { + return parseFloat(opts[wh] as string); + } + + // IE8 does not support getComputedStyle, but it use VML. + const stl = document.defaultView.getComputedStyle(root); + + return ( + (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) + - (parseInt10(stl[plt]) || 0) + - (parseInt10(stl[prb]) || 0) + ) | 0; } \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 7be4a7898..fe7528abe 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +1,9 @@ +import env from './core/env'; + let dpr = 1; // If in browser environment -if (typeof window !== 'undefined') { +if (env.hasGlobalWindow) { dpr = Math.max( window.devicePixelRatio || (window.screen && (window.screen as any).deviceXDPI / (window.screen as any).logicalXDPI) diff --git a/src/contain/text.ts b/src/contain/text.ts index 6b95b7a59..c799f67fc 100644 --- a/src/contain/text.ts +++ b/src/contain/text.ts @@ -1,41 +1,10 @@ import BoundingRect, { RectLike } from '../core/BoundingRect'; -import { createCanvas } from '../core/util'; -import { Dictionary, PropType, TextAlign, TextVerticalAlign, BuiltinTextPosition } from '../core/types'; +import { Dictionary, TextAlign, TextVerticalAlign, BuiltinTextPosition } from '../core/types'; import LRU from '../core/LRU'; +import { DEFAULT_FONT, platformApi } from '../core/platform'; let textWidthCache: Dictionary> = {}; -export const DEFAULT_FONT = '12px sans-serif'; - -let _ctx: CanvasRenderingContext2D; -let _cachedFont: string; - -function defaultMeasureText(text: string, font?: string): { width: number } { - if (!_ctx) { - _ctx = createCanvas().getContext('2d'); - } - if (_cachedFont !== font) { - _cachedFont = _ctx.font = font || DEFAULT_FONT; - } - return _ctx.measureText(text); -} - -let methods: { - measureText: (text: string, font?: string) => { width: number } -} = { - measureText: defaultMeasureText -}; - -export function $override( - name: keyof typeof methods, - fn: PropType -) { - methods[name] = fn; -} - -// let cacheMissCount = 0; -// let totalCount = 0; - export function getWidth(text: string, font: string): number { font = font || DEFAULT_FONT; let cacheOfFont = textWidthCache[font]; @@ -44,11 +13,9 @@ export function getWidth(text: string, font: string): number { } let width = cacheOfFont.get(text); if (width == null) { - width = methods.measureText(text, font).width; + width = platformApi.measureText(text, font).width; cacheOfFont.put(text, width); - // cacheMissCount++; } - // totalCount++; return width; } @@ -131,7 +98,7 @@ export function getLineHeight(font?: string): number { export function measureText(text: string, font?: string): { width: number } { - return methods.measureText(text, font); + return platformApi.measureText(text, font); } diff --git a/src/core/PathProxy.ts b/src/core/PathProxy.ts index 0d520d891..f0331f947 100644 --- a/src/core/PathProxy.ts +++ b/src/core/PathProxy.ts @@ -11,7 +11,7 @@ import * as vec2 from './vector'; import BoundingRect from './BoundingRect'; import {devicePixelRatio as dpr} from '../config'; import { fromLine, fromCubic, fromQuadratic, fromArc } from './bbox'; -import { cubicAt, cubicLength, cubicSubdivide, quadraticLength, quadraticSubdivide } from './curve'; +import { cubicLength, cubicSubdivide, quadraticLength, quadraticSubdivide } from './curve'; const CMD = { M: 1, @@ -49,7 +49,6 @@ const mathMin = Math.min; const mathMax = Math.max; const mathCos = Math.cos; const mathSin = Math.sin; -const mathSqrt = Math.sqrt; const mathAbs = Math.abs; const PI = Math.PI; @@ -147,13 +146,6 @@ export default class PathProxy { private _ux: number private _uy: number - // For dash shim. - private _lineDash: number[] - private _needsDash: boolean - private _dashOffset: number - private _dashIdx: number - private _dashSum: number - static CMD = CMD constructor(notSaveData?: boolean) { @@ -217,11 +209,6 @@ export default class PathProxy { this._len = 0; } - if (this._lineDash) { - this._lineDash = null; - this._dashOffset = 0; - } - if (this._pathSegLen) { this._pathSegLen = null; this._pathLen = 0; @@ -259,8 +246,7 @@ export default class PathProxy { this.addData(CMD.L, x, y); if (this._ctx && exceedUnit) { - this._needsDash ? this._dashedLineTo(x, y) - : this._ctx.lineTo(x, y); + this._ctx.lineTo(x, y); } if (exceedUnit) { this._xi = x; @@ -285,8 +271,7 @@ export default class PathProxy { this.addData(CMD.C, x1, y1, x2, y2, x3, y3); if (this._ctx) { - this._needsDash ? this._dashedBezierTo(x1, y1, x2, y2, x3, y3) - : this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); } this._xi = x3; this._yi = y3; @@ -298,8 +283,7 @@ export default class PathProxy { this.addData(CMD.Q, x1, y1, x2, y2); if (this._ctx) { - this._needsDash ? this._dashedQuadraticTo(x1, y1, x2, y2) - : this._ctx.quadraticCurveTo(x1, y1, x2, y2); + this._ctx.quadraticCurveTo(x1, y1, x2, y2); } this._xi = x2; this._yi = y2; @@ -358,7 +342,6 @@ export default class PathProxy { const x0 = this._x0; const y0 = this._y0; if (ctx) { - this._needsDash && this._dashedLineTo(x0, y0); ctx.closePath(); } @@ -377,41 +360,6 @@ export default class PathProxy { this.toStatic(); } - /** - * 必须在其它绘制命令前调用 - * Must be invoked before all other path drawing methods - */ - setLineDash(lineDash: number[] | false) { - if (lineDash instanceof Array) { - this._lineDash = lineDash; - - this._dashIdx = 0; - - let lineDashSum = 0; - for (let i = 0; i < lineDash.length; i++) { - lineDashSum += lineDash[i]; - } - this._dashSum = lineDashSum; - - this._needsDash = true; - } - else { - // Clear - this._lineDash = null; - this._needsDash = false; - } - return this; - } - - /** - * 必须在其它绘制命令前调用 - * Must be invoked before all other path drawing methods - */ - setLineDashOffset(offset: number) { - this._dashOffset = offset; - return this; - } - len() { return this._len; } @@ -502,135 +450,6 @@ export default class PathProxy { } } - private _dashedLineTo(x1: number, y1: number) { - const dashSum = this._dashSum; - const lineDash = this._lineDash; - const ctx = this._ctx; - let offset = this._dashOffset; - - let x0 = this._xi; - let y0 = this._yi; - let dx = x1 - x0; - let dy = y1 - y0; - let dist = mathSqrt(dx * dx + dy * dy); - let x = x0; - let y = y0; - let nDash = lineDash.length; - let dash; - let idx; - dx /= dist; - dy /= dist; - - if (offset < 0) { - // Convert to positive offset - offset = dashSum + offset; - } - offset %= dashSum; - x -= offset * dx; - y -= offset * dy; - - while ((dx > 0 && x <= x1) || (dx < 0 && x >= x1) - || (dx === 0 && ((dy > 0 && y <= y1) || (dy < 0 && y >= y1)))) { - idx = this._dashIdx; - dash = lineDash[idx]; - x += dx * dash; - y += dy * dash; - this._dashIdx = (idx + 1) % nDash; - // Skip positive offset - if ((dx > 0 && x < x0) || (dx < 0 && x > x0) || (dy > 0 && y < y0) || (dy < 0 && y > y0)) { - continue; - } - ctx[idx % 2 ? 'moveTo' : 'lineTo']( - dx >= 0 ? mathMin(x, x1) : mathMax(x, x1), - dy >= 0 ? mathMin(y, y1) : mathMax(y, y1) - ); - } - // Offset for next lineTo - dx = x - x1; - dy = y - y1; - this._dashOffset = -mathSqrt(dx * dx + dy * dy); - } - - // Not accurate dashed line to - private _dashedBezierTo(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number) { - const ctx = this._ctx; - - let dashSum = this._dashSum; - let offset = this._dashOffset; - let lineDash = this._lineDash; - - let x0 = this._xi; - let y0 = this._yi; - let bezierLen = 0; - let idx = this._dashIdx; - let nDash = lineDash.length; - - let t; - let dx; - let dy; - - let x; - let y; - - let tmpLen = 0; - - if (offset < 0) { - // Convert to positive offset - offset = dashSum + offset; - } - offset %= dashSum; - // Bezier approx length - for (t = 0; t < 1; t += 0.1) { - dx = cubicAt(x0, x1, x2, x3, t + 0.1) - - cubicAt(x0, x1, x2, x3, t); - dy = cubicAt(y0, y1, y2, y3, t + 0.1) - - cubicAt(y0, y1, y2, y3, t); - bezierLen += mathSqrt(dx * dx + dy * dy); - } - - // Find idx after add offset - for (; idx < nDash; idx++) { - tmpLen += lineDash[idx]; - if (tmpLen > offset) { - break; - } - } - t = (tmpLen - offset) / bezierLen; - - while (t <= 1) { - - x = cubicAt(x0, x1, x2, x3, t); - y = cubicAt(y0, y1, y2, y3, t); - - // Use line to approximate dashed bezier - // Bad result if dash is long - idx % 2 ? ctx.moveTo(x, y) - : ctx.lineTo(x, y); - - t += lineDash[idx] / bezierLen; - - idx = (idx + 1) % nDash; - } - - // Finish the last segment and calculate the new offset - (idx % 2 !== 0) && ctx.lineTo(x3, y3); - dx = x3 - x; - dy = y3 - y; - this._dashOffset = -mathSqrt(dx * dx + dy * dy); - } - - private _dashedQuadraticTo(x1: number, y1: number, x2: number, y2: number) { - // Convert quadratic to cubic using degree elevation - const x3 = x2; - const y3 = y2; - x2 = (x2 + 2 * x1) / 3; - y2 = (y2 + 2 * y1) / 3; - x1 = (this._xi + 2 * x1) / 3; - y1 = (this._yi + 2 * y1) / 3; - - this._dashedBezierTo(x1, y1, x2, y2, x3, y3); - } - /** * Convert dynamic array to static Float32Array * @@ -1156,10 +975,6 @@ export default class PathProxy { private static initDefaultProps = (function () { const proto = PathProxy.prototype; proto._saveData = true; - proto._needsDash = false; - proto._dashOffset = 0; - proto._dashIdx = 0; - proto._dashSum = 0; proto._ux = 0; proto._uy = 0; proto._pendingPtDist = 0; diff --git a/src/core/Transformable.ts b/src/core/Transformable.ts index b8d7b63ba..0ab5ce796 100644 --- a/src/core/Transformable.ts +++ b/src/core/Transformable.ts @@ -28,6 +28,12 @@ class Transformable { skewY: number rotation: number + + /** + * Will translated the element to the anchor position before applying other transforms. + */ + anchorX: number + anchorY: number /** * Origin of scale, rotation, skew */ @@ -88,7 +94,9 @@ class Transformable { || isNotAroundZero(this.x) || isNotAroundZero(this.y) || isNotAroundZero(this.scaleX - 1) - || isNotAroundZero(this.scaleY - 1); + || isNotAroundZero(this.scaleY - 1) + || isNotAroundZero(this.skewX) + || isNotAroundZero(this.skewY); } /** @@ -280,12 +288,7 @@ class Transformable { } copyTransform(source: Transformable) { - const target = this; - - for (let i = 0; i < TRANSFORMABLE_PROPS.length; i++) { - const propName = TRANSFORMABLE_PROPS[i]; - target[propName] = source[propName]; - } + copyTransform(this, source); } @@ -296,6 +299,8 @@ class Transformable { const oy = target.originY || 0; const sx = target.scaleX; const sy = target.scaleY; + const ax = target.anchorX; + const ay = target.anchorY; const rotation = target.rotation || 0; const x = target.x; const y = target.y; @@ -303,12 +308,14 @@ class Transformable { // TODO: zrender use different hand in coordinate system and y axis is inversed. const skewY = target.skewY ? Math.tan(-target.skewY) : 0; - // The order of transform (-origin * scale * skew * rotate * origin * translate). + // The order of transform (-anchor * -origin * scale * skew * rotate * origin * translate). // We merge (-origin * scale * skew) into one. Also did identity in these operations. // origin - if (ox || oy) { - m[4] = -ox * sx - skewX * oy * sy; - m[5] = -oy * sy - skewY * ox * sx; + if (ox || oy || ax || ay) { + const dx = ox + ax; + const dy = oy + ay; + m[4] = -dx * sx - skewX * dy * sy; + m[5] = -dy * sy - skewY * dx * sx; } else { m[4] = m[5] = 0; @@ -332,21 +339,35 @@ class Transformable { private static initDefaultProps = (function () { const proto = Transformable.prototype; - proto.x = 0; - proto.y = 0; - proto.scaleX = 1; - proto.scaleY = 1; - proto.originX = 0; - proto.originY = 0; - proto.skewX = 0; - proto.skewY = 0; - proto.rotation = 0; + proto.scaleX = + proto.scaleY = proto.globalScaleRatio = 1; + proto.x = + proto.y = + proto.originX = + proto.originY = + proto.skewX = + proto.skewY = + proto.rotation = + proto.anchorX = + proto.anchorY = 0; })() }; export const TRANSFORMABLE_PROPS = [ - 'x', 'y', 'originX', 'originY', 'rotation', 'scaleX', 'scaleY', 'skewX', 'skewY' + 'x', 'y', 'originX', 'originY', 'anchorX', 'anchorY', 'rotation', 'scaleX', 'scaleY', 'skewX', 'skewY' ] as const; +export type TransformProp = (typeof TRANSFORMABLE_PROPS)[number] + +export function copyTransform( + target: Partial>, + source: Pick +) { + for (let i = 0; i < TRANSFORMABLE_PROPS.length; i++) { + const propName = TRANSFORMABLE_PROPS[i]; + target[propName] = source[propName]; + } +} + export default Transformable; \ No newline at end of file diff --git a/src/core/env.ts b/src/core/env.ts index 010ef9f0c..cd52e3d91 100644 --- a/src/core/env.ts +++ b/src/core/env.ts @@ -17,31 +17,29 @@ class Env { wxa = false worker = false - canvasSupported = false svgSupported = false touchEventsSupported = false pointerEventsSupported = false domSupported = false transformSupported = false transform3dSupported = false + + hasGlobalWindow = typeof window !== 'undefined' } const env = new Env(); if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') { env.wxa = true; - env.canvasSupported = true; env.touchEventsSupported = true; } else if (typeof document === 'undefined' && typeof self !== 'undefined') { // In worker env.worker = true; - env.canvasSupported = true; } else if (typeof navigator === 'undefined') { // In node env.node = true; - env.canvasSupported = true; env.svgSupported = true; } else { @@ -83,7 +81,6 @@ function detect(ua: string, env: Env) { browser.weChat = true; } - env.canvasSupported = !!document.createElement('canvas').getContext; env.svgSupported = typeof SVGRect !== 'undefined'; env.touchEventsSupported = 'ontouchstart' in window && !browser.ie && !browser.edge; env.pointerEventsSupported = 'onpointerdown' in window diff --git a/src/core/event.ts b/src/core/event.ts index c5fc28117..6cf141fa1 100644 --- a/src/core/event.ts +++ b/src/core/event.ts @@ -7,10 +7,12 @@ import env from './env'; import { ZRRawEvent } from './types'; import {isCanvasEl, transformCoordWithViewport} from './dom'; -const isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener; - const MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/; const _calcOut: number[] = []; +const firefoxNotSupportOffsetXY = env.browser.firefox + // use offsetX/offsetY for Firefox >= 39 + // PENDING: consider Firefox for Android and Firefox OS? >= 43 + && +(env.browser.version as string).split('.')[0] < 39; type FirefoxMouseEvent = { layerX: number @@ -55,8 +57,7 @@ export function clientToLocal( // not support the properties. // (see http://www.jacklmoore.com/notes/mouse-position/) // In zr painter.dom, padding edge equals to border edge. - - if (calculate || !env.canvasSupported) { + if (calculate) { calculateZrXY(el, e as ZRRawEvent, out); } // Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned @@ -66,10 +67,7 @@ export function clientToLocal( // BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d. // // BTW3, In ff, offsetX/offsetY is always 0. - else if (env.browser.firefox - // use offsetX/offsetY for Firefox >= 39 - // PENDING: consider Firefox for Android and Firefox OS? >= 43 - && env.browser.version < '39' + else if (firefoxNotSupportOffsetXY && (e as FirefoxMouseEvent).layerX != null && (e as FirefoxMouseEvent).layerX !== (e as MouseEvent).offsetX ) { @@ -207,7 +205,6 @@ function getWheelDeltaMayPolyfill(e: ZRRawEvent): number { // we currently do not break it. // But event "wheel" in firefox do not has "wheelDelta", so we calculate // "wheelDeta" from "deltaX", "deltaY" (which is the props in spec). - const rawWheelDelta = (e as any).wheelDelta; // Theroetically `e.wheelDelta` won't be 0 unless some day it has been deprecated // by agent like Chrome or Safari. So we also calculate it if rawWheelDelta is 0. @@ -249,34 +246,28 @@ export function addEventListener( handler: AddEventListenerParams[1], opt?: AddEventListenerParams[2] ) { - if (isDomLevel2) { - // Reproduct the console warning: - // [Violation] Added non-passive event listener to a scroll-blocking event. - // Consider marking event handler as 'passive' to make the page more responsive. - // Just set console log level: verbose in chrome dev tool. - // then the warning log will be printed when addEventListener called. - // See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md - // We have not yet found a neat way to using passive. Because in zrender the dom event - // listener delegate all of the upper events of element. Some of those events need - // to prevent default. For example, the feature `preventDefaultMouseMove` of echarts. - // Before passive can be adopted, these issues should be considered: - // (1) Whether and how a zrender user specifies an event listener passive. And by default, - // passive or not. - // (2) How to tread that some zrender event listener is passive, and some is not. If - // we use other way but not preventDefault of mousewheel and touchmove, browser - // compatibility should be handled. - - // const opts = (env.passiveSupported && name === 'mousewheel') - // ? {passive: true} - // // By default, the third param of el.addEventListener is `capture: false`. - // : void 0; - // el.addEventListener(name, handler /* , opts */); - el.addEventListener(name, handler, opt); - } - else { - // For simplicity, do not implement `setCapture` for IE9-. - (el as any).attachEvent('on' + name, handler); - } + // Reproduct the console warning: + // [Violation] Added non-passive event listener to a scroll-blocking event. + // Consider marking event handler as 'passive' to make the page more responsive. + // Just set console log level: verbose in chrome dev tool. + // then the warning log will be printed when addEventListener called. + // See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md + // We have not yet found a neat way to using passive. Because in zrender the dom event + // listener delegate all of the upper events of element. Some of those events need + // to prevent default. For example, the feature `preventDefaultMouseMove` of echarts. + // Before passive can be adopted, these issues should be considered: + // (1) Whether and how a zrender user specifies an event listener passive. And by default, + // passive or not. + // (2) How to tread that some zrender event listener is passive, and some is not. If + // we use other way but not preventDefault of mousewheel and touchmove, browser + // compatibility should be handled. + + // const opts = (env.passiveSupported && name === 'mousewheel') + // ? {passive: true} + // // By default, the third param of el.addEventListener is `capture: false`. + // : void 0; + // el.addEventListener(name, handler /* , opts */); + el.addEventListener(name, handler, opt); } /** @@ -292,12 +283,7 @@ export function removeEventListener( handler: RemoveEventListenerParams[1], opt: RemoveEventListenerParams[2] ) { - if (isDomLevel2) { - el.removeEventListener(name, handler, opt); - } - else { - (el as any).detachEvent('on' + name, handler); - } + el.removeEventListener(name, handler, opt); } /** @@ -307,16 +293,11 @@ export function removeEventListener( * * @param {Event} e A mouse or touch event. */ -export const stop = isDomLevel2 - ? function (e: MouseEvent | TouchEvent | PointerEvent) { - e.preventDefault(); - e.stopPropagation(); - e.cancelBubble = true; - } - : function (e: MouseEvent | TouchEvent | PointerEvent) { - e.returnValue = false; - e.cancelBubble = true; - }; +export const stop = function (e: MouseEvent | TouchEvent | PointerEvent) { + e.preventDefault(); + e.stopPropagation(); + e.cancelBubble = true; +}; /** * This method only works for mouseup and mousedown. The functionality is restricted @@ -328,15 +309,6 @@ export function isMiddleOrRightButtonOnMouseUpDown(e: { which: number }) { return e.which === 2 || e.which === 3; } -/** - * To be removed. - * @deprecated - */ -export function notLeftMouse(e: MouseEvent) { - // If e.which is undefined, considered as left mouse event. - return e.which > 1; -} - // For backward compatibility export {Eventful as Dispatcher}; diff --git a/src/core/platform.ts b/src/core/platform.ts new file mode 100644 index 000000000..7df2364cb --- /dev/null +++ b/src/core/platform.ts @@ -0,0 +1,111 @@ +export const DEFAULT_FONT_SIZE = 12; +export const DEFAULT_FONT_FAMILY = 'sans-serif'; +export const DEFAULT_FONT = `${DEFAULT_FONT_SIZE}px ${DEFAULT_FONT_FAMILY}`; + +interface Platform { + // TODO CanvasLike? + createCanvas(): HTMLCanvasElement + measureText(text: string, font?: string): { width: number } + loadImage( + src: string, + onload: () => void | HTMLImageElement['onload'], + onerror: () => void | HTMLImageElement['onerror'] + ): HTMLImageElement +} + +// Text width map used for environment there is no canvas +// Only common ascii is used for size concern. + +// Generated from following code +// +// ctx.font = '12px sans-serif'; +// const asciiRange = [32, 126]; +// let mapStr = ''; +// for (let i = asciiRange[0]; i <= asciiRange[1]; i++) { +// const char = String.fromCharCode(i); +// const width = ctx.measureText(char).width; +// const ratio = Math.round(width / 12 * 100); +// mapStr += String.fromCharCode(ratio + 20)) +// } +// mapStr.replace(/\\/g, '\\\\'); +const OFFSET = 20; +const SCALE = 100; +// TODO other basic fonts? +// eslint-disable-next-line +const defaultWidthMapStr = `007LLmW'55;N0500LLLLLLLLLL00NNNLzWW\\\\WQb\\0FWLg\\bWb\\WQ\\WrWWQ000CL5LLFLL0LL**F*gLLLL5F0LF\\FFF5.5N`; + +function getTextWidthMap(mapStr: string): Record { + const map: Record = {}; + if (typeof JSON === 'undefined') { + return map; + } + for (let i = 0; i < mapStr.length; i++) { + const char = String.fromCharCode(i + 32); + const size = (mapStr.charCodeAt(i) - OFFSET) / SCALE; + map[char] = size; + } + return map; +} + +export const DEFAULT_TEXT_WIDTH_MAP = getTextWidthMap(defaultWidthMapStr); + +export const platformApi: Platform = { + // Export methods + createCanvas() { + return typeof document !== 'undefined' + && document.createElement('canvas'); + }, + + measureText: (function () { + + let _ctx: CanvasRenderingContext2D; + let _cachedFont: string; + return (text: string, font?: string) => { + if (!_ctx) { + const canvas = platformApi.createCanvas(); + _ctx = canvas && canvas.getContext('2d'); + } + if (_ctx) { + if (_cachedFont !== font) { + _cachedFont = _ctx.font = font || DEFAULT_FONT; + } + return _ctx.measureText(text); + } + else { + text = text || ''; + font = font || DEFAULT_FONT; + // Use font size if there is no other method can be used. + const res = /^([0-9]*?)px$/.exec(font); + const fontSize = +(res && res[1]) || DEFAULT_FONT_SIZE; + let width = 0; + if (font.indexOf('mono') >= 0) { // is monospace + width = fontSize * text.length; + } + else { + for (let i = 0; i < text.length; i++) { + const preCalcWidth = DEFAULT_TEXT_WIDTH_MAP[text[i]]; + width += preCalcWidth == null ? fontSize : (preCalcWidth * fontSize); + } + } + return { width }; + } + }; + })(), + + loadImage(src, onload, onerror) { + const image = new Image(); + image.onload = onload; + image.onerror = onerror; + image.src = src; + return image; + } +}; + +export function setPlatformAPI(newPlatformApis: Partial) { + for (let key in platformApi) { + // Don't assign unkown methods. + if ((newPlatformApis as any)[key]) { + (platformApi as any)[key] = (newPlatformApis as any)[key]; + } + } +} \ No newline at end of file diff --git a/src/core/timsort.ts b/src/core/timsort.ts index fdd1cbe0e..ee602f229 100644 --- a/src/core/timsort.ts +++ b/src/core/timsort.ts @@ -448,7 +448,6 @@ function TimSort(array: T[], compare: CompareFunc) { } else if (length1 === 0) { throw new Error(); - // throw new Error('mergeLow preconditions were not respected'); } else { for (i = 0; i < length1; i++) { diff --git a/src/core/types.ts b/src/core/types.ts index 41b035d65..e04a295f5 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -22,6 +22,9 @@ export type TextVerticalAlign = 'top' | 'middle' | 'bottom' export type TextAlign = 'left' | 'center' | 'right' // | 'middle' // DEPRECATED +export type FontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | number; +export type FontStyle = 'normal' | 'italic' | 'oblique'; + export type BuiltinTextPosition = 'left' | 'right' | 'top' | 'bottom' | 'inside' | 'insideLeft' | 'insideRight' | 'insideTop' | 'insideBottom' | 'insideTopLeft' | 'insideTopRight'| 'insideBottomLeft' | 'insideBottomRight'; diff --git a/src/core/util.ts b/src/core/util.ts index 8b39f068a..2fc571dc0 100644 --- a/src/core/util.ts +++ b/src/core/util.ts @@ -2,32 +2,38 @@ import { Dictionary, ArrayLike, KeyOfDistributive } from './types'; import { GradientObject } from '../graphic/Gradient'; import { ImagePatternObject } from '../graphic/Pattern'; - +import { platformApi } from './platform'; // 用于处理merge时无法遍历Date等对象的问题 -const BUILTIN_OBJECT: {[key: string]: boolean} = { - '[object Function]': true, - '[object RegExp]': true, - '[object Date]': true, - '[object Error]': true, - '[object CanvasGradient]': true, - '[object CanvasPattern]': true, +const BUILTIN_OBJECT: Record = reduce([ + 'Function', + 'RegExp', + 'Date', + 'Error', + 'CanvasGradient', + 'CanvasPattern', // For node-canvas - '[object Image]': true, - '[object Canvas]': true -}; - -const TYPED_ARRAY: {[key: string]: boolean} = { - '[object Int8Array]': true, - '[object Uint8Array]': true, - '[object Uint8ClampedArray]': true, - '[object Int16Array]': true, - '[object Uint16Array]': true, - '[object Int32Array]': true, - '[object Uint32Array]': true, - '[object Float32Array]': true, - '[object Float64Array]': true -}; + 'Image', + 'Canvas' +], (obj, val) => { + obj['[object ' + val + ']'] = true; + return obj; +}, {} as Record); + +const TYPED_ARRAY: Record = reduce([ + 'Int8', + 'Uint8', + 'Uint8Clamped', + 'Int16', + 'Uint16', + 'Int32', + 'Uint32', + 'Float32', + 'Float64' +], (obj, val) => { + obj['[object ' + val + 'Array]'] = true; + return obj; +}, {} as Record); const objToString = Object.prototype.toString; @@ -41,12 +47,6 @@ const ctorFunction = function () {}.constructor; const protoFunction = ctorFunction ? ctorFunction.prototype : null; const protoKey = '__proto__'; -// Avoid assign to an exported constiable, for transforming to cjs. -const methods: {[key: string]: Function} = {}; - -export function $override(name: string, fn: Function) { - methods[name] = fn; -} let idStart = 0x0907; @@ -101,7 +101,7 @@ export function clone(source: T): T { else { result = new Ctor((source as Float32Array).length); for (let i = 0, len = (source as Float32Array).length; i < len; i++) { - result[i] = clone((source as Float32Array)[i]); + result[i] = (source as Float32Array)[i]; } } } @@ -212,13 +212,8 @@ export function defaults< return target as T & S; } -export const createCanvas = function (): HTMLCanvasElement { - return methods.createCanvas(); -}; - -methods.createCanvas = function (): HTMLCanvasElement { - return document.createElement('canvas'); -}; +// Expose createCanvas in util for compatibility +export const createCanvas = platformApi.createCanvas; /** * 查询数组中元素的index @@ -452,7 +447,6 @@ export function keys(obj: T): (KeyOfDistributive & string)[ return keyList; } - // Remove this type in returned function. Or it will conflicts wicth callback with given context. Like Eventful. // According to lib.es5.d.ts /* eslint-disable max-len*/ @@ -753,8 +747,20 @@ export function createObject(proto?: object, properties?: T): T { return obj; } + +export function disableUserSelect(dom: HTMLElement) { + const domStyle = dom.style; + domStyle.webkitUserSelect = 'none'; + domStyle.userSelect = 'none'; + // @ts-ignore + domStyle.webkitTapHighlightColor = 'rgba(0,0,0,0)'; + (domStyle as any)['-webkit-touch-callout'] = 'none'; +} + export function hasOwn(own: object, prop: string): boolean { return own.hasOwnProperty(prop); } export function noop() {} + +export const RADIAN_TO_DEGREE = 180 / Math.PI; \ No newline at end of file diff --git a/src/export.ts b/src/export.ts index 7889e74a9..05fea0459 100644 --- a/src/export.ts +++ b/src/export.ts @@ -71,4 +71,6 @@ export {morphPathTool as morph}; export {parseSVG}; -export {default as showDebugDirtyRect} from './debug/showDebugDirtyRect'; \ No newline at end of file +export {default as showDebugDirtyRect} from './debug/showDebugDirtyRect'; + +export {setPlatformAPI} from './core/platform'; \ No newline at end of file diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 000000000..07a39ec11 --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,5 @@ +declare namespace NodeJS { + interface ProcessEnv { + NODE_ENV: 'production' | 'development' + } +} \ No newline at end of file diff --git a/src/graphic/Group.ts b/src/graphic/Group.ts index 337a8822b..8406f6efd 100644 --- a/src/graphic/Group.ts +++ b/src/graphic/Group.ts @@ -86,8 +86,10 @@ class Group extends Element { this._children.push(child); this._doAdd(child); } - if (child.__hostTarget) { - throw 'This elemenet has been used as an attachment'; + if (process.env.NODE_ENV !== 'production') { + if (child.__hostTarget) { + throw 'This elemenet has been used as an attachment'; + } } } diff --git a/src/graphic/IncrementalDisplayable.ts b/src/graphic/IncrementalDisplayable.ts index ada4f437d..c1fd4dbc7 100644 --- a/src/graphic/IncrementalDisplayable.ts +++ b/src/graphic/IncrementalDisplayable.ts @@ -38,6 +38,7 @@ export default class IncrementalDisplayable extends Displayble { // PENDING this.style = {}; } + // getCurrentCursor / updateCursorAfterBrush // is used in graphic.ts. It's not provided for developers getCursor() { diff --git a/src/graphic/Path.ts b/src/graphic/Path.ts index f76da8de1..b1b16d087 100644 --- a/src/graphic/Path.ts +++ b/src/graphic/Path.ts @@ -17,6 +17,7 @@ import Animator from '../animation/Animator'; import { lum } from '../tool/color'; import { DARK_LABEL_COLOR, LIGHT_LABEL_COLOR, DARK_MODE_THRESHOLD, LIGHTER_LABEL_COLOR } from '../config'; import { REDRAW_BIT, SHAPE_CHANGED_BIT, STYLE_CHANGED_BIT } from './constants'; +import { TRANSFORMABLE_PROPS } from '../core/Transformable'; export interface PathStyleProps extends CommonStyleProps { @@ -125,10 +126,9 @@ export type PathState = Pick & { hoverLayer?: boolean } -const pathCopyParams = [ - 'x', 'y', 'rotation', 'scaleX', 'scaleY', 'originX', 'originY', 'invisible', +const pathCopyParams = (TRANSFORMABLE_PROPS as readonly string[]).concat(['invisible', 'culling', 'z', 'z2', 'zlevel', 'parent' -] as const; +]) as (keyof Path)[]; class Path extends Displayable { @@ -149,7 +149,7 @@ class Path extends Displayable { */ autoBatch: boolean - private _rectWithStroke: BoundingRect + private _rectStroke: BoundingRect protected _normalState: PathState @@ -359,9 +359,9 @@ class Path extends Displayable { // Needs update rect with stroke lineWidth when // 1. Element changes scale or lineWidth // 2. Shape is changed - const rectWithStroke = this._rectWithStroke || (this._rectWithStroke = rect.clone()); + const rectStroke = this._rectStroke || (this._rectStroke = rect.clone()); if (this.__dirty || needsUpdateRect) { - rectWithStroke.copy(rect); + rectStroke.copy(rect); // PENDING, Min line width is needed when line is horizontal or vertical const lineScale = style.strokeNoScale ? this.getLineScale() : 1; // FIXME Must after updateTransform @@ -375,15 +375,15 @@ class Path extends Displayable { // Consider line width // Line scale can't be 0; if (lineScale > 1e-10) { - rectWithStroke.width += w / lineScale; - rectWithStroke.height += w / lineScale; - rectWithStroke.x -= w / lineScale / 2; - rectWithStroke.y -= w / lineScale / 2; + rectStroke.width += w / lineScale; + rectStroke.height += w / lineScale; + rectStroke.x -= w / lineScale / 2; + rectStroke.y -= w / lineScale / 2; } } // Return rect with stroke - return rectWithStroke; + return rectStroke; } return rect; diff --git a/src/graphic/Pattern.ts b/src/graphic/Pattern.ts index 188b6ce21..80c2f9d0b 100644 --- a/src/graphic/Pattern.ts +++ b/src/graphic/Pattern.ts @@ -1,4 +1,5 @@ import { ImageLike } from '../core/types'; +import { SVGVNode } from '../svg/core'; type ImagePatternRepeat = 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat' @@ -17,6 +18,15 @@ export interface PatternObjectBase { export interface ImagePatternObject extends PatternObjectBase { image: ImageLike | string repeat?: ImagePatternRepeat + + /** + * Width and height of image. + * `imageWidth` and `imageHeight` are only used in svg-ssr renderer. + * Because we can't get the size of image in svg-ssr renderer. + * They need to be give explictly. + */ + imageWidth?: number + imageHeight?: number } export interface InnerImagePatternObject extends ImagePatternObject { @@ -26,10 +36,10 @@ export interface InnerImagePatternObject extends ImagePatternObject { export interface SVGPatternObject extends PatternObjectBase { /** - * svg element can only be used in svg renderer currently. + * svg vnode can only be used in svg renderer currently. * svgWidth, svgHeight defines width and height used for pattern. */ - svgElement?: SVGElement + svgElement?: SVGVNode svgWidth?: number svgHeight?: number } @@ -43,8 +53,10 @@ class Pattern { image: ImageLike | string /** * svg element can only be used in svg renderer currently. + * + * Will be string if using SSR rendering. */ - svgElement: SVGElement + svgElement: SVGElement | string repeat: ImagePatternRepeat diff --git a/src/graphic/TSpan.ts b/src/graphic/TSpan.ts index c08af5545..4b5012901 100644 --- a/src/graphic/TSpan.ts +++ b/src/graphic/TSpan.ts @@ -1,9 +1,10 @@ import Displayable, { DisplayableProps, DisplayableStatePropNames } from './Displayable'; -import { getBoundingRect, DEFAULT_FONT } from '../contain/text'; +import { getBoundingRect } from '../contain/text'; import BoundingRect from '../core/BoundingRect'; import { PathStyleProps, DEFAULT_PATH_STYLE } from './Path'; import { createObject, defaults } from '../core/util'; -import { TextAlign, TextVerticalAlign } from '../core/types'; +import { FontStyle, FontWeight, TextAlign, TextVerticalAlign } from '../core/types'; +import { DEFAULT_FONT } from '../core/platform'; export interface TSpanStyleProps extends PathStyleProps { @@ -13,8 +14,18 @@ export interface TSpanStyleProps extends PathStyleProps { // TODO Text is assigned inside zrender text?: string + // Final generated font string + // Used in canvas, and when developers specified it. font?: string + // Value for each part of font + // Used in svg. + // NOTE: font should always been sync with these 4 properties. + fontSize?: number + fontWeight?: FontWeight + fontStyle?: FontStyle + fontFamily?: string + textAlign?: CanvasTextAlign textBaseline?: CanvasTextBaseline diff --git a/src/graphic/Text.ts b/src/graphic/Text.ts index eb4709e3d..254360790 100644 --- a/src/graphic/Text.ts +++ b/src/graphic/Text.ts @@ -2,11 +2,11 @@ * RichText is a container that manages complex text label. * It will parse text string and create sub displayble elements respectively. */ -import { TextAlign, TextVerticalAlign, ImageLike, Dictionary, MapToType } from '../core/types'; +import { TextAlign, TextVerticalAlign, ImageLike, Dictionary, MapToType, FontWeight, FontStyle } from '../core/types'; import { parseRichText, parsePlainText } from './helper/parseText'; import TSpan, { TSpanStyleProps } from './TSpan'; import { retrieve2, each, normalizeCssArray, trim, retrieve3, extend, keys, defaults } from '../core/util'; -import { DEFAULT_FONT, adjustTextX, adjustTextY } from '../contain/text'; +import { adjustTextX, adjustTextY } from '../contain/text'; import ZRImage from './Image'; import Rect from './shape/Rect'; import BoundingRect from '../core/BoundingRect'; @@ -21,6 +21,7 @@ import Animator from '../animation/Animator'; import Transformable from '../core/Transformable'; import { ElementCommonState } from '../Element'; import { GroupLike } from './Group'; +import { DEFAULT_FONT, DEFAULT_FONT_SIZE } from '../core/platform'; type TextContentBlock = ReturnType type TextLine = TextContentBlock['lines'][0] @@ -33,6 +34,7 @@ export interface TextStylePropsPart { fill?: string stroke?: string + strokeNoScale?: boolean opacity?: number fillOpacity?: number @@ -65,11 +67,11 @@ export interface TextStylePropsPart { /** * It helps merging respectively, rather than parsing an entire font string. */ - fontStyle?: 'normal' | 'italic' | 'oblique' + fontStyle?: FontStyle /** * It helps merging respectively, rather than parsing an entire font string. */ - fontWeight?: 'normal' | 'bold' | 'bolder' | 'lighter' | number + fontWeight?: FontWeight /** * It helps merging respectively, rather than parsing an entire font string. */ @@ -412,7 +414,9 @@ class ZRText extends Displayable implements GroupLike { } setTextContent(textContent: never) { - throw new Error('Can\'t attach text on another text'); + if (process.env.NODE_ENV !== 'production') { + throw new Error('Can\'t attach text on another text'); + } } // getDefaultStyleValue(key: T): TextStyleProps[T] { @@ -582,17 +586,18 @@ class ZRText extends Displayable implements GroupLike { subElStyle.shadowOffsetY = style.textShadowOffsetY || 0; } + // Always override default fill and stroke value. + subElStyle.stroke = textStroke as string; + subElStyle.fill = textFill as string; + if (textStroke) { - subElStyle.stroke = textStroke as string; subElStyle.lineWidth = style.lineWidth || defaultLineWidth; subElStyle.lineDash = style.lineDash; subElStyle.lineDashOffset = style.lineDashOffset || 0; } - if (textFill) { - subElStyle.fill = textFill as string; - } subElStyle.font = textFont; + setSeparateFont(subElStyle, style); textY += lineHeight; @@ -763,7 +768,7 @@ class ZRText extends Displayable implements GroupLike { ); const hasShadow = tokenStyle.textShadowBlur > 0 - || style.textShadowBlur > 0; + || style.textShadowBlur > 0; subElStyle.text = token.text; subElStyle.x = x; @@ -782,6 +787,10 @@ class ZRText extends Displayable implements GroupLike { subElStyle.font = token.font || DEFAULT_FONT; subElStyle.opacity = retrieve3(tokenStyle.opacity, style.opacity, 1); + + // TODO inherit each item from top style in token style? + setSeparateFont(subElStyle, tokenStyle); + if (textStroke) { subElStyle.lineWidth = retrieve3(tokenStyle.lineWidth, style.lineWidth, defaultLineWidth); subElStyle.lineDash = retrieve2(tokenStyle.lineDash, style.lineDash); @@ -882,28 +891,11 @@ class ZRText extends Displayable implements GroupLike { // FIXME in node-canvas fontWeight is before fontStyle // Use `fontSize` `fontFamily` to check whether font properties are defined. let font = ''; - if (style.fontSize || style.fontFamily || style.fontWeight) { - let fontSize = ''; - if ( - typeof style.fontSize === 'string' - && ( - style.fontSize.indexOf('px') !== -1 - || style.fontSize.indexOf('rem') !== -1 - || style.fontSize.indexOf('em') !== -1 - ) - ) { - fontSize = style.fontSize; - } - else if (!isNaN(+style.fontSize)) { - fontSize = style.fontSize + 'px'; - } - else { - fontSize = '12px'; - } + if (hasSeparateFont(style)) { font = [ style.fontStyle, style.fontWeight, - fontSize, + parseFontSize(style.fontSize), // If font properties are defined, `fontFamily` should not be ignored. style.fontFamily || 'sans-serif' ].join(' '); @@ -916,8 +908,47 @@ class ZRText extends Displayable implements GroupLike { const VALID_TEXT_ALIGN = {left: true, right: 1, center: 1}; const VALID_TEXT_VERTICAL_ALIGN = {top: 1, bottom: 1, middle: 1}; +const FONT_PARTS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily'] as const; + +export function parseFontSize(fontSize: number | string) { + if ( + typeof fontSize === 'string' + && ( + fontSize.indexOf('px') !== -1 + || fontSize.indexOf('rem') !== -1 + || fontSize.indexOf('em') !== -1 + ) + ) { + return fontSize; + } + else if (!isNaN(+fontSize)) { + return fontSize + 'px'; + } + else { + return DEFAULT_FONT_SIZE + 'px'; + } +} + +function setSeparateFont( + targetStyle: TSpanStyleProps, + sourceStyle: TextStylePropsPart +) { + for (let i = 0; i < FONT_PARTS.length; i++) { + const fontProp = FONT_PARTS[i]; + const val = sourceStyle[fontProp]; + if (val != null) { + (targetStyle as any)[fontProp] = val; + } + } +} + +export function hasSeparateFont(style: Pick) { + return style.fontSize != null || style.fontFamily || style.fontWeight; +} + export function normalizeTextStyle(style: TextStyleProps): TextStyleProps { normalizeStyle(style); + // TODO inherit each item from top style in token style? each(style.rich, normalizeStyle); return style; } diff --git a/src/graphic/helper/dashStyle.ts b/src/graphic/helper/dashStyle.ts deleted file mode 100644 index 732ad45c5..000000000 --- a/src/graphic/helper/dashStyle.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { isArray, isNumber } from '../../core/util'; - -export function normalizeLineDash(lineType: any, lineWidth?: number): number[] | false { - if (!lineType || lineType === 'solid' || !(lineWidth > 0)) { - return null; - } - lineWidth = lineWidth || 1; - return lineType === 'dashed' - ? [4 * lineWidth, 2 * lineWidth] - : lineType === 'dotted' - ? [lineWidth] - : isNumber(lineType) - ? [lineType] : isArray(lineType) ? lineType : null; -} \ No newline at end of file diff --git a/src/graphic/helper/image.ts b/src/graphic/helper/image.ts index f99e096cb..aa2bd37ba 100644 --- a/src/graphic/helper/image.ts +++ b/src/graphic/helper/image.ts @@ -1,5 +1,6 @@ import LRU from '../../core/LRU'; +import { platformApi } from '../../core/platform'; import { ImageLike } from '../../core/types'; const globalImageCache = new LRU(50); @@ -64,8 +65,10 @@ export function createOrUpdateImage( !isImageReady(image) && cachedImgObj.pending.push(pendingWrap); } else { - image = new Image(); - image.onload = image.onerror = imageOnLoad; + const image = platformApi.loadImage( + newImageOrSrc, imageOnLoad, imageOnLoad + ); + (image as any).__zrImageSrc = newImageOrSrc; globalImageCache.put( newImageOrSrc, @@ -74,8 +77,6 @@ export function createOrUpdateImage( pending: [pendingWrap] } ); - - image.src = (image as any).__zrImageSrc = newImageOrSrc; } return image; diff --git a/src/graphic/helper/poly.ts b/src/graphic/helper/poly.ts index 1950f77a1..316838d0b 100644 --- a/src/graphic/helper/poly.ts +++ b/src/graphic/helper/poly.ts @@ -1,5 +1,4 @@ -import smoothSpline from './smoothSpline'; import smoothBezier from './smoothBezier'; import { VectorArray } from '../../core/vector'; import PathProxy from '../../core/PathProxy'; @@ -8,7 +7,7 @@ export function buildPath( ctx: CanvasRenderingContext2D | PathProxy, shape: { points: VectorArray[], - smooth?: number | 'spline' + smooth?: number smoothConstraint?: VectorArray[] }, closePath: boolean @@ -16,7 +15,7 @@ export function buildPath( const smooth = shape.smooth; let points = shape.points; if (points && points.length >= 2) { - if (smooth && smooth !== 'spline') { + if (smooth) { const controlPoints = smoothBezier( points, smooth, closePath, shape.smoothConstraint ); @@ -33,10 +32,6 @@ export function buildPath( } } else { - if (smooth === 'spline') { - points = smoothSpline(points, closePath); - } - ctx.moveTo(points[0][0], points[0][1]); for (let i = 1, l = points.length; i < l; i++) { ctx.lineTo(points[i][0], points[i][1]); diff --git a/src/graphic/helper/roundSector.ts b/src/graphic/helper/roundSector.ts index ef5a7f466..1c2099214 100644 --- a/src/graphic/helper/roundSector.ts +++ b/src/graphic/helper/roundSector.ts @@ -1,4 +1,5 @@ -import PathProxy, { normalizeArcAngles } from '../../core/PathProxy'; +import PathProxy from '../../core/PathProxy'; +import { isArray } from '../../core/util'; const PI = Math.PI; const PI2 = PI * 2; @@ -12,31 +13,22 @@ const mathMax = Math.max; const mathMin = Math.min; const e = 1e-4; -type CornerTangents = { - cx: number - cy: number - x01: number - y01: number - x11: number - y11: number -}; - function intersect( x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number ): [number, number] { - const x10 = x1 - x0; - const y10 = y1 - y0; - const x32 = x3 - x2; - const y32 = y3 - y2; - let t = y32 * x10 - x32 * y10; + const dx10 = x1 - x0; + const dy10 = y1 - y0; + const dx32 = x3 - x2; + const dy32 = y3 - y2; + let t = dy32 * dx10 - dx32 * dy10; if (t * t < e) { return; } - t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t; - return [x0 + t * x10, y0 + t * y10]; + t = (dx32 * (y0 - y2) - dy32 * (x0 - x2)) / t; + return [x0 + t * dx10, y0 + t * dy10]; } // Compute perpendicular offset line of length rc. @@ -45,48 +37,80 @@ function computeCornerTangents( x1: number, y1: number, radius: number, cr: number, clockwise: boolean -): CornerTangents { - const x01 = x0 - x1; - const y01 = y0 - y1; - const lo = (clockwise ? cr : -cr) / mathSqrt(x01 * x01 + y01 * y01); - const ox = lo * y01; - const oy = -lo * x01; - const x11 = x0 + ox; - const y11 = y0 + oy; - const x10 = x1 + ox; - const y10 = y1 + oy; - const x00 = (x11 + x10) / 2; - const y00 = (y11 + y10) / 2; - const dx = x10 - x11; - const dy = y10 - y11; - const d2 = dx * dx + dy * dy; - const r = radius - cr; - const s = x11 * y10 - x10 * y11; - const d = (dy < 0 ? -1 : 1) * mathSqrt(mathMax(0, r * r * d2 - s * s)); - let cx0 = (s * dy - dx * d) / d2; - let cy0 = (-s * dx - dy * d) / d2; - const cx1 = (s * dy + dx * d) / d2; - const cy1 = (-s * dx + dy * d) / d2; - const dx0 = cx0 - x00; - const dy0 = cy0 - y00; - const dx1 = cx1 - x00; - const dy1 = cy1 - y00; +) { + const x01 = x0 - x1; + const y01 = y0 - y1; + const lo = (clockwise ? cr : -cr) / mathSqrt(x01 * x01 + y01 * y01); + const ox = lo * y01; + const oy = -lo * x01; + const x11 = x0 + ox; + const y11 = y0 + oy; + const x10 = x1 + ox; + const y10 = y1 + oy; + const x00 = (x11 + x10) / 2; + const y00 = (y11 + y10) / 2; + const dx = x10 - x11; + const dy = y10 - y11; + const d2 = dx * dx + dy * dy; + const r = radius - cr; + const s = x11 * y10 - x10 * y11; + const d = (dy < 0 ? -1 : 1) * mathSqrt(mathMax(0, r * r * d2 - s * s)); + let cx0 = (s * dy - dx * d) / d2; + let cy0 = (-s * dx - dy * d) / d2; + const cx1 = (s * dy + dx * d) / d2; + const cy1 = (-s * dx + dy * d) / d2; + const dx0 = cx0 - x00; + const dy0 = cy0 - y00; + const dx1 = cx1 - x00; + const dy1 = cy1 - y00; - // Pick the closer of the two intersection points - // TODO: Is there a faster way to determine which intersection to use? - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) { - cx0 = cx1; - cy0 = cy1; - } + // Pick the closer of the two intersection points + // TODO: Is there a faster way to determine which intersection to use? + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) { + cx0 = cx1; + cy0 = cy1; + } - return { - cx: cx0, - cy: cy0, - x01: -ox, - y01: -oy, - x11: cx0 * (radius / r - 1), - y11: cy0 * (radius / r - 1) - }; + return { + cx: cx0, + cy: cy0, + x0: -ox, + y0: -oy, + x1: cx0 * (radius / r - 1), + y1: cy0 * (radius / r - 1) + }; +} + +// For compatibility, don't use normalizeCssArray +// 5 represents [5, 5, 5, 5] +// [5] represents [5, 5, 0, 0] +// [5, 10] represents [5, 5, 10, 10] +// [5, 10, 15] represents [5, 10, 15, 15] +// [5, 10, 15, 20] represents [5, 10, 15, 20] +function normalizeCornerRadius(cr: number | number[]): number[] { + let arr: number[]; + if (isArray(cr)) { + const len = cr.length; + if (!len) { + return cr as number[]; + } + if (len === 1) { + arr = [cr[0], cr[0], 0, 0]; + } + else if (len === 2) { + arr = [cr[0], cr[0], cr[1], cr[1]]; + } + else if (len === 3) { + arr = cr.concat(cr[2]); + } + else { + arr = cr; + } + } + else { + arr = [cr, cr, cr, cr]; + } + return arr; } export function buildPath(ctx: CanvasRenderingContext2D | PathProxy, shape: { @@ -97,8 +121,7 @@ export function buildPath(ctx: CanvasRenderingContext2D | PathProxy, shape: { clockwise?: boolean, r?: number, r0?: number, - cornerRadius?: number, - innerCornerRadius?: number + cornerRadius?: number | number[] }) { let radius = mathMax(shape.r, 0); let innerRadius = mathMax(shape.r0 || 0, 0); @@ -123,152 +146,168 @@ export function buildPath(ctx: CanvasRenderingContext2D | PathProxy, shape: { } const clockwise = !!shape.clockwise; - const startAngle = shape.startAngle; - const endAngle = shape.endAngle; + const { startAngle, endAngle, cx, cy, cornerRadius } = shape; - // PENDING: whether normalizing angles is required? - let arc: number; - // FIXME: there may be a precision issue in `normalizeArcAngles` - if (startAngle === endAngle) { - arc = 0; - } - else { - const tmpAngles = [startAngle, endAngle]; - normalizeArcAngles(tmpAngles, !clockwise); - arc = mathAbs(tmpAngles[0] - tmpAngles[1]); - } - - const x = shape.cx; - const y = shape.cy; - const cornerRadius = shape.cornerRadius || 0; - const innerCornerRadius = shape.innerCornerRadius || 0; + let arc = mathAbs(endAngle - startAngle); + const mod = arc && arc % PI2; + mod && (arc = mod); // is a point if (!(radius > e)) { - ctx.moveTo(x, y); + ctx.moveTo(cx, cy); } // is a circle or annulus else if (arc > PI2 - e) { ctx.moveTo( - x + radius * mathCos(startAngle), - y + radius * mathSin(startAngle) + cx + radius * mathCos(startAngle), + cy + radius * mathSin(startAngle) ); - ctx.arc(x, y, radius, startAngle, endAngle, !clockwise); + ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise); if (innerRadius > e) { ctx.moveTo( - x + innerRadius * mathCos(endAngle), - y + innerRadius * mathSin(endAngle) + cx + innerRadius * mathCos(endAngle), + cy + innerRadius * mathSin(endAngle) ); - ctx.arc(x, y, innerRadius, endAngle, startAngle, clockwise); + ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise); } } // is a circular or annular sector else { - const halfRd = mathAbs(radius - innerRadius) / 2; - const cr = mathMin(halfRd, cornerRadius); - const icr = mathMin(halfRd, innerCornerRadius); - let cr0 = icr; - let cr1 = cr; + let icrStart; + let icrEnd; + let ocrStart; + let ocrEnd; - const xrs = radius * mathCos(startAngle); - const yrs = radius * mathSin(startAngle); - const xire = innerRadius * mathCos(endAngle); - const yire = innerRadius * mathSin(endAngle); + let ocrs; + let ocre; + let icrs; + let icre; + + let ocrMax; + let icrMax; + let limitedOcrMax; + let limitedIcrMax; let xre; let yre; let xirs; let yirs; - // draw corner radius - if (cr > e || icr > e) { - xre = radius * mathCos(endAngle); - yre = radius * mathSin(endAngle); - xirs = innerRadius * mathCos(startAngle); - yirs = innerRadius * mathSin(startAngle); + const xrs = radius * mathCos(startAngle); + const yrs = radius * mathSin(startAngle); + const xire = innerRadius * mathCos(endAngle); + const yire = innerRadius * mathSin(endAngle); + + const hasArc = arc > e; + if (hasArc) { + if (cornerRadius) { + [icrStart, icrEnd, ocrStart, ocrEnd] = normalizeCornerRadius(cornerRadius); + } + + const halfRd = mathAbs(radius - innerRadius) / 2; + ocrs = mathMin(halfRd, ocrStart); + ocre = mathMin(halfRd, ocrEnd); + icrs = mathMin(halfRd, icrStart); + icre = mathMin(halfRd, icrEnd); + + limitedOcrMax = ocrMax = mathMax(ocrs, ocre); + limitedIcrMax = icrMax = mathMax(icrs, icre); + + // draw corner radius + if (ocrMax > e || icrMax > e) { + xre = radius * mathCos(endAngle); + yre = radius * mathSin(endAngle); + xirs = innerRadius * mathCos(startAngle); + yirs = innerRadius * mathSin(startAngle); - // restrict the max value of corner radius - if (arc < PI) { - const it = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire); - if (it) { - const x0 = xrs - it[0]; - const y0 = yrs - it[1]; - const x1 = xre - it[0]; - const y1 = yre - it[1]; - const a = 1 / mathSin( - mathACos((x0 * x1 + y0 * y1) / (mathSqrt(x0 * x0 + y0 * y0) * mathSqrt(x1 * x1 + y1 * y1))) / 2 - ); - const b = mathSqrt(it[0] * it[0] + it[1] * it[1]); - cr0 = mathMin(icr, (innerRadius - b) / (a - 1)); - cr1 = mathMin(cr, (radius - b) / (a + 1)); + // restrict the max value of corner radius + if (arc < PI) { + const it = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire); + if (it) { + const x0 = xrs - it[0]; + const y0 = yrs - it[1]; + const x1 = xre - it[0]; + const y1 = yre - it[1]; + const a = 1 / mathSin( + // eslint-disable-next-line max-len + mathACos((x0 * x1 + y0 * y1) / (mathSqrt(x0 * x0 + y0 * y0) * mathSqrt(x1 * x1 + y1 * y1))) / 2 + ); + const b = mathSqrt(it[0] * it[0] + it[1] * it[1]); + limitedOcrMax = mathMin(ocrMax, (radius - b) / (a + 1)); + limitedIcrMax = mathMin(icrMax, (innerRadius - b) / (a - 1)); + } } } } // the sector is collapsed to a line - if (!(arc > e)) { - ctx.moveTo(x + xrs, y + yrs); + if (!hasArc) { + ctx.moveTo(cx + xrs, cy + yrs); } // the outer ring has corners - else if (cr1 > e) { - const ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, radius, cr1, clockwise); - const ct1 = computeCornerTangents(xre, yre, xire, yire, radius, cr1, clockwise); + else if (limitedOcrMax > e) { + const crStart = mathMin(ocrStart, limitedOcrMax); + const crEnd = mathMin(ocrEnd, limitedOcrMax); + const ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, radius, crStart, clockwise); + const ct1 = computeCornerTangents(xre, yre, xire, yire, radius, crEnd, clockwise); - ctx.moveTo(x + ct0.cx + ct0.x01, y + ct0.cy + ct0.y01); + ctx.moveTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0); // Have the corners merged? - if (cr1 < cr) { + if (limitedOcrMax < ocrMax && crStart === crEnd) { // eslint-disable-next-line max-len - ctx.arc(x + ct0.cx, y + ct0.cy, cr1, mathATan2(ct0.y01, ct0.x01), mathATan2(ct1.y01, ct1.x01), !clockwise); + ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedOcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise); } else { // draw the two corners and the ring // eslint-disable-next-line max-len - ctx.arc(x + ct0.cx, y + ct0.cy, cr1, mathATan2(ct0.y01, ct0.x01), mathATan2(ct0.y11, ct0.x11), !clockwise); + crStart > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crStart, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise); // eslint-disable-next-line max-len - ctx.arc(x, y, radius, mathATan2(ct0.cy + ct0.y11, ct0.cx + ct0.x11), mathATan2(ct1.cy + ct1.y11, ct1.cx + ct1.x11), !clockwise); + ctx.arc(cx, cy, radius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), !clockwise); // eslint-disable-next-line max-len - ctx.arc(x + ct1.cx, y + ct1.cy, cr1, mathATan2(ct1.y11, ct1.x11), mathATan2(ct1.y01, ct1.x01), !clockwise); + crEnd > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crEnd, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise); } } // the outer ring is a circular arc else { - ctx.moveTo(x + xrs, y + yrs); - ctx.arc(x, y, radius, startAngle, endAngle, !clockwise); + ctx.moveTo(cx + xrs, cy + yrs); + ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise); } // no inner ring, is a circular sector - if (!(innerRadius > e) || !(arc > e)) { - ctx.lineTo(x + xire, y + yire); + if (!(innerRadius > e) || !hasArc) { + ctx.lineTo(cx + xire, cy + yire); } // the inner ring has corners - else if (cr0 > e) { - const ct0 = computeCornerTangents(xire, yire, xre, yre, innerRadius, -cr0, clockwise); - const ct1 = computeCornerTangents(xrs, yrs, xirs, yirs, innerRadius, -cr0, clockwise); - ctx.lineTo(x + ct0.cx + ct0.x01, y + ct0.cy + ct0.y01); + else if (limitedIcrMax > e) { + const crStart = mathMin(icrStart, limitedIcrMax); + const crEnd = mathMin(icrEnd, limitedIcrMax); + const ct0 = computeCornerTangents(xire, yire, xre, yre, innerRadius, -crEnd, clockwise); + const ct1 = computeCornerTangents(xrs, yrs, xirs, yirs, innerRadius, -crStart, clockwise); + ctx.lineTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0); // Have the corners merged? - if (cr0 < icr) { + if (limitedIcrMax < icrMax && crStart === crEnd) { // eslint-disable-next-line max-len - ctx.arc(x + ct0.cx, y + ct0.cy, cr0, mathATan2(ct0.y01, ct0.x01), mathATan2(ct1.y01, ct1.x01), !clockwise); + ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedIcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise); } // draw the two corners and the ring else { // eslint-disable-next-line max-len - ctx.arc(x + ct0.cx, y + ct0.cy, cr0, mathATan2(ct0.y01, ct0.x01), mathATan2(ct0.y11, ct0.x11), !clockwise); + crEnd > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crEnd, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise); // eslint-disable-next-line max-len - ctx.arc(x, y, innerRadius, mathATan2(ct0.cy + ct0.y11, ct0.cx + ct0.x11), mathATan2(ct1.cy + ct1.y11, ct1.cx + ct1.x11), clockwise); + ctx.arc(cx, cy, innerRadius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), clockwise); // eslint-disable-next-line max-len - ctx.arc(x + ct1.cx, y + ct1.cy, cr0, mathATan2(ct1.y11, ct1.x11), mathATan2(ct1.y01, ct1.x01), !clockwise); + crStart > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crStart, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise); } } // the inner ring is just a circular arc else { // FIXME: if no lineTo, svg renderer will perform an abnormal drawing behavior. - ctx.lineTo(x + xire, y + yire); + ctx.lineTo(cx + xire, cy + yire); - ctx.arc(x, y, innerRadius, endAngle, startAngle, clockwise); + ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise); } } diff --git a/src/graphic/shape/Polygon.ts b/src/graphic/shape/Polygon.ts index cf24961d1..b7c9f75ca 100644 --- a/src/graphic/shape/Polygon.ts +++ b/src/graphic/shape/Polygon.ts @@ -9,7 +9,7 @@ import { VectorArray } from '../../core/vector'; export class PolygonShape { points: VectorArray[] = null - smooth?: number | 'spline' = 0 + smooth?: number = 0 smoothConstraint?: VectorArray[] = null } diff --git a/src/graphic/shape/Polyline.ts b/src/graphic/shape/Polyline.ts index f93caa98e..2221eb260 100644 --- a/src/graphic/shape/Polyline.ts +++ b/src/graphic/shape/Polyline.ts @@ -10,7 +10,7 @@ export class PolylineShape { points: VectorArray[] = null // Percent of displayed polyline. For animating purpose percent?: number = 1 - smooth?: number | 'spline' = 0 + smooth?: number = 0 smoothConstraint?: VectorArray[] = null } diff --git a/src/graphic/shape/Sector.ts b/src/graphic/shape/Sector.ts index 0b3f6cdfb..96550325f 100644 --- a/src/graphic/shape/Sector.ts +++ b/src/graphic/shape/Sector.ts @@ -9,8 +9,20 @@ export class SectorShape { startAngle = 0 endAngle = Math.PI * 2 clockwise = true - cornerRadius = 0 - innerCornerRadius = 0 + /** + * Corner radius of sector + * + * clockwise, from inside to outside, four corners are + * inner start -> inner end + * outer start -> outer end + * + * 5 => [5, 5, 5, 5] + * [5] => [5, 5, 0, 0] + * [5, 10] => [5, 5, 10, 10] + * [5, 10, 15] => [5, 10, 15, 15] + * [5, 10, 15, 20] => [5, 10, 15, 20] + */ + cornerRadius: number | number[] = 0 } export interface SectorProps extends PathProps { diff --git a/src/svg-legacy/Painter.ts b/src/svg-legacy/Painter.ts new file mode 100644 index 000000000..d4c213b75 --- /dev/null +++ b/src/svg-legacy/Painter.ts @@ -0,0 +1,421 @@ +/** + * SVG Painter + */ + +import {createElement, SVGNS, XLINKNS, XMLNS} from '../svg/core'; +import { normalizeColor } from '../svg/helper'; +import * as util from '../core/util'; +import Path from '../graphic/Path'; +import ZRImage from '../graphic/Image'; +import TSpan from '../graphic/TSpan'; +import arrayDiff from '../core/arrayDiff'; +import GradientManager from './helper/GradientManager'; +import PatternManager from './helper/PatternManager'; +import ClippathManager, {hasClipPath} from './helper/ClippathManager'; +import ShadowManager from './helper/ShadowManager'; +import { + path as svgPath, + image as svgImage, + text as svgText, + SVGProxy +} from './graphic'; +import Displayable from '../graphic/Displayable'; +import Storage from '../Storage'; +import { PainterBase } from '../PainterBase'; +import { getSize } from '../canvas/helper'; + +function getSvgProxy(el: Displayable) { + if (el instanceof Path) { + return svgPath; + } + else if (el instanceof ZRImage) { + return svgImage; + } + else if (el instanceof TSpan) { + return svgText; + } + else { + return svgPath; + } +} + +function checkParentAvailable(parent: SVGElement, child: SVGElement) { + return child && parent && child.parentNode !== parent; +} + +function insertAfter(parent: SVGElement, child: SVGElement, prevSibling: SVGElement) { + if (checkParentAvailable(parent, child) && prevSibling) { + const nextSibling = prevSibling.nextSibling; + nextSibling ? parent.insertBefore(child, nextSibling) + : parent.appendChild(child); + } +} + +function prepend(parent: SVGElement, child: SVGElement) { + if (checkParentAvailable(parent, child)) { + const firstChild = parent.firstChild; + firstChild ? parent.insertBefore(child, firstChild) + : parent.appendChild(child); + } +} + +function remove(parent: SVGElement, child: SVGElement) { + if (child && parent && child.parentNode === parent) { + parent.removeChild(child); + } +} +function removeFromMyParent(child: SVGElement) { + if (child && child.parentNode) { + child.parentNode.removeChild(child); + } +} + +function getSvgElement(displayable: Displayable) { + return displayable.__svgEl; +} + +interface SVGPainterOption { + width?: number | string + height?: number | string +} + +class SVGPainter implements PainterBase { + + type = 'svg' + + root: HTMLElement + + storage: Storage + + private _opts: SVGPainterOption + + private _svgDom: SVGElement + private _svgRoot: SVGGElement + private _backgroundRoot: SVGGElement + private _backgroundNode: SVGRectElement + + private _gradientManager: GradientManager + private _patternManager: PatternManager + private _clipPathManager: ClippathManager + private _shadowManager: ShadowManager + + private _viewport: HTMLDivElement + private _visibleList: Displayable[] + + private _width: number + private _height: number + + constructor(root: HTMLElement, storage: Storage, opts: SVGPainterOption, zrId: number) { + this.root = root; + this.storage = storage; + this._opts = opts = util.extend({}, opts || {}); + + const svgDom = createElement('svg'); + svgDom.setAttributeNS(XMLNS, 'xmlns', SVGNS); + svgDom.setAttributeNS(XMLNS, 'xmlns:xlink', XLINKNS); + + svgDom.setAttribute('version', '1.1'); + svgDom.setAttribute('baseProfile', 'full'); + svgDom.style.cssText = 'user-select:none;position:absolute;left:0;top:0;'; + + const bgRoot = createElement('g') as SVGGElement; + svgDom.appendChild(bgRoot); + const svgRoot = createElement('g') as SVGGElement; + svgDom.appendChild(svgRoot); + + this._gradientManager = new GradientManager(zrId, svgRoot); + this._patternManager = new PatternManager(zrId, svgRoot); + this._clipPathManager = new ClippathManager(zrId, svgRoot); + this._shadowManager = new ShadowManager(zrId, svgRoot); + + const viewport = document.createElement('div'); + viewport.style.cssText = 'overflow:hidden;position:relative'; + + this._svgDom = svgDom; + this._svgRoot = svgRoot; + this._backgroundRoot = bgRoot; + this._viewport = viewport; + + root.appendChild(viewport); + viewport.appendChild(svgDom); + + this.resize(opts.width, opts.height); + + this._visibleList = []; + } + + getType() { + return 'svg'; + } + + getViewportRoot() { + return this._viewport; + } + + getSvgDom() { + return this._svgDom; + } + + getSvgRoot() { + return this._svgRoot; + } + + getViewportRootOffset() { + const viewportRoot = this.getViewportRoot(); + if (viewportRoot) { + return { + offsetLeft: viewportRoot.offsetLeft || 0, + offsetTop: viewportRoot.offsetTop || 0 + }; + } + } + + refresh() { + const list = this.storage.getDisplayList(true); + this._paintList(list); + } + + setBackgroundColor(backgroundColor: string) { + // TODO gradient + // Insert a bg rect instead of setting background to viewport. + // Otherwise, the exported SVG don't have background. + if (this._backgroundRoot && this._backgroundNode) { + this._backgroundRoot.removeChild(this._backgroundNode); + } + + const bgNode = createElement('rect') as SVGRectElement; + bgNode.setAttribute('width', this.getWidth() as any); + bgNode.setAttribute('height', this.getHeight() as any); + bgNode.setAttribute('x', 0 as any); + bgNode.setAttribute('y', 0 as any); + bgNode.setAttribute('id', 0 as any); + const { color, opacity } = normalizeColor(backgroundColor); + bgNode.setAttribute('fill', color); + bgNode.setAttribute('fill-opacity', opacity as any); + + this._backgroundRoot.appendChild(bgNode); + this._backgroundNode = bgNode; + } + + createSVGElement(tag: string): SVGElement { + return createElement(tag); + } + + paintOne(el: Displayable): SVGElement { + const svgProxy = getSvgProxy(el); + svgProxy && (svgProxy as SVGProxy).brush(el); + return getSvgElement(el); + } + + _paintList(list: Displayable[]) { + const gradientManager = this._gradientManager; + const patternManager = this._patternManager; + const clipPathManager = this._clipPathManager; + const shadowManager = this._shadowManager; + + gradientManager.markAllUnused(); + patternManager.markAllUnused(); + clipPathManager.markAllUnused(); + shadowManager.markAllUnused(); + + const svgRoot = this._svgRoot; + const visibleList = this._visibleList; + const listLen = list.length; + + const newVisibleList = []; + + for (let i = 0; i < listLen; i++) { + const displayable = list[i]; + const svgProxy = getSvgProxy(displayable); + let svgElement = getSvgElement(displayable); + if (!displayable.invisible) { + if (displayable.__dirty || !svgElement) { + svgProxy && (svgProxy as SVGProxy).brush(displayable); + svgElement = getSvgElement(displayable); + // Update gradient and shadow + if (svgElement && displayable.style) { + gradientManager.update(displayable.style.fill); + gradientManager.update(displayable.style.stroke); + patternManager.update(displayable.style.fill); + patternManager.update(displayable.style.stroke); + shadowManager.update(svgElement, displayable); + } + + displayable.__dirty = 0; + } + + // May have optimizations and ignore brush(like empty string in TSpan) + if (svgElement) { + newVisibleList.push(displayable); + } + } + } + + const diff = arrayDiff(visibleList, newVisibleList); + let prevSvgElement; + let topPrevSvgElement; + + // NOTE: First do remove, in case element moved to the head and do remove + // after add + for (let i = 0; i < diff.length; i++) { + const item = diff[i]; + if (item.removed) { + for (let k = 0; k < item.count; k++) { + const displayable = visibleList[item.indices[k]]; + const svgElement = getSvgElement(displayable); + hasClipPath(displayable) ? removeFromMyParent(svgElement) + : remove(svgRoot, svgElement); + } + } + } + + let prevDisplayable; + let currentClipGroup; + for (let i = 0; i < diff.length; i++) { + const item = diff[i]; + // const isAdd = item.added; + if (item.removed) { + continue; + } + for (let k = 0; k < item.count; k++) { + const displayable = newVisibleList[item.indices[k]]; + // Update clipPath + const clipGroup = clipPathManager.update(displayable, prevDisplayable); + if (clipGroup !== currentClipGroup) { + // First pop to top level. + prevSvgElement = topPrevSvgElement; + if (clipGroup) { + // Enter second level of clipping group. + prevSvgElement ? insertAfter(svgRoot, clipGroup, prevSvgElement) + : prepend(svgRoot, clipGroup); + topPrevSvgElement = clipGroup; + // Reset prevSvgElement in second level. + prevSvgElement = null; + } + currentClipGroup = clipGroup; + } + + const svgElement = getSvgElement(displayable); + // if (isAdd) { + prevSvgElement + ? insertAfter(currentClipGroup || svgRoot, svgElement, prevSvgElement) + : prepend(currentClipGroup || svgRoot, svgElement); + // } + + prevSvgElement = svgElement || prevSvgElement; + if (!currentClipGroup) { + topPrevSvgElement = prevSvgElement; + } + + gradientManager.markUsed(displayable); + gradientManager.addWithoutUpdate(svgElement, displayable); + + patternManager.markUsed(displayable); + patternManager.addWithoutUpdate(svgElement, displayable); + + clipPathManager.markUsed(displayable); + + prevDisplayable = displayable; + } + } + + gradientManager.removeUnused(); + patternManager.removeUnused(); + clipPathManager.removeUnused(); + shadowManager.removeUnused(); + + this._visibleList = newVisibleList; + } + + resize(width: number | string, height: number | string) { + const viewport = this._viewport; + // FIXME Why ? + viewport.style.display = 'none'; + + // Save input w/h + const opts = this._opts; + width != null && (opts.width = width); + height != null && (opts.height = height); + + width = getSize(this.root, 0, opts); + height = getSize(this.root, 1, opts); + + viewport.style.display = ''; + + if (this._width !== width || this._height !== height) { + this._width = width; + this._height = height; + + const viewportStyle = viewport.style; + viewportStyle.width = width + 'px'; + viewportStyle.height = height + 'px'; + + const svgRoot = this._svgDom; + // Set width by 'svgRoot.width = width' is invalid + svgRoot.setAttribute('width', width + ''); + svgRoot.setAttribute('height', height + ''); + } + + if (this._backgroundNode) { + this._backgroundNode.setAttribute('width', width as any); + this._backgroundNode.setAttribute('height', height as any); + } + } + + /** + * 获取绘图区域宽度 + */ + getWidth() { + return this._width; + } + + /** + * 获取绘图区域高度 + */ + getHeight() { + return this._height; + } + + dispose() { + this.root.innerHTML = ''; + + this._svgRoot = + this._backgroundRoot = + this._svgDom = + this._backgroundNode = + this._viewport = this.storage = null; + } + + clear() { + const viewportNode = this._viewport; + if (viewportNode && viewportNode.parentNode) { + viewportNode.parentNode.removeChild(viewportNode); + } + } + + toDataURL() { + this.refresh(); + const svgDom = this._svgDom; + const outerHTML = svgDom.outerHTML + // outerHTML of `svg` tag is not supported in IE, use `parentNode.innerHTML` instead + // PENDING: Or use `new XMLSerializer().serializeToString(svg)`? + || (svgDom.parentNode && svgDom.parentNode as HTMLElement).innerHTML; + const html = encodeURIComponent(outerHTML.replace(/>\n\r<')); + return 'data:image/svg+xml;charset=UTF-8,' + html; + } + refreshHover = createMethodNotSupport('refreshHover') as PainterBase['refreshHover']; + configLayer = createMethodNotSupport('configLayer') as PainterBase['configLayer']; +} + + +// Not supported methods +function createMethodNotSupport(method: string): any { + return function () { + if (process.env.NODE_ENV !== 'production') { + util.logError('In SVG mode painter not support method "' + method + '"'); + } + }; +} + + +export default SVGPainter; \ No newline at end of file diff --git a/src/svg-legacy/graphic.ts b/src/svg-legacy/graphic.ts new file mode 100644 index 000000000..f48b20d25 --- /dev/null +++ b/src/svg-legacy/graphic.ts @@ -0,0 +1,194 @@ +// TODO +// 1. shadow +// 2. Image: sx, sy, sw, sh + +import {createElement, XLINKNS } from '../svg/core'; +import { getMatrixStr, TEXT_ALIGN_TO_ANCHOR, adjustTextY } from '../svg/helper'; +import * as matrix from '../core/matrix'; +import Path, { PathStyleProps } from '../graphic/Path'; +import ZRImage, { ImageStyleProps } from '../graphic/Image'; +import { getLineHeight } from '../contain/text'; +import TSpan, { TSpanStyleProps } from '../graphic/TSpan'; +import SVGPathRebuilder from '../svg/SVGPathRebuilder'; +import mapStyleToAttrs from '../svg/mapStyleToAttrs'; +import { DEFAULT_FONT } from '../core/platform'; + +export interface SVGProxy { + brush(el: T): void +} + +type AllStyleOption = PathStyleProps | TSpanStyleProps | ImageStyleProps; + +function setTransform(svgEl: SVGElement, m: matrix.MatrixArray) { + if (m) { + attr(svgEl, 'transform', getMatrixStr(m)); + } +} + +function attr(el: SVGElement, key: string, val: string | number) { + if (!val || (val as any).type !== 'linear' && (val as any).type !== 'radial') { + // Don't set attribute for gradient, since it need new dom nodes + el.setAttribute(key, val as any); + } +} + +function attrXLink(el: SVGElement, key: string, val: string) { + el.setAttributeNS(XLINKNS, key, val); +} + +function attrXML(el: SVGElement, key: string, val: string) { + el.setAttributeNS('http://www.w3.org/XML/1998/namespace', key, val); +} + +function bindStyle(svgEl: SVGElement, style: PathStyleProps, el?: Path): void +function bindStyle(svgEl: SVGElement, style: TSpanStyleProps, el?: TSpan): void +function bindStyle(svgEl: SVGElement, style: ImageStyleProps, el?: ZRImage): void +function bindStyle(svgEl: SVGElement, style: AllStyleOption, el?: Path | TSpan | ZRImage) { + mapStyleToAttrs((key, val) => attr(svgEl, key, val), style, el, true); +} + +interface PathWithSVGBuildPath extends Path { + __svgPathVersion: number + __svgPathBuilder: SVGPathRebuilder +} + +const svgPath: SVGProxy = { + brush(el: Path) { + const style = el.style; + + let svgEl = el.__svgEl; + if (!svgEl) { + svgEl = createElement('path'); + el.__svgEl = svgEl; + } + + if (!el.path) { + el.createPathProxy(); + } + const path = el.path; + + if (el.shapeChanged()) { + path.beginPath(); + el.buildPath(path, el.shape); + el.pathUpdated(); + } + + const pathVersion = path.getVersion(); + const elExt = el as PathWithSVGBuildPath; + let svgPathBuilder = elExt.__svgPathBuilder; + if (elExt.__svgPathVersion !== pathVersion || !svgPathBuilder || el.style.strokePercent < 1) { + if (!svgPathBuilder) { + svgPathBuilder = elExt.__svgPathBuilder = new SVGPathRebuilder(); + } + svgPathBuilder.reset(); + path.rebuildPath(svgPathBuilder, el.style.strokePercent); + svgPathBuilder.generateStr(); + elExt.__svgPathVersion = pathVersion; + } + + attr(svgEl, 'd', svgPathBuilder.getStr()); + + bindStyle(svgEl, style, el); + setTransform(svgEl, el.transform); + } +}; + +export {svgPath as path}; + +/*************************************************** + * IMAGE + **************************************************/ +const svgImage: SVGProxy = { + brush(el: ZRImage) { + const style = el.style; + let image = style.image; + + if (image instanceof HTMLImageElement) { + image = image.src; + } + // heatmap layer in geo may be a canvas + else if (image instanceof HTMLCanvasElement) { + image = image.toDataURL(); + } + if (!image) { + return; + } + + const x = style.x || 0; + const y = style.y || 0; + + const dw = style.width; + const dh = style.height; + + let svgEl = el.__svgEl; + if (!svgEl) { + svgEl = createElement('image'); + el.__svgEl = svgEl; + } + + if (image !== el.__imageSrc) { + attrXLink(svgEl, 'href', image as string); + // Caching image src + el.__imageSrc = image as string; + } + + attr(svgEl, 'width', dw + ''); + attr(svgEl, 'height', dh + ''); + + attr(svgEl, 'x', x + ''); + attr(svgEl, 'y', y + ''); + + bindStyle(svgEl, style, el); + setTransform(svgEl, el.transform); + } +}; +export {svgImage as image}; + +/*************************************************** + * TEXT + **************************************************/ + + +const svgText: SVGProxy = { + brush(el: TSpan) { + const style = el.style; + + let text = style.text; + // Convert to string + text != null && (text += ''); + if (!text || isNaN(style.x) || isNaN(style.y)) { + return; + } + + let textSvgEl = el.__svgEl as SVGTextElement; + if (!textSvgEl) { + textSvgEl = createElement('text') as SVGTextElement; + attrXML(textSvgEl, 'xml:space', 'preserve'); + el.__svgEl = textSvgEl; + } + + const font = style.font || DEFAULT_FONT; + + // style.font has been normalized by `normalizeTextStyle`. + const textSvgElStyle = textSvgEl.style; + textSvgElStyle.font = font; + + textSvgEl.textContent = text; + + bindStyle(textSvgEl, style, el); + setTransform(textSvgEl, el.transform); + + // Consider different font display differently in vertial align, we always + // set vertialAlign as 'middle', and use 'y' to locate text vertically. + const x = style.x || 0; + const y = adjustTextY(style.y || 0, getLineHeight(font), style.textBaseline); + const textAlign = TEXT_ALIGN_TO_ANCHOR[style.textAlign as keyof typeof TEXT_ALIGN_TO_ANCHOR] + || style.textAlign; + + attr(textSvgEl, 'dominant-baseline', 'central'); + attr(textSvgEl, 'text-anchor', textAlign); + attr(textSvgEl, 'x', x + ''); + attr(textSvgEl, 'y', y + ''); + } +}; +export {svgText as text}; diff --git a/src/svg/helper/ClippathManager.ts b/src/svg-legacy/helper/ClippathManager.ts similarity index 88% rename from src/svg/helper/ClippathManager.ts rename to src/svg-legacy/helper/ClippathManager.ts index 2e2fe3345..cce3cf5c9 100644 --- a/src/svg/helper/ClippathManager.ts +++ b/src/svg-legacy/helper/ClippathManager.ts @@ -7,25 +7,16 @@ import Definable from './Definable'; import * as zrUtil from '../../core/util'; import Displayable from '../../graphic/Displayable'; import Path from '../../graphic/Path'; -import {SVGProxy} from '../graphic'; +import {path} from '../graphic'; import { Dictionary } from '../../core/types'; import { isClipPathChanged } from '../../canvas/helper'; +import { getClipPathsKey, getIdURL } from '../../svg/helper'; +import { createElement } from '../../svg/core'; type PathExtended = Path & { _dom: SVGElement } -function generateClipPathsKey(clipPaths: Path[]) { - let key: number[] = []; - if (clipPaths) { - for (let i = 0; i < clipPaths.length; i++) { - const clipPath = clipPaths[i]; - key.push(clipPath.id); - } - } - return key.join(','); -} - export function hasClipPath(displayable: Displayable) { const clipPaths = displayable.__clipPaths; return clipPaths && clipPaths.length > 0; @@ -61,7 +52,7 @@ export default class ClippathManager extends Definable { const clipPaths = displayable.__clipPaths; const keyDuplicateCount = this._keyDuplicateCount; - let clipPathKey = generateClipPathsKey(clipPaths); + let clipPathKey = getClipPathsKey(clipPaths); if (isClipPathChanged(clipPaths, prevDisplayable && prevDisplayable.__clipPaths)) { keyDuplicateCount[clipPathKey] = keyDuplicateCount[clipPathKey] || 0; keyDuplicateCount[clipPathKey] && (clipPathKey += '-' + keyDuplicateCount[clipPathKey]); @@ -69,7 +60,7 @@ export default class ClippathManager extends Definable { } return this._refGroups[clipPathKey] - || (this._refGroups[clipPathKey] = this.createElement('g')); + || (this._refGroups[clipPathKey] = createElement('g')); } /** @@ -115,7 +106,7 @@ export default class ClippathManager extends Definable { // New id = 'zr' + this._zrId + '-clip-' + this.nextId; ++this.nextId; - clipPathEl = this.createElement('clipPath'); + clipPathEl = createElement('clipPath'); clipPathEl.setAttribute('id', id); defs.appendChild(clipPathEl); @@ -123,15 +114,14 @@ export default class ClippathManager extends Definable { } // Build path and add to - const svgProxy = this.getSvgProxy(clipPath); - (svgProxy as SVGProxy).brush(clipPath); + path.brush(clipPath); const pathEl = this.getSvgElement(clipPath); clipPathEl.innerHTML = ''; clipPathEl.appendChild(pathEl); - parentEl.setAttribute('clip-path', 'url(#' + id + ')'); + parentEl.setAttribute('clip-path', getIdURL(id)); if (clipPaths.length > 1) { // Make the other clipPaths recursively diff --git a/src/svg/helper/Definable.ts b/src/svg-legacy/helper/Definable.ts similarity index 88% rename from src/svg/helper/Definable.ts rename to src/svg-legacy/helper/Definable.ts index fe8d86df7..6eb4009fe 100644 --- a/src/svg/helper/Definable.ts +++ b/src/svg-legacy/helper/Definable.ts @@ -4,16 +4,8 @@ * @author Zhang Wenli */ -import {createElement} from '../core'; +import {createElement} from '../../svg/core'; import * as zrUtil from '../../core/util'; -import Path from '../../graphic/Path'; -import ZRImage from '../../graphic/Image'; -import TSpan from '../../graphic/TSpan'; -import { - path as svgPath, - image as svgImage, - text as svgText -} from '../graphic'; import Displayable from '../../graphic/Displayable'; @@ -51,9 +43,6 @@ export default class Definable { } } - createElement = createElement - - /** * Get the tag for svgRoot; optionally creates one if not exists. * @@ -68,7 +57,7 @@ export default class Definable { // Not exist if (isForceCreating) { let defs = svgRoot.insertBefore( - this.createElement('defs'), // Create new tag + createElement('defs'), // Create new tag svgRoot.firstChild // Insert in the front of svg ) as SVGDefsElement; if (!defs.contains) { @@ -233,29 +222,6 @@ export default class Definable { }); } - - /** - * Get SVG proxy. - * - * @param displayable displayable element - * @return svg proxy of given element - */ - getSvgProxy(displayable: Displayable) { - if (displayable instanceof Path) { - return svgPath; - } - else if (displayable instanceof ZRImage) { - return svgImage; - } - else if (displayable instanceof TSpan) { - return svgText; - } - else { - return svgPath; - } - } - - /** * Get SVG element. * diff --git a/src/svg/helper/GradientManager.ts b/src/svg-legacy/helper/GradientManager.ts similarity index 67% rename from src/svg/helper/GradientManager.ts rename to src/svg-legacy/helper/GradientManager.ts index 93cae2064..da8512c70 100644 --- a/src/svg/helper/GradientManager.ts +++ b/src/svg-legacy/helper/GradientManager.ts @@ -5,26 +5,10 @@ import Definable from './Definable'; import * as zrUtil from '../../core/util'; -import * as colorTool from '../../tool/color'; import Displayable from '../../graphic/Displayable'; import { GradientObject } from '../../graphic/Gradient'; -import { LinearGradientObject } from '../../graphic/LinearGradient'; -import { RadialGradientObject } from '../../graphic/RadialGradient'; - -function isLinearGradient(value: GradientObject): value is LinearGradientObject { - return value.type === 'linear'; -} - -function isRadialGradient(value: GradientObject): value is RadialGradientObject { - return value.type === 'radial'; -} - -function isGradient(value: GradientObject | string): value is GradientObject { - return value && ( - (value as GradientObject).type === 'linear' - || (value as GradientObject).type === 'radial' - ); -} +import { getIdURL, isGradient, isLinearGradient, isRadialGradient, normalizeColor, round4 } from '../../svg/helper'; +import { createElement } from '../../svg/core'; type GradientObjectExtended = GradientObject & { @@ -80,8 +64,7 @@ export default class GradientManager extends Definable { that.markUsed(displayable); - const id = dom.getAttribute('id'); - svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')'); + svgElement.setAttribute(fillOrStroke, getIdURL(dom.getAttribute('id'))); } }); } @@ -96,13 +79,15 @@ export default class GradientManager extends Definable { add(gradient: GradientObject): SVGElement { let dom; if (isLinearGradient(gradient)) { - dom = this.createElement('linearGradient'); + dom = createElement('linearGradient'); } else if (isRadialGradient(gradient)) { - dom = this.createElement('radialGradient'); + dom = createElement('radialGradient'); } else { - zrUtil.logError('Illegal gradient type.'); + if (process.env.NODE_ENV !== 'production') { + zrUtil.logError('Illegal gradient type.'); + } return null; } @@ -164,29 +149,28 @@ export default class GradientManager extends Definable { */ updateDom(gradient: GradientObject, dom: SVGElement) { if (isLinearGradient(gradient)) { - dom.setAttribute('x1', gradient.x + ''); - dom.setAttribute('y1', gradient.y + ''); - dom.setAttribute('x2', gradient.x2 + ''); - dom.setAttribute('y2', gradient.y2 + ''); + dom.setAttribute('x1', gradient.x as any); + dom.setAttribute('y1', gradient.y as any); + dom.setAttribute('x2', gradient.x2 as any); + dom.setAttribute('y2', gradient.y2 as any); } else if (isRadialGradient(gradient)) { - dom.setAttribute('cx', gradient.x + ''); - dom.setAttribute('cy', gradient.y + ''); - dom.setAttribute('r', gradient.r + ''); + dom.setAttribute('cx', gradient.x as any); + dom.setAttribute('cy', gradient.y as any); + dom.setAttribute('r', gradient.r as any); } else { - zrUtil.logError('Illegal gradient type.'); + if (process.env.NODE_ENV !== 'production') { + zrUtil.logError('Illegal gradient type.'); + } return; } - if (gradient.global) { - // x1, x2, y1, y2 in range of 0 to canvas width or height - dom.setAttribute('gradientUnits', 'userSpaceOnUse'); - } - else { - // x1, x2, y1, y2 in range of 0 to 1 - dom.setAttribute('gradientUnits', 'objectBoundingBox'); - } + dom.setAttribute('gradientUnits', + gradient.global + ? 'userSpaceOnUse' // x1, x2, y1, y2 in range of 0 to canvas width or height + : 'objectBoundingBox' // x1, x2, y1, y2 in range of 0 to 1 + ); // Remove color stops if exists dom.innerHTML = ''; @@ -194,25 +178,20 @@ export default class GradientManager extends Definable { // Add color stops const colors = gradient.colorStops; for (let i = 0, len = colors.length; i < len; ++i) { - const stop = this.createElement('stop'); - stop.setAttribute('offset', colors[i].offset * 100 + '%'); - - const color = colors[i].color; - if (color.indexOf('rgba') > -1) { - // Fix Safari bug that stop-color not recognizing alpha #9014 - const opacity = colorTool.parse(color)[3]; - const hex = colorTool.toHex(color); - - // stop-color cannot be color, since: - // The opacity value used for the gradient calculation is the - // *product* of the value of stop-opacity and the opacity of the - // value of stop-color. - // See https://www.w3.org/TR/SVG2/pservers.html#StopOpacityProperty - stop.setAttribute('stop-color', '#' + hex); - stop.setAttribute('stop-opacity', opacity + ''); - } - else { - stop.setAttribute('stop-color', colors[i].color); + const stop = createElement('stop'); + stop.setAttribute('offset', round4(colors[i].offset) * 100 + '%'); + + const stopColor = colors[i].color; + // Fix Safari bug that stop-color not recognizing alpha #9014 + const {color, opacity} = normalizeColor(stopColor); + // stop-color cannot be color, since: + // The opacity value used for the gradient calculation is the + // *product* of the value of stop-opacity and the opacity of the + // value of stop-color. + // See https://www.w3.org/TR/SVG2/pservers.html#StopOpacityProperty + stop.setAttribute('stop-color', color); + if (opacity < 1) { + stop.setAttribute('stop-opacity', opacity as any); } dom.appendChild(stop); diff --git a/src/svg/helper/PatternManager.ts b/src/svg-legacy/helper/PatternManager.ts similarity index 78% rename from src/svg/helper/PatternManager.ts rename to src/svg-legacy/helper/PatternManager.ts index 1f1f74e3b..38afcbda3 100644 --- a/src/svg/helper/PatternManager.ts +++ b/src/svg-legacy/helper/PatternManager.ts @@ -6,13 +6,11 @@ import Definable from './Definable'; import * as zrUtil from '../../core/util'; import Displayable from '../../graphic/Displayable'; -import {PatternObject, ImagePatternObject, SVGPatternObject} from '../../graphic/Pattern'; +import {PatternObject} from '../../graphic/Pattern'; import {createOrUpdateImage} from '../../graphic/helper/image'; import WeakMap from '../../core/WeakMap'; - -function isPattern(value: PatternObject | string): value is PatternObject { - return value && (!!(value as ImagePatternObject).image || !!(value as SVGPatternObject).svgElement); -} +import { getIdURL, isPattern, isSVGPattern } from '../../svg/helper'; +import { createElement } from '../../svg/core'; const patternDomMap = new WeakMap(); @@ -63,8 +61,7 @@ export default class PatternManager extends Definable { that.markUsed(displayable); - const id = dom.getAttribute('id'); - svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')'); + svgElement.setAttribute(fillOrStroke, getIdURL(dom.getAttribute('id'))); } }); } @@ -81,14 +78,12 @@ export default class PatternManager extends Definable { return; } - let dom = this.createElement('pattern'); + let dom = createElement('pattern'); pattern.id = pattern.id == null ? this.nextId++ : pattern.id; dom.setAttribute('id', 'zr' + this._zrId + '-pattern-' + pattern.id); - dom.setAttribute('x', '0'); - dom.setAttribute('y', '0'); dom.setAttribute('patternUnits', 'userSpaceOnUse'); this.updateDom(pattern, dom); @@ -123,22 +118,30 @@ export default class PatternManager extends Definable { * @param patternDom DOM to update */ updateDom(pattern: PatternObject, patternDom: SVGElement) { - const svgElement = (pattern as SVGPatternObject).svgElement; - - if (svgElement instanceof SVGElement) { - if (svgElement.parentNode !== patternDom) { - patternDom.innerHTML = ''; - patternDom.appendChild(svgElement); - - patternDom.setAttribute('width', (pattern as SVGPatternObject).svgWidth + ''); - patternDom.setAttribute('height', (pattern as SVGPatternObject).svgHeight + ''); - } + if (isSVGPattern(pattern)) { + // New SVGPattern will not been supported in the legacy SVG renderer. + // svg-legacy will been removed soon. + + // const svgElement = pattern.svgElement; + // const isStringSVG = typeof svgElement === 'string'; + // if (isStringSVG || svgElement.parentNode !== patternDom) { + // if (isStringSVG) { + // patternDom.innerHTML = svgElement; + // } + // else { + // patternDom.innerHTML = ''; + // patternDom.appendChild(svgElement); + // } + + // patternDom.setAttribute('width', pattern.svgWidth as any); + // patternDom.setAttribute('height', pattern.svgHeight as any); + // } } else { let img: SVGElement; const prevImage = patternDom.getElementsByTagName('image'); if (prevImage.length) { - if ((pattern as ImagePatternObject).image) { + if (pattern.image) { // Update img = prevImage[0]; } @@ -148,14 +151,14 @@ export default class PatternManager extends Definable { return; } } - else if ((pattern as ImagePatternObject).image) { + else if (pattern.image) { // Create - img = this.createElement('image'); + img = createElement('image'); } if (img) { let imageSrc; - const patternImage = (pattern as ImagePatternObject).image; + const patternImage = pattern.image; if (typeof patternImage === 'string') { imageSrc = patternImage; } @@ -168,21 +171,20 @@ export default class PatternManager extends Definable { if (imageSrc) { img.setAttribute('href', imageSrc); - img.setAttribute('x', '0'); - img.setAttribute('y', '0'); // No need to re-render so dirty is empty const hostEl = { dirty: () => {} }; - const createdImage = createOrUpdateImage(imageSrc, img as any, hostEl, img => { - patternDom.setAttribute('width', img.width + ''); - patternDom.setAttribute('height', img.height + ''); - }); + const updateSize = (img: HTMLImageElement) => { + patternDom.setAttribute('width', img.width as any); + patternDom.setAttribute('height', img.height as any); + }; + + const createdImage = createOrUpdateImage(imageSrc, img as any, hostEl, updateSize); if (createdImage && createdImage.width && createdImage.height) { // Loaded before - patternDom.setAttribute('width', createdImage.width + ''); - patternDom.setAttribute('height', createdImage.height + ''); + updateSize(createdImage as HTMLImageElement); } patternDom.appendChild(img); diff --git a/src/svg/helper/ShadowManager.ts b/src/svg-legacy/helper/ShadowManager.ts similarity index 80% rename from src/svg/helper/ShadowManager.ts rename to src/svg-legacy/helper/ShadowManager.ts index f836444fa..cc2c76e89 100644 --- a/src/svg/helper/ShadowManager.ts +++ b/src/svg-legacy/helper/ShadowManager.ts @@ -5,9 +5,9 @@ import Definable from './Definable'; import Displayable from '../../graphic/Displayable'; -import { PathStyleProps } from '../../graphic/Path'; import { Dictionary } from '../../core/types'; -import { normalizeColor } from '../core'; +import { getIdURL, getShadowKey, hasShadow, normalizeColor } from '../../svg/helper'; +import { createElement } from '../../svg/core'; type DisplayableExtended = Displayable & { _shadowDom: SVGElement @@ -34,9 +34,9 @@ export default class ShadowManager extends Definable { private _getFromPool(): SVGFilterElement { let shadowDom = this._shadowDomPool.pop(); // Try to get one from trash. if (!shadowDom) { - shadowDom = this.createElement('filter') as SVGFilterElement; + shadowDom = createElement('filter') as SVGFilterElement; shadowDom.setAttribute('id', 'zr' + this._zrId + '-shadow-' + this.nextId++); - const domChild = this.createElement('feDropShadow'); + const domChild = createElement('feDropShadow'); shadowDom.appendChild(domChild); this.addDom(shadowDom); } @@ -96,9 +96,9 @@ export default class ShadowManager extends Definable { } // TODO: textBoxShadowBlur is not supported yet - let offsetX = style.shadowOffsetX || 0; - let offsetY = style.shadowOffsetY || 0; - let blur = style.shadowBlur; + const offsetX = style.shadowOffsetX || 0; + const offsetY = style.shadowOffsetY || 0; + const blur = style.shadowBlur; const normalizedColor = normalizeColor(style.shadowColor); domChild.setAttribute('dx', offsetX / scaleX + ''); @@ -123,8 +123,7 @@ export default class ShadowManager extends Definable { // dom instances for the same shadow element (displayable as DisplayableExtended)._shadowDom = shadowDom; - const id = shadowDom.getAttribute('id'); - svgElement.setAttribute('filter', 'url(#' + id + ')'); + svgElement.setAttribute('filter', getIdURL(shadowDom.getAttribute('id'))); } removeUnused() { @@ -148,23 +147,3 @@ export default class ShadowManager extends Definable { this._shadowDomMap = {}; } } - - -function hasShadow(style: PathStyleProps) { - // TODO: textBoxShadowBlur is not supported yet - return style - && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY); -} - -function getShadowKey(displayable: Displayable) { - const style = displayable.style; - const globalScale = displayable.getGlobalScale(); - return [ - style.shadowColor, - (style.shadowBlur || 0).toFixed(2), // Reduce the precision - (style.shadowOffsetX || 0).toFixed(2), - (style.shadowOffsetY || 0).toFixed(2), - globalScale[0], - globalScale[1] - ].join(','); -} \ No newline at end of file diff --git a/src/vml/vml.ts b/src/svg-legacy/svg-legacy.ts similarity index 53% rename from src/vml/vml.ts rename to src/svg-legacy/svg-legacy.ts index bc06baf33..2d19fc1d3 100644 --- a/src/vml/vml.ts +++ b/src/svg-legacy/svg-legacy.ts @@ -1,7 +1,4 @@ -// @ts-nocheck - -import './graphic'; import {registerPainter} from '../zrender'; import Painter from './Painter'; -registerPainter('vml', Painter); \ No newline at end of file +registerPainter('svg-legacy', Painter); \ No newline at end of file diff --git a/src/svg/Painter.ts b/src/svg/Painter.ts index 811eb64a3..51a4d8ca7 100644 --- a/src/svg/Painter.ts +++ b/src/svg/Painter.ts @@ -1,168 +1,91 @@ /** * SVG Painter - * @module zrender/svg/Painter */ -import {createElement, normalizeColor} from './core'; -import * as util from '../core/util'; -import Path from '../graphic/Path'; -import ZRImage from '../graphic/Image'; -import TSpan from '../graphic/TSpan'; -import arrayDiff from '../core/arrayDiff'; -import GradientManager from './helper/GradientManager'; -import PatternManager from './helper/PatternManager'; -import ClippathManager, {hasClipPath} from './helper/ClippathManager'; -import ShadowManager from './helper/ShadowManager'; import { - path as svgPath, - image as svgImage, - text as svgText, - SVGProxy + brush, setClipPath } from './graphic'; import Displayable from '../graphic/Displayable'; import Storage from '../Storage'; import { PainterBase } from '../PainterBase'; +import { + createElement, + createVNode, + vNodeToString, + SVGVNodeAttrs, + SVGVNode, + getCssString, + BrushScope, + createBrushScope, + createSVGVNode +} from './core'; +import { normalizeColor, encodeBase64 } from './helper'; +import { extend, keys, logError, map, retrieve2 } from '../core/util'; +import Path from '../graphic/Path'; +import patch, { updateAttrs } from './patch'; +import { getSize } from '../canvas/helper'; -function parseInt10(val: string) { - return parseInt(val, 10); -} - -function getSvgProxy(el: Displayable) { - if (el instanceof Path) { - return svgPath; - } - else if (el instanceof ZRImage) { - return svgImage; - } - else if (el instanceof TSpan) { - return svgText; - } - else { - return svgPath; - } -} - -function checkParentAvailable(parent: SVGElement, child: SVGElement) { - return child && parent && child.parentNode !== parent; -} - -function insertAfter(parent: SVGElement, child: SVGElement, prevSibling: SVGElement) { - if (checkParentAvailable(parent, child) && prevSibling) { - const nextSibling = prevSibling.nextSibling; - nextSibling ? parent.insertBefore(child, nextSibling) - : parent.appendChild(child); - } -} - -function prepend(parent: SVGElement, child: SVGElement) { - if (checkParentAvailable(parent, child)) { - const firstChild = parent.firstChild; - firstChild ? parent.insertBefore(child, firstChild) - : parent.appendChild(child); - } -} - -function remove(parent: SVGElement, child: SVGElement) { - if (child && parent && child.parentNode === parent) { - parent.removeChild(child); - } -} -function removeFromMyParent(child: SVGElement) { - if (child && child.parentNode) { - child.parentNode.removeChild(child); - } -} - -function getSvgElement(displayable: Displayable) { - return displayable.__svgEl; -} +let svgId = 0; interface SVGPainterOption { - width?: number | string - height?: number | string + width?: number + height?: number + ssr?: boolean } class SVGPainter implements PainterBase { type = 'svg' - root: HTMLElement - storage: Storage - private _opts: SVGPainterOption + root: HTMLElement private _svgDom: SVGElement - private _svgRoot: SVGGElement - private _backgroundRoot: SVGGElement - private _backgroundNode: SVGRectElement + private _viewport: HTMLElement - private _gradientManager: GradientManager - private _patternManager: PatternManager - private _clipPathManager: ClippathManager - private _shadowManager: ShadowManager + private _opts: SVGPainterOption - private _viewport: HTMLDivElement - private _visibleList: Displayable[] + private _oldVNode: SVGVNode + private _bgVNode: SVGVNode + private _mainVNode: SVGVNode private _width: number private _height: number - constructor(root: HTMLElement, storage: Storage, opts: SVGPainterOption, zrId: number) { - this.root = root; - this.storage = storage; - this._opts = opts = util.extend({}, opts || {}); - - const svgDom = createElement('svg'); - svgDom.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg'); - svgDom.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink'); + private _backgroundColor: string - svgDom.setAttribute('version', '1.1'); - svgDom.setAttribute('baseProfile', 'full'); - svgDom.style.cssText = 'user-select:none;position:absolute;left:0;top:0;'; + private _id: string - const bgRoot = createElement('g') as SVGGElement; - svgDom.appendChild(bgRoot); - const svgRoot = createElement('g') as SVGGElement; - svgDom.appendChild(svgRoot); - - this._gradientManager = new GradientManager(zrId, svgRoot); - this._patternManager = new PatternManager(zrId, svgRoot); - this._clipPathManager = new ClippathManager(zrId, svgRoot); - this._shadowManager = new ShadowManager(zrId, svgRoot); - - const viewport = document.createElement('div'); - viewport.style.cssText = 'overflow:hidden;position:relative'; - - this._svgDom = svgDom; - this._svgRoot = svgRoot; - this._backgroundRoot = bgRoot; - this._viewport = viewport; + constructor(root: HTMLElement, storage: Storage, opts: SVGPainterOption) { + this.storage = storage; + this._opts = opts = extend({}, opts); - root.appendChild(viewport); - viewport.appendChild(svgDom); + this.root = root; + // A unique id for generating svg ids. + this._id = 'zr' + svgId++; + + this._oldVNode = createSVGVNode(opts.width, opts.height); + + if (root && !opts.ssr) { + const viewport = this._viewport = document.createElement('div'); + viewport.style.cssText = 'position:relative;overflow:hidden'; + const svgDom = this._svgDom = this._oldVNode.elm = createElement('svg'); + updateAttrs(null, this._oldVNode); + viewport.appendChild(svgDom); + root.appendChild(viewport); + } this.resize(opts.width, opts.height); - - this._visibleList = []; } getType() { - return 'svg'; + return this.type; } getViewportRoot() { return this._viewport; } - - getSvgDom() { - return this._svgDom; - } - - getSvgRoot() { - return this._svgRoot; - } - getViewportRootOffset() { const viewportRoot = this.getViewportRoot(); if (viewportRoot) { @@ -173,235 +96,218 @@ class SVGPainter implements PainterBase { } } + getSvgDom() { + return this._svgDom; + } + refresh() { + if (this.root) { + const vnode = this.renderToVNode({ + willUpdate: true + }); + // Disable user selection. + vnode.attrs.style = 'position:absolute;left:0;top:0;user-select:none'; + patch(this._oldVNode, vnode); + this._oldVNode = vnode; + } + } + + renderOneToVNode(el: Displayable) { + return brush(el, createBrushScope(this._id)); + } + + renderToVNode(opts?: { + animation?: boolean + willUpdate?: boolean + compress?: boolean, + useViewBox?: boolean + }) { + + opts = opts || {}; const list = this.storage.getDisplayList(true); + const bgColor = this._backgroundColor; + const width = this._width; + const height = this._height; + + const scope = createBrushScope(this._id); + scope.animation = opts.animation; + scope.willUpdate = opts.willUpdate; + scope.compress = opts.compress; + + const children: SVGVNode[] = []; + + if (bgColor && bgColor !== 'none') { + const { color, opacity } = normalizeColor(bgColor); + this._bgVNode = createVNode( + 'rect', + 'bg', + { + width: width, + height: height, + x: '0', + y: '0', + id: '0', + fill: color, + 'fill-opacity': opacity + } + ); + children.push(this._bgVNode); + } + else { + this._bgVNode = null; + } - this._paintList(list); - } + // Ignore the root g if wan't the output to be more tight. + const mainVNode = !opts.compress + ? (this._mainVNode = createVNode('g', 'main', {}, [])) : null; + this._paintList(list, scope, mainVNode ? mainVNode.children : children); + mainVNode && children.push(mainVNode); - setBackgroundColor(backgroundColor: string) { - // TODO gradient - // Insert a bg rect instead of setting background to viewport. - // Otherwise, the exported SVG don't have background. - if (this._backgroundRoot && this._backgroundNode) { - this._backgroundRoot.removeChild(this._backgroundNode); + const defs = map(keys(scope.defs), (id) => scope.defs[id]); + if (defs.length) { + children.push(createVNode('defs', 'defs', {}, defs)); } - const bgNode = createElement('rect') as SVGRectElement; - bgNode.setAttribute('width', this.getWidth() as any); - bgNode.setAttribute('height', this.getHeight() as any); - bgNode.setAttribute('x', 0 as any); - bgNode.setAttribute('y', 0 as any); - bgNode.setAttribute('id', 0 as any); - const { color, opacity } = normalizeColor(backgroundColor); - bgNode.setAttribute('fill', color); - bgNode.setAttribute('fill-opacity', opacity as any); - - this._backgroundRoot.appendChild(bgNode); - this._backgroundNode = bgNode; - } + if (opts.animation) { + const animationCssStr = getCssString(scope.cssNodes, scope.cssAnims, { newline: true }); + if (animationCssStr) { + const styleNode = createVNode('style', 'stl', {}, [], animationCssStr); + children.push(styleNode); + } + } - createSVGElement(tag: string): SVGElement { - return createElement(tag); + return createSVGVNode(width, height, children, opts.useViewBox); } - paintOne(el: Displayable): SVGElement { - const svgProxy = getSvgProxy(el); - svgProxy && (svgProxy as SVGProxy).brush(el); - return getSvgElement(el); + renderToString(opts?: { + /** + * If add css animation. + * @default true + */ + cssAnimation?: boolean + /** + * If use viewBox + * @default true + */ + useViewBox?: boolean + }) { + opts = opts || {}; + return vNodeToString(this.renderToVNode({ + animation: retrieve2(opts.cssAnimation, true), + willUpdate: false, + compress: true, + useViewBox: retrieve2(opts.useViewBox, true) + }), { newline: true }); } - _paintList(list: Displayable[]) { - const gradientManager = this._gradientManager; - const patternManager = this._patternManager; - const clipPathManager = this._clipPathManager; - const shadowManager = this._shadowManager; + setBackgroundColor(backgroundColor: string) { + this._backgroundColor = backgroundColor; + const bgVNode = this._bgVNode; + if (bgVNode && bgVNode.elm) { + const { color, opacity } = normalizeColor(backgroundColor); + (bgVNode.elm as SVGElement).setAttribute('fill', color); + if (opacity < 1) { + (bgVNode.elm as SVGElement).setAttribute('fill-opacity', opacity as any); + } + } + } - gradientManager.markAllUnused(); - patternManager.markAllUnused(); - clipPathManager.markAllUnused(); - shadowManager.markAllUnused(); + getSvgRoot() { + return this._mainVNode && this._mainVNode.elm as SVGElement; + } - const svgRoot = this._svgRoot; - const visibleList = this._visibleList; + _paintList(list: Displayable[], scope: BrushScope, out?: SVGVNode[]) { const listLen = list.length; - const newVisibleList = []; - + const clipPathsGroupsStack: SVGVNode[] = []; + let clipPathsGroupsStackDepth = 0; + let currentClipPathGroup; + let prevClipPaths: Path[]; + let clipGroupNodeIdx = 0; for (let i = 0; i < listLen; i++) { const displayable = list[i]; - const svgProxy = getSvgProxy(displayable); - let svgElement = getSvgElement(displayable); if (!displayable.invisible) { - if (displayable.__dirty || !svgElement) { - svgProxy && (svgProxy as SVGProxy).brush(displayable); - svgElement = getSvgElement(displayable); - // Update gradient and shadow - if (svgElement && displayable.style) { - gradientManager.update(displayable.style.fill); - gradientManager.update(displayable.style.stroke); - patternManager.update(displayable.style.fill); - patternManager.update(displayable.style.stroke); - shadowManager.update(svgElement, displayable); + const clipPaths = displayable.__clipPaths; + const len = clipPaths && clipPaths.length || 0; + const prevLen = prevClipPaths && prevClipPaths.length || 0; + let lca; + // Find the lowest common ancestor + for (lca = Math.max(len - 1, prevLen - 1); lca >= 0; lca--) { + if (clipPaths && prevClipPaths + && clipPaths[lca] === prevClipPaths[lca] + ) { + break; } - - displayable.__dirty = 0; - } - - // May have optimizations and ignore brush(like empty string in TSpan) - if (svgElement) { - newVisibleList.push(displayable); } - - } - } - - const diff = arrayDiff(visibleList, newVisibleList); - let prevSvgElement; - let topPrevSvgElement; - - // NOTE: First do remove, in case element moved to the head and do remove - // after add - for (let i = 0; i < diff.length; i++) { - const item = diff[i]; - if (item.removed) { - for (let k = 0; k < item.count; k++) { - const displayable = visibleList[item.indices[k]]; - const svgElement = getSvgElement(displayable); - hasClipPath(displayable) ? removeFromMyParent(svgElement) - : remove(svgRoot, svgElement); + // pop the stack + for (let i = prevLen - 1; i > lca; i--) { + clipPathsGroupsStackDepth--; + // svgEls.push(closeGroup); + currentClipPathGroup = clipPathsGroupsStack[clipPathsGroupsStackDepth - 1]; } - } - } - - let prevDisplayable; - let currentClipGroup; - for (let i = 0; i < diff.length; i++) { - const item = diff[i]; - // const isAdd = item.added; - if (item.removed) { - continue; - } - for (let k = 0; k < item.count; k++) { - const displayable = newVisibleList[item.indices[k]]; - // Update clipPath - const clipGroup = clipPathManager.update(displayable, prevDisplayable); - if (clipGroup !== currentClipGroup) { - // First pop to top level. - prevSvgElement = topPrevSvgElement; - if (clipGroup) { - // Enter second level of clipping group. - prevSvgElement ? insertAfter(svgRoot, clipGroup, prevSvgElement) - : prepend(svgRoot, clipGroup); - topPrevSvgElement = clipGroup; - // Reset prevSvgElement in second level. - prevSvgElement = null; - } - currentClipGroup = clipGroup; + // Pop clip path group for clipPaths not match the previous. + for (let i = lca + 1; i < len; i++) { + const groupAttrs: SVGVNodeAttrs = {}; + setClipPath( + clipPaths[i], + groupAttrs, + scope + ); + const g = createVNode( + 'g', + 'clip-g-' + clipGroupNodeIdx++, + groupAttrs, + [] + ); + (currentClipPathGroup ? currentClipPathGroup.children : out).push(g); + clipPathsGroupsStack[clipPathsGroupsStackDepth++] = g; + currentClipPathGroup = g; } + prevClipPaths = clipPaths; - const svgElement = getSvgElement(displayable); - // if (isAdd) { - prevSvgElement - ? insertAfter(currentClipGroup || svgRoot, svgElement, prevSvgElement) - : prepend(currentClipGroup || svgRoot, svgElement); - // } - - prevSvgElement = svgElement || prevSvgElement; - if (!currentClipGroup) { - topPrevSvgElement = prevSvgElement; + const ret = brush(displayable, scope); + if (ret) { + (currentClipPathGroup ? currentClipPathGroup.children : out).push(ret); } - - gradientManager.markUsed(displayable); - gradientManager.addWithoutUpdate(svgElement, displayable); - - patternManager.markUsed(displayable); - patternManager.addWithoutUpdate(svgElement, displayable); - - clipPathManager.markUsed(displayable); - - prevDisplayable = displayable; } } - - gradientManager.removeUnused(); - patternManager.removeUnused(); - clipPathManager.removeUnused(); - shadowManager.removeUnused(); - - this._visibleList = newVisibleList; } - // Not used any more - // _getDefs(isForceCreating?: boolean) { - // let svgRoot = this._svgDom; - // let defs = svgRoot.getElementsByTagName('defs'); - // if (defs.length === 0) { - // // Not exist - // if (isForceCreating) { - // let defs = svgRoot.insertBefore( - // createElement('defs'), // Create new tag - // svgRoot.firstChild // Insert in the front of svg - // ); - // if (!defs.contains) { - // // IE doesn't support contains method - // defs.contains = function (el) { - // const children = defs.children; - // if (!children) { - // return false; - // } - // for (let i = children.length - 1; i >= 0; --i) { - // if (children[i] === el) { - // return true; - // } - // } - // return false; - // }; - // } - // return defs; - // } - // else { - // return null; - // } - // } - // else { - // return defs[0]; - // } - // } - - resize(width: number | string, height: number | string) { - const viewport = this._viewport; - // FIXME Why ? - viewport.style.display = 'none'; - + resize(width: number, height: number) { // Save input w/h const opts = this._opts; + const root = this.root; + const viewport = this._viewport; width != null && (opts.width = width); height != null && (opts.height = height); - width = this._getSize(0); - height = this._getSize(1); + if (root && viewport) { + // FIXME Why ? + viewport.style.display = 'none'; - viewport.style.display = ''; + width = getSize(root, 0, opts); + height = getSize(root, 1, opts); + + viewport.style.display = ''; + } if (this._width !== width || this._height !== height) { this._width = width; this._height = height; - const viewportStyle = viewport.style; - viewportStyle.width = width + 'px'; - viewportStyle.height = height + 'px'; - - const svgRoot = this._svgDom; - // Set width by 'svgRoot.width = width' is invalid - svgRoot.setAttribute('width', width + ''); - svgRoot.setAttribute('height', height + ''); - } + if (viewport) { + const viewportStyle = viewport.style; + viewportStyle.width = width + 'px'; + viewportStyle.height = height + 'px'; + } - if (this._backgroundNode) { - this._backgroundNode.setAttribute('width', width as any); - this._backgroundNode.setAttribute('height', height as any); + const svgDom = this._svgDom; + if (svgDom) { + // Set width by 'svgRoot.width = width' is invalid + svgDom.setAttribute('width', width as any); + svgDom.setAttribute('height', height as any); + } } } @@ -419,57 +325,35 @@ class SVGPainter implements PainterBase { return this._height; } - _getSize(whIdx: number) { - const opts = this._opts; - const wh = ['width', 'height'][whIdx] as 'width' | 'height'; - const cwh = ['clientWidth', 'clientHeight'][whIdx] as 'clientWidth' | 'clientHeight'; - const plt = ['paddingLeft', 'paddingTop'][whIdx] as 'paddingLeft' | 'paddingTop'; - const prb = ['paddingRight', 'paddingBottom'][whIdx] as 'paddingRight' | 'paddingBottom'; - - if (opts[wh] != null && opts[wh] !== 'auto') { - return parseFloat(opts[wh] as string); - } - - const root = this.root; - // IE8 does not support getComputedStyle, but it use VML. - const stl = document.defaultView.getComputedStyle(root); - - return ( - (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) - - (parseInt10(stl[plt]) || 0) - - (parseInt10(stl[prb]) || 0) - ) | 0; - } - dispose() { - this.root.innerHTML = ''; + if (this.root) { + this.root.innerHTML = ''; + } - this._svgRoot = - this._backgroundRoot = - this._svgDom = - this._backgroundNode = - this._viewport = this.storage = null; + this._svgDom = + this._viewport = + this.storage = + this._oldVNode = + this._bgVNode = + this._mainVNode = null; } - clear() { - const viewportNode = this._viewport; - if (viewportNode && viewportNode.parentNode) { - viewportNode.parentNode.removeChild(viewportNode); + if (this._svgDom) { + this._svgDom.innerHTML = null; } + this._oldVNode = null; } - - toDataURL() { - this.refresh(); - const svgDom = this._svgDom; - const outerHTML = svgDom.outerHTML - // outerHTML of `svg` tag is not supported in IE, use `parentNode.innerHTML` instead - // PENDING: Or use `new XMLSerializer().serializeToString(svg)`? - || (svgDom.parentNode && svgDom.parentNode as HTMLElement).innerHTML; - const html = encodeURIComponent(outerHTML.replace(/>\n\r<')); - return 'data:image/svg+xml;charset=UTF-8,' + html; + toDataURL(base64?: boolean) { + let str = encodeURIComponent(this.renderToString()); + const prefix = 'data:image/svg+xml;'; + if (base64) { + str = encodeBase64(str); + return str && prefix + 'base64,' + str; + } + return prefix + 'charset=UTF-8,' + str; } + refreshHover = createMethodNotSupport('refreshHover') as PainterBase['refreshHover']; - pathToImage = createMethodNotSupport('pathToImage') as PainterBase['pathToImage']; configLayer = createMethodNotSupport('configLayer') as PainterBase['configLayer']; } @@ -477,9 +361,11 @@ class SVGPainter implements PainterBase { // Not supported methods function createMethodNotSupport(method: string): any { return function () { - util.logError('In SVG mode painter not support method "' + method + '"'); + if (process.env.NODE_ENV !== 'production') { + logError('In SVG mode painter not support method "' + method + '"'); + } }; } -export default SVGPainter; \ No newline at end of file +export default SVGPainter; diff --git a/src/svg/SVGPathRebuilder.ts b/src/svg/SVGPathRebuilder.ts new file mode 100644 index 000000000..1c9cc2245 --- /dev/null +++ b/src/svg/SVGPathRebuilder.ts @@ -0,0 +1,151 @@ +import { PathRebuilder } from '../core/PathProxy'; +import { isAroundZero } from './helper'; + +const mathSin = Math.sin; +const mathCos = Math.cos; +const PI = Math.PI; +const PI2 = Math.PI * 2; +const degree = 180 / PI; + + +export default class SVGPathRebuilder implements PathRebuilder { + private _d: (string | number)[] + private _str: string + private _invalid: boolean + + // If is start of subpath + private _start: boolean + private _p: number + + reset(precision?: number) { + this._start = true; + this._d = []; + this._str = ''; + + this._p = Math.pow(10, precision || 4); + } + moveTo(x: number, y: number) { + this._add('M', x, y); + } + lineTo(x: number, y: number) { + this._add('L', x, y); + } + bezierCurveTo(x: number, y: number, x2: number, y2: number, x3: number, y3: number) { + this._add('C', x, y, x2, y2, x3, y3); + } + quadraticCurveTo(x: number, y: number, x2: number, y2: number) { + this._add('Q', x, y, x2, y2); + } + arc(cx: number, cy: number, r: number, startAngle: number, endAngle: number, anticlockwise: boolean) { + this.ellipse(cx, cy, r, r, 0, startAngle, endAngle, anticlockwise); + } + ellipse( + cx: number, cy: number, + rx: number, ry: number, + psi: number, + startAngle: number, + endAngle: number, + anticlockwise: boolean + ) { + let dTheta = endAngle - startAngle; + const clockwise = !anticlockwise; + + const dThetaPositive = Math.abs(dTheta); + const isCircle = isAroundZero(dThetaPositive - PI2) + || (clockwise ? dTheta >= PI2 : -dTheta >= PI2); + + // Mapping to 0~2PI + const unifiedTheta = dTheta > 0 ? dTheta % PI2 : (dTheta % PI2 + PI2); + + let large = false; + if (isCircle) { + large = true; + } + else if (isAroundZero(dThetaPositive)) { + large = false; + } + else { + large = (unifiedTheta >= PI) === !!clockwise; + } + + const x0 = cx + rx * mathCos(startAngle); + const y0 = cy + ry * mathSin(startAngle); + + if (this._start) { + // Move to (x0, y0) only when CMD.A comes at the + // first position of a shape. + // For instance, when drawing a ring, CMD.A comes + // after CMD.M, so it's unnecessary to move to + // (x0, y0). + this._add('M', x0, y0); + } + + const xRot = Math.round(psi * degree); + // It will not draw if start point and end point are exactly the same + // We need to add two arcs + if (isCircle) { + const p = 1 / this._p; + const dTheta = (clockwise ? 1 : -1) * (PI2 - p); + this._add( + 'A', rx, ry, xRot, 1, +clockwise, + cx + rx * mathCos(startAngle + dTheta), + cy + ry * mathSin(startAngle + dTheta) + ); + // TODO. + // Usually we can simply divide the circle into two halfs arcs. + // But it will cause slightly diff with previous screenshot. + // We can't tell it but visual regression test can. To avoid too much breaks. + // We keep the logic on the browser as before. + // But in SSR mode wich has lower precision. We close the circle by adding another arc. + if (p > 1e-2) { + this._add('A', rx, ry, xRot, 0, +clockwise, x0, y0); + } + } + else { + const x = cx + rx * mathCos(endAngle); + const y = cy + ry * mathSin(endAngle); + + // FIXME Ellipse + this._add('A', rx, ry, xRot, +large, +clockwise, x, y); + } + + } + rect(x: number, y: number, w: number, h: number) { + this._add('M', x, y); + // Use relative coordinates to reduce the size. + this._add('l', w, 0); + this._add('l', 0, h); + this._add('l', -w, 0); + // this._add('L', x, y); + this._add('Z'); + } + closePath() { + // Not use Z as first command + if (this._d.length > 0) { + this._add('Z'); + } + } + + _add(cmd: string, a?: number, b?: number, c?: number, d?: number, e?: number, f?: number, g?: number, h?: number) { + const vals = []; + const p = this._p; + for (let i = 1; i < arguments.length; i++) { + const val = arguments[i]; + if (isNaN(val)) { + this._invalid = true; + return; + } + vals.push(Math.round(val * p) / p); + } + this._d.push(cmd + vals.join(' ')); + this._start = cmd === 'Z'; + } + + generateStr() { + this._str = this._invalid ? '' : this._d.join(''); + this._d = []; + } + getStr() { + return this._str; + } +} \ No newline at end of file diff --git a/src/svg/core.ts b/src/svg/core.ts index 7ddc66b0f..412038a44 100644 --- a/src/svg/core.ts +++ b/src/svg/core.ts @@ -1,23 +1,197 @@ -import { parse } from '../tool/color'; +import { keys, map } from '../core/util'; + +export type CSSSelectorVNode = Record +export type CSSAnimationVNode = Record> + +export const SVGNS = 'http://www.w3.org/2000/svg'; +export const XLINKNS = 'http://www.w3.org/1999/xlink'; +export const XMLNS = 'http://www.w3.org/2000/xmlns/'; +export const XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'; export function createElement(name: string) { - return document.createElementNS('http://www.w3.org/2000/svg', name); + return document.createElementNS(SVGNS, name); } -export function normalizeColor(color: string): { color: string, opacity: number } { - let opacity; - if (!color || color === 'transparent') { - color = 'none'; - } - else if (typeof color === 'string' && color.indexOf('rgba') > -1) { - const arr = parse(color); - if (arr) { - color = 'rgb(' + arr[0] + ',' + arr[1] + ',' + arr[2] + ')'; - opacity = arr[3]; +export type SVGVNodeAttrs = Record +export interface SVGVNode { + tag: string, + attrs: SVGVNodeAttrs, + children?: SVGVNode[], + text?: string + + // For patching + elm?: Node + key: string +}; +export function createVNode( + tag: string, + key: string, + attrs?: SVGVNodeAttrs, + children?: SVGVNode[], + text?: string +): SVGVNode { + return { + tag, + attrs: attrs || {}, + children, + text, + key + }; +} + +function createElementOpen(name: string, attrs?: SVGVNodeAttrs) { + const attrsStr: string[] = []; + if (attrs) { + // eslint-disable-next-line + for (let key in attrs) { + const val = attrs[key]; + let part = key; + // Same with the logic in patch. + if (val === false) { + continue; + } + else if (val !== true && val != null) { + part += `="${val}"`; + } + attrsStr.push(part); } } + return `<${name} ${attrsStr.join(' ')}>`; +} + +function createElementClose(name: string) { + return ``; +} + +export function vNodeToString(el: SVGVNode, opts?: { + newline?: boolean +}) { + opts = opts || {}; + const S = opts.newline ? '\n' : ''; + function convertElToString(el: SVGVNode): string { + const {children, tag, attrs} = el; + return createElementOpen(tag, attrs) + + (el.text || '') + + (children ? `${S}${map(children, child => convertElToString(child)).join(S)}${S}` : '') + + createElementClose(tag); + } + return convertElToString(el); +} + +export function getCssString( + selectorNodes: Record, + animationNodes: Record, + opts?: { + newline?: boolean + } +) { + opts = opts || {}; + const S = opts.newline ? '\n' : ''; + const bracketBegin = ` {${S}`; + const bracketEnd = `${S}}`; + const selectors = map(keys(selectorNodes), className => { + return className + bracketBegin + map(keys(selectorNodes[className]), attrName => { + return `${attrName}:${selectorNodes[className][attrName]};`; + }).join(S) + bracketEnd; + }).join(S); + const animations = map(keys(animationNodes), (animationName) => { + return `@keyframes ${animationName}${bracketBegin}` + map(keys(animationNodes[animationName]), percent => { + return percent + bracketBegin + map(keys(animationNodes[animationName][percent]), attrName => { + let val = animationNodes[animationName][percent][attrName]; + // postprocess + if (attrName === 'd') { + val = `path("${val}")`; + } + return `${attrName}:${val};`; + }).join(S) + bracketEnd; + }).join(S) + bracketEnd; + }).join(S); + + if (!selectors && !animations) { + return ''; + } + + return [''].join(S); +} + + +export interface BrushScope { + zrId: string + + shadowCache: Record + gradientCache: Record + patternCache: Record + clipPathCache: Record + + defs: Record + + cssNodes: Record + cssAnims: Record>> + + cssClassIdx: number + cssAnimIdx: number + + shadowIdx: number + gradientIdx: number + patternIdx: number + clipPathIdx: number + // configs + /** + * If create animates nodes. + */ + animation?: boolean, + + /** + * If will update. Some optimization for string generation can't be applied. + */ + willUpdate?: boolean + + /** + * If compress the output string. + */ + compress?: boolean +} + +export function createBrushScope(zrId: string): BrushScope { return { - color, - opacity: opacity == null ? 1 : opacity + zrId, + shadowCache: {}, + patternCache: {}, + gradientCache: {}, + clipPathCache: {}, + defs: {}, + + cssNodes: {}, + cssAnims: {}, + + cssClassIdx: 0, + cssAnimIdx: 0, + + shadowIdx: 0, + gradientIdx: 0, + patternIdx: 0, + clipPathIdx: 0 }; } + +export function createSVGVNode( + width: number | string, + height: number | string, + children?: SVGVNode[], + useViewBox?: boolean +) { + return createVNode( + 'svg', + 'root', + { + 'width': width, + 'height': height, + 'xmlns': SVGNS, + 'xmlns:xlink': XLINKNS, + 'version': '1.1', + 'baseProfile': 'full', + 'viewBox': useViewBox ? `0 0 ${width} ${height}` : false + }, + children + ); +} \ No newline at end of file diff --git a/src/svg/cssAnimation.ts b/src/svg/cssAnimation.ts new file mode 100644 index 000000000..38fe5cfe3 --- /dev/null +++ b/src/svg/cssAnimation.ts @@ -0,0 +1,365 @@ +import Transformable, { copyTransform } from '../core/Transformable'; +import Displayable from '../graphic/Displayable'; +import { SVGVNodeAttrs, BrushScope, createBrushScope} from './core'; +import Path from '../graphic/Path'; +import SVGPathRebuilder from './SVGPathRebuilder'; +import PathProxy from '../core/PathProxy'; +import { getPathPrecision, getSRTTransformString } from './helper'; +import { each, extend, filter, isNumber, isString, keys } from '../core/util'; +import Animator from '../animation/Animator'; +import CompoundPath from '../graphic/CompoundPath'; +import { AnimationEasing } from '../animation/easing'; +import { createCubicEasingFunc } from '../animation/cubicEasing'; + +export const EASING_MAP: Record = { + // From https://easings.net/ + cubicIn: '0.32,0,0.67,0', + cubicOut: '0.33,1,0.68,1', + cubicInOut: '0.65,0,0.35,1', + quadraticIn: '0.11,0,0.5,0', + quadraticOut: '0.5,1,0.89,1', + quadraticInOut: '0.45,0,0.55,1', + quarticIn: '0.5,0,0.75,0', + quarticOut: '0.25,1,0.5,1', + quarticInOut: '0.76,0,0.24,1', + quinticIn: '0.64,0,0.78,0', + quinticOut: '0.22,1,0.36,1', + quinticInOut: '0.83,0,0.17,1', + sinusoidalIn: '0.12,0,0.39,0', + sinusoidalOut: '0.61,1,0.88,1', + sinusoidalInOut: '0.37,0,0.63,1', + exponentialIn: '0.7,0,0.84,0', + exponentialOut: '0.16,1,0.3,1', + exponentialInOut: '0.87,0,0.13,1', + circularIn: '0.55,0,1,0.45', + circularOut: '0,0.55,0.45,1', + circularInOut: '0.85,0,0.15,1' + // TODO elastic, bounce +}; + +const transformOriginKey = 'transform-origin'; + +function buildPathString(el: Path, kfShape: Path['shape'], path: PathProxy) { + const shape = extend({}, el.shape); + extend(shape, kfShape); + + el.buildPath(path, shape); + const svgPathBuilder = new SVGPathRebuilder(); + svgPathBuilder.reset(getPathPrecision(el)); + path.rebuildPath(svgPathBuilder, 1); + svgPathBuilder.generateStr(); + // will add path("") when generated to css string in the final step. + return svgPathBuilder.getStr(); +} + +function setTransformOrigin(target: Record, transform: Transformable) { + const {originX, originY} = transform; + if (originX || originY) { + target[transformOriginKey] = `${originX}px ${originY}px`; + } +} + +export const ANIMATE_STYLE_MAP: Record = { + fill: 'fill', + opacity: 'opacity', + lineWidth: 'stroke-width', + lineDashOffset: 'stroke-dashoffset' + // TODO shadow is not supported. +}; + +type CssKF = Record; + +function addAnimation(cssAnim: Record, scope: BrushScope) { + const animationName = scope.zrId + '-ani-' + scope.cssAnimIdx++; + scope.cssAnims[animationName] = cssAnim; + return animationName; +} + +function createCompoundPathCSSAnimation( + el: CompoundPath, + attrs: SVGVNodeAttrs, + scope: BrushScope +) { + const paths = el.shape.paths; + const composedAnim: Record = {}; + let cssAnimationCfg: string; + let cssAnimationName: string; + each(paths, path => { + const subScope = createBrushScope(scope.zrId); + subScope.animation = true; + createCSSAnimation(path, {}, subScope, true); + const cssAnims = subScope.cssAnims; + const cssNodes = subScope.cssNodes; + const animNames = keys(cssAnims); + const len = animNames.length; + if (!len) { + return; + } + cssAnimationName = animNames[len - 1]; + // Only use last animation because they are conflicted. + const lastAnim = cssAnims[cssAnimationName]; + // eslint-disable-next-line + for (let percent in lastAnim) { + const kf = lastAnim[percent]; + composedAnim[percent] = composedAnim[percent] || { d: '' }; + composedAnim[percent].d += kf.d || ''; + } + // eslint-disable-next-line + for (let className in cssNodes) { + const val = cssNodes[className].animation; + if (val.indexOf(cssAnimationName) >= 0) { + // Only pick the animation configuration of last subpath. + cssAnimationCfg = val; + } + } + }); + + if (!cssAnimationCfg) { + return; + } + + // Remove the attrs in the element because it will be set by animation. + // Reduce the size. + attrs.d = false; + const animationName = addAnimation(composedAnim, scope); + return cssAnimationCfg.replace(cssAnimationName, animationName); +} + +function getEasingFunc(easing: AnimationEasing) { + return isString(easing) + ? EASING_MAP[easing] + ? `cubic-bezier(${EASING_MAP[easing]})` + : createCubicEasingFunc(easing) ? easing : '' + : ''; +} + +export function createCSSAnimation( + el: Displayable, + attrs: SVGVNodeAttrs, + scope: BrushScope, + onlyShape?: boolean +) { + const animators = el.animators; + const len = animators.length; + + const cssAnimations: string[] = []; + + if (el instanceof CompoundPath) { + const animationCfg = createCompoundPathCSSAnimation(el, attrs, scope); + if (animationCfg) { + cssAnimations.push(animationCfg); + } + else if (!len) { + return; + } + } + else if (!len) { + return; + } + // Group animators by it's configuration + const groupAnimators: Record[]]> = {}; + for (let i = 0; i < len; i++) { + const animator = animators[i]; + const cfgArr: (string | number)[] = [animator.getMaxTime() / 1000 + 's']; + const easing = getEasingFunc(animator.getClip().easing); + const delay = animator.getDelay(); + + if (easing) { + cfgArr.push(easing); + } + else { + cfgArr.push('linear'); + } + if (delay) { + cfgArr.push(delay / 1000 + 's'); + } + if (animator.getLoop()) { + cfgArr.push('infinite'); + } + const cfg = cfgArr.join(' '); + + // TODO fill mode + groupAnimators[cfg] = groupAnimators[cfg] || [cfg, [] as Animator[]]; + groupAnimators[cfg][1].push(animator); + } + + function createSingleCSSAnimation(groupAnimator: [string, Animator[]]) { + const animators = groupAnimator[1]; + const len = animators.length; + const transformKfs: Record = {}; + const shapeKfs: Record = {}; + + const finalKfs: Record = {}; + + const animationTimingFunctionAttrName = 'animation-timing-function'; + + function saveAnimatorTrackToCssKfs( + animator: Animator, + cssKfs: Record, + toCssAttrName?: (propName: string) => string + ) { + const tracks = animator.getTracks(); + const maxTime = animator.getMaxTime(); + for (let k = 0; k < tracks.length; k++) { + const track = tracks[k]; + if (track.needsAnimate()) { + const kfs = track.keyframes; + let attrName = track.propName; + toCssAttrName && (attrName = toCssAttrName(attrName)); + if (attrName) { + for (let i = 0; i < kfs.length; i++) { + const kf = kfs[i]; + const percent = Math.round(kf.time / maxTime * 100) + '%'; + const kfEasing = getEasingFunc(kf.easing); + const rawValue = kf.rawValue; + + // TODO gradient + if (isString(rawValue) || isNumber(rawValue)) { + cssKfs[percent] = cssKfs[percent] || {}; + cssKfs[percent][attrName] = kf.rawValue; + + if (kfEasing) { + // TODO. If different property have different easings. + cssKfs[percent][animationTimingFunctionAttrName] = kfEasing; + } + } + } + } + } + } + } + + // Find all transform animations. + // TODO origin, parent + for (let i = 0; i < len; i++) { + const animator = animators[i]; + const targetProp = animator.targetName; + if (!targetProp) { + !onlyShape && saveAnimatorTrackToCssKfs(animator, transformKfs); + } + else if (targetProp === 'shape') { + saveAnimatorTrackToCssKfs(animator, shapeKfs); + } + } + + // eslint-disable-next-line + for (let percent in transformKfs) { + const transform = {} as Transformable; + copyTransform(transform, el); + extend(transform, transformKfs[percent]); + const str = getSRTTransformString(transform); + const timingFunction = transformKfs[percent][animationTimingFunctionAttrName]; + finalKfs[percent] = str ? { + transform: str + } : {}; + // TODO set transform origin in element? + setTransformOrigin(finalKfs[percent], transform); + + // Save timing function + if (timingFunction) { + finalKfs[percent][animationTimingFunctionAttrName] = timingFunction; + } + }; + + + let path: PathProxy; + let canAnimateShape = true; + // eslint-disable-next-line + for (let percent in shapeKfs) { + finalKfs[percent] = finalKfs[percent] || {}; + + const isFirst = !path; + const timingFunction = shapeKfs[percent][animationTimingFunctionAttrName]; + + if (isFirst) { + path = new PathProxy(); + } + let len = path.len(); + path.reset(); + finalKfs[percent].d = buildPathString(el as Path, shapeKfs[percent], path); + let newLen = path.len(); + // Path data don't match. + if (!isFirst && len !== newLen) { + canAnimateShape = false; + break; + } + + // Save timing function + if (timingFunction) { + finalKfs[percent][animationTimingFunctionAttrName] = timingFunction; + } + }; + if (!canAnimateShape) { + // eslint-disable-next-line + for (let percent in finalKfs) { + delete finalKfs[percent].d; + } + } + + if (!onlyShape) { + for (let i = 0; i < len; i++) { + const animator = animators[i]; + const targetProp = animator.targetName; + if (targetProp === 'style') { + saveAnimatorTrackToCssKfs( + animator, finalKfs, (propName) => ANIMATE_STYLE_MAP[propName] + ); + } + } + } + + const percents = keys(finalKfs); + + // Set transform origin in attribute to reduce the size. + let allTransformOriginSame = true; + let transformOrigin; + for (let i = 1; i < percents.length; i++) { + const p0 = percents[i - 1]; + const p1 = percents[i]; + if (finalKfs[p0][transformOriginKey] !== finalKfs[p1][transformOriginKey]) { + allTransformOriginSame = false; + break; + } + transformOrigin = finalKfs[p0][transformOriginKey]; + } + if (allTransformOriginSame && transformOrigin) { + for (const percent in finalKfs) { + if (finalKfs[percent][transformOriginKey]) { + delete finalKfs[percent][transformOriginKey]; + } + } + attrs[transformOriginKey] = transformOrigin; + } + + if (filter( + percents, (percent) => keys(finalKfs[percent]).length > 0 + ).length) { + const animationName = addAnimation(finalKfs, scope); + // eslint-disable-next-line + // for (const attrName in finalKfs[percents[0]]) { + // // Remove the attrs in the element because it will be set by animation. + // // Reduce the size. + // attrs[attrName] = false; + // } + // animationName {duration easing delay loop} fillMode + return `${animationName} ${groupAnimator[0]} both`; + } + } + + // eslint-disable-next-line + for (let key in groupAnimators) { + const animationCfg = createSingleCSSAnimation(groupAnimators[key]); + if (animationCfg) { + cssAnimations.push(animationCfg); + } + } + + if (cssAnimations.length) { + const className = scope.zrId + '-cls-' + scope.cssClassIdx++; + scope.cssNodes['.' + className] = { + animation: cssAnimations.join(',') + }; + // TODO exists class? + attrs.class = className; + } +} \ No newline at end of file diff --git a/src/svg/domapi.ts b/src/svg/domapi.ts new file mode 100644 index 000000000..5e7c914f6 --- /dev/null +++ b/src/svg/domapi.ts @@ -0,0 +1,55 @@ +export function createTextNode(text: string): Text { + return document.createTextNode(text); +} + +export function createComment(text: string): Comment { + return document.createComment(text); +} + +export function insertBefore( + parentNode: Node, + newNode: Node, + referenceNode: Node | null +): void { + parentNode.insertBefore(newNode, referenceNode); +} + +export function removeChild(node: Node, child: Node): void { + node.removeChild(child); +} + +export function appendChild(node: Node, child: Node): void { + node.appendChild(child); +} + +export function parentNode(node: Node): Node | null { + return node.parentNode; +} + +export function nextSibling(node: Node): Node | null { + return node.nextSibling; +} + +export function tagName(elm: Element): string { + return elm.tagName; +} + +export function setTextContent(node: Node, text: string | null): void { + node.textContent = text; +} + +export function getTextContent(node: Node): string | null { + return node.textContent; +} + +export function isElement(node: Node): node is Element { + return node.nodeType === 1; +} + +export function isText(node: Node): node is Text { + return node.nodeType === 3; +} + +export function isComment(node: Node): node is Comment { + return node.nodeType === 8; +} diff --git a/src/svg/graphic.ts b/src/svg/graphic.ts index 8f27ab2e9..ba4892197 100644 --- a/src/svg/graphic.ts +++ b/src/svg/graphic.ts @@ -2,300 +2,174 @@ // 1. shadow // 2. Image: sx, sy, sw, sh -import {createElement, normalizeColor} from './core'; -import { PathRebuilder } from '../core/PathProxy'; -import * as matrix from '../core/matrix'; +import { + adjustTextY, + getIdURL, + getMatrixStr, + getPathPrecision, + getShadowKey, + getSRTTransformString, + hasShadow, + isAroundZero, + isGradient, + isImagePattern, + isLinearGradient, + isPattern, + isRadialGradient, + normalizeColor, + round4, + TEXT_ALIGN_TO_ANCHOR +} from './helper'; import Path, { PathStyleProps } from '../graphic/Path'; import ZRImage, { ImageStyleProps } from '../graphic/Image'; -import { DEFAULT_FONT, getLineHeight } from '../contain/text'; +import { getLineHeight } from '../contain/text'; import TSpan, { TSpanStyleProps } from '../graphic/TSpan'; -import { map } from '../core/util'; -import { normalizeLineDash } from '../graphic/helper/dashStyle'; - -export interface SVGProxy { - brush(el: T): void +import SVGPathRebuilder from './SVGPathRebuilder'; +import mapStyleToAttrs from './mapStyleToAttrs'; +import { SVGVNodeAttrs, createVNode, SVGVNode, vNodeToString, BrushScope } from './core'; +import { MatrixArray } from '../core/matrix'; +import Displayable from '../graphic/Displayable'; +import { assert, isFunction, isString, logError, map, retrieve2 } from '../core/util'; +import Polyline from '../graphic/shape/Polyline'; +import Polygon from '../graphic/shape/Polygon'; +import { GradientObject } from '../graphic/Gradient'; +import { ImagePatternObject, SVGPatternObject } from '../graphic/Pattern'; +import { createOrUpdateImage } from '../graphic/helper/image'; +import { ImageLike } from '../core/types'; +import { createCSSAnimation } from './cssAnimation'; +import { hasSeparateFont, parseFontSize } from '../graphic/Text'; +import { DEFAULT_FONT, DEFAULT_FONT_FAMILY } from '../core/platform'; + +const round = Math.round; + +function isImageLike(val: any): val is HTMLImageElement { + return val && isString(val.src); +} +function isCanvasLike(val: any): val is HTMLCanvasElement { + return val && isFunction(val.toDataURL); } -const NONE = 'none'; -const mathRound = Math.round; -const mathSin = Math.sin; -const mathCos = Math.cos; -const PI = Math.PI; -const PI2 = Math.PI * 2; -const degree = 180 / PI; - -const EPSILON = 1e-4; type AllStyleOption = PathStyleProps | TSpanStyleProps | ImageStyleProps; -function round3(val: number) { - return mathRound(val * 1e3) / 1e3; -} -function round4(val: number) { - return mathRound(val * 1e4) / 1e4; -} +function setStyleAttrs(attrs: SVGVNodeAttrs, style: AllStyleOption, el: Path | TSpan | ZRImage, scope: BrushScope) { + mapStyleToAttrs((key, val) => { + const isFillStroke = key === 'fill' || key === 'stroke'; + if (isFillStroke && isGradient(val)) { + setGradient(style, attrs, key, scope); + } + else if (isFillStroke && isPattern(val)) { + setPattern(el, attrs, key, scope); + } + else { + attrs[key] = val; + } + }, style, el, false); -function isAroundZero(val: number) { - return val < EPSILON && val > -EPSILON; + setShadow(el, attrs, scope); } -function pathHasFill(style: AllStyleOption): style is PathStyleProps { - const fill = (style as PathStyleProps).fill; - return fill != null && fill !== NONE; +function noRotateScale(m: MatrixArray) { + return isAroundZero(m[0] - 1) + && isAroundZero(m[1]) + && isAroundZero(m[2]) + && isAroundZero(m[3] - 1); } -function pathHasStroke(style: AllStyleOption): style is PathStyleProps { - const stroke = (style as PathStyleProps).stroke; - return stroke != null && stroke !== NONE; +function noTranslate(m: MatrixArray) { + return isAroundZero(m[4]) && isAroundZero(m[5]); } -function setTransform(svgEl: SVGElement, m: matrix.MatrixArray) { - if (m) { - attr(svgEl, 'transform', 'matrix(' - // Avoid large string of matrix - // PENDING If have precision issue when scaled - + round3(m[0]) + ',' - + round3(m[1]) + ',' - + round3(m[2]) + ',' - + round3(m[3]) + ',' - + round4(m[4]) + ',' - + round4(m[5]) - + ')'); +function setTransform(attrs: SVGVNodeAttrs, m: MatrixArray, compress?: boolean) { + if (m && !(noTranslate(m) && noRotateScale(m))) { + const mul = compress ? 10 : 1e4; + // Use translate possible to reduce the size a bit. + attrs.transform = noRotateScale(m) + ? `translate(${round(m[4] * mul) / mul} ${round(m[5] * mul) / mul})` : getMatrixStr(m); } } -function attr(el: SVGElement, key: string, val: string) { - if (!val || (val as any).type !== 'linear' && (val as any).type !== 'radial') { - // Don't set attribute for gradient, since it need new dom nodes - el.setAttribute(key, val); - } -} +type ShapeMapDesc = (string | [string, string])[]; +type ConvertShapeToAttr = (shape: any, attrs: SVGVNodeAttrs, mul?: number) => void; +type ShapeValidator = (shape: any) => boolean; -function attrXLink(el: SVGElement, key: string, val: string) { - el.setAttributeNS('http://www.w3.org/1999/xlink', key, val); +function convertPolyShape(shape: Polygon['shape'], attrs: SVGVNodeAttrs, mul: number) { + const points = shape.points; + const strArr = []; + for (let i = 0; i < points.length; i++) { + strArr.push(round(points[i][0] * mul) / mul); + strArr.push(round(points[i][1] * mul) / mul); + } + attrs.points = strArr.join(' '); } -function attrXML(el: SVGElement, key: string, val: string) { - el.setAttributeNS('http://www.w3.org/XML/1998/namespace', key, val); +function validatePolyShape(shape: Polyline['shape']) { + return !shape.smooth; } -function bindStyle(svgEl: SVGElement, style: PathStyleProps, el?: Path): void -function bindStyle(svgEl: SVGElement, style: TSpanStyleProps, el?: TSpan): void -function bindStyle(svgEl: SVGElement, style: ImageStyleProps, el?: ZRImage): void -function bindStyle(svgEl: SVGElement, style: AllStyleOption, el?: Path | TSpan | ZRImage) { - const opacity = style.opacity == null ? 1 : style.opacity; - - // only set opacity. stroke and fill cannot be applied to svg image - if (el instanceof ZRImage) { - attr(svgEl, 'opacity', opacity + ''); - return; - } - - if (pathHasFill(style)) { - const fill = normalizeColor(style.fill as string); - attr(svgEl, 'fill', fill.color); - attr(svgEl, - 'fill-opacity', - (style.fillOpacity != null - ? style.fillOpacity * fill.opacity * opacity - : fill.opacity * opacity - ) + '' - ); - } - else { - attr(svgEl, 'fill', NONE); - } - - if (pathHasStroke(style)) { - const stroke = normalizeColor(style.stroke as string); - attr(svgEl, 'stroke', stroke.color); - const strokeWidth = style.lineWidth; - const strokeScale = style.strokeNoScale - ? (el as Path).getLineScale() - : 1; - attr(svgEl, 'stroke-width', (strokeScale ? strokeWidth / strokeScale : 0) + ''); - // stroke then fill for text; fill then stroke for others - attr(svgEl, 'paint-order', style.strokeFirst ? 'stroke' : 'fill'); - attr(svgEl, 'stroke-opacity', ( - style.strokeOpacity != null - ? style.strokeOpacity * stroke.opacity * opacity - : stroke.opacity * opacity - ) + ''); - let lineDash = style.lineDash && strokeWidth > 0 && normalizeLineDash(style.lineDash, strokeWidth); - if (lineDash) { - let lineDashOffset = style.lineDashOffset; - if (strokeScale && strokeScale !== 1) { - lineDash = map(lineDash, function (rawVal) { - return rawVal / strokeScale; - }); - if (lineDashOffset) { - lineDashOffset /= strokeScale; - lineDashOffset = mathRound(lineDashOffset); - } +function createAttrsConvert(desc: ShapeMapDesc): ConvertShapeToAttr { + const normalizedDesc: [string, string][] = map(desc, (item) => + (typeof item === 'string' ? [item, item] : item) + ); + + return function (shape, attrs, mul) { + for (let i = 0; i < normalizedDesc.length; i++) { + const item = normalizedDesc[i]; + const val = shape[item[0]]; + if (val != null) { + attrs[item[1]] = round(val * mul) / mul; } - attr(svgEl, 'stroke-dasharray', lineDash.join(',')); - attr(svgEl, 'stroke-dashoffset', (lineDashOffset || 0) + ''); } - else { - attr(svgEl, 'stroke-dasharray', NONE); - } - - // PENDING - style.lineCap && attr(svgEl, 'stroke-linecap', style.lineCap); - style.lineJoin && attr(svgEl, 'stroke-linejoin', style.lineJoin); - style.miterLimit && attr(svgEl, 'stroke-miterlimit', style.miterLimit + ''); - } - else { - attr(svgEl, 'stroke', NONE); - } + }; } -class SVGPathRebuilder implements PathRebuilder { - private _d: (string | number)[] - private _str: string - private _invalid: boolean - - // If is start of subpath - private _start: boolean; - - reset() { - this._start = true; - this._d = []; - this._str = ''; - } - moveTo(x: number, y: number) { - this._add('M', x, y); - } - lineTo(x: number, y: number) { - this._add('L', x, y); - } - bezierCurveTo(x: number, y: number, x2: number, y2: number, x3: number, y3: number) { - this._add('C', x, y, x2, y2, x3, y3); - } - quadraticCurveTo(x: number, y: number, x2: number, y2: number) { - this._add('Q', x, y, x2, y2); - } - arc(cx: number, cy: number, r: number, startAngle: number, endAngle: number, anticlockwise: boolean) { - this.ellipse(cx, cy, r, r, 0, startAngle, endAngle, anticlockwise); - } - ellipse( - cx: number, cy: number, - rx: number, ry: number, - psi: number, - startAngle: number, - endAngle: number, - anticlockwise: boolean - ) { - let dTheta = endAngle - startAngle; - const clockwise = !anticlockwise; - - const dThetaPositive = Math.abs(dTheta); - const isCircle = isAroundZero(dThetaPositive - PI2) - || (clockwise ? dTheta >= PI2 : -dTheta >= PI2); - - // Mapping to 0~2PI - const unifiedTheta = dTheta > 0 ? dTheta % PI2 : (dTheta % PI2 + PI2); - - let large = false; - if (isCircle) { - large = true; - } - else if (isAroundZero(dThetaPositive)) { - large = false; - } - else { - large = (unifiedTheta >= PI) === !!clockwise; - } - - const x0 = round4(cx + rx * mathCos(startAngle)); - const y0 = round4(cy + ry * mathSin(startAngle)); - - // It will not draw if start point and end point are exactly the same - // We need to shift the end point with a small value - // FIXME A better way to draw circle ? - if (isCircle) { - if (clockwise) { - dTheta = PI2 - 1e-4; - } - else { - dTheta = -PI2 + 1e-4; - } - - large = true; - } - - if (this._start) { - // Move to (x0, y0) only when CMD.A comes at the - // first position of a shape. - // For instance, when drawing a ring, CMD.A comes - // after CMD.M, so it's unnecessary to move to - // (x0, y0). - this._add('M', x0, y0); - } - - const x = round4(cx + rx * mathCos(startAngle + dTheta)); - const y = round4(cy + ry * mathSin(startAngle + dTheta)); - - if (isNaN(x0) || isNaN(y0) || isNaN(rx) || isNaN(ry) || isNaN(psi) || isNaN(degree) || isNaN(x) || isNaN(y)) { - return ''; - } - - // FIXME Ellipse - this._add('A', round4(rx), round4(ry), - mathRound(psi * degree), +large, +clockwise, x, y); - } - rect(x: number, y: number, w: number, h: number) { - this._add('M', x, y); - this._add('L', x + w, y); - this._add('L', x + w, y + h); - this._add('L', x, y + h); - this._add('L', x, y); - this._add('Z'); - } - closePath() { - // Not use Z as first command - if (this._d.length > 0) { - this._add('Z'); - } - } - - _add(cmd: string, a?: number, b?: number, c?: number, d?: number, e?: number, f?: number, g?: number, h?: number) { - this._d.push(cmd); - for (let i = 1; i < arguments.length; i++) { - const val = arguments[i]; - if (isNaN(val)) { - this._invalid = true; - return; - } - this._d.push(round4(val)); - } - this._start = cmd === 'Z'; - } - - generateStr() { - this._str = this._invalid ? '' : this._d.join(' '); - this._d = []; - } - getStr() { - return this._str; - } -} +const buitinShapesDef: Record = { + circle: [createAttrsConvert(['cx', 'cy', 'r'])], + polyline: [convertPolyShape, validatePolyShape], + polygon: [convertPolyShape, validatePolyShape] + // Ignore line because it will be larger. +}; interface PathWithSVGBuildPath extends Path { __svgPathVersion: number __svgPathBuilder: SVGPathRebuilder + __svgPathStrokePercent: number } -const svgPath: SVGProxy = { - brush(el: Path) { - const style = el.style; - - let svgEl = el.__svgEl; - if (!svgEl) { - svgEl = createElement('path'); - el.__svgEl = svgEl; +function hasShapeAnimation(el: Displayable) { + const animators = el.animators; + for (let i = 0; i < animators.length; i++) { + if (animators[i].targetName === 'shape') { + return true; } + } + return false; +} +export function brushSVGPath(el: Path, scope: BrushScope) { + const style = el.style; + const shape = el.shape; + const builtinShpDef = buitinShapesDef[el.type]; + const attrs: SVGVNodeAttrs = {}; + const needsAnimate = scope.animation; + let svgElType = 'path'; + const strokePercent = el.style.strokePercent; + const precision = (scope.compress && getPathPrecision(el)) || 4; + // Using SVG builtin shapes if possible + if (builtinShpDef + // Force to use path if it will update later. + // To avoid some animation(like morph) fail + && !scope.willUpdate + && !(builtinShpDef[1] && !builtinShpDef[1](shape)) + // use `path` to simplify the animate element creation logic. + && !(needsAnimate && hasShapeAnimation(el)) + && !(strokePercent < 1) + ) { + svgElType = el.type; + const mul = Math.pow(10, precision); + builtinShpDef[0](shape, attrs, mul); + } + else { if (!el.path) { el.createPathProxy(); } @@ -306,139 +180,417 @@ const svgPath: SVGProxy = { el.buildPath(path, el.shape); el.pathUpdated(); } - const pathVersion = path.getVersion(); const elExt = el as PathWithSVGBuildPath; + let svgPathBuilder = elExt.__svgPathBuilder; - if (elExt.__svgPathVersion !== pathVersion || !svgPathBuilder || el.style.strokePercent < 1) { + if (elExt.__svgPathVersion !== pathVersion + || !svgPathBuilder + || strokePercent !== elExt.__svgPathStrokePercent + ) { if (!svgPathBuilder) { svgPathBuilder = elExt.__svgPathBuilder = new SVGPathRebuilder(); } - svgPathBuilder.reset(); - path.rebuildPath(svgPathBuilder, el.style.strokePercent); + svgPathBuilder.reset(precision); + path.rebuildPath(svgPathBuilder, strokePercent); svgPathBuilder.generateStr(); elExt.__svgPathVersion = pathVersion; + elExt.__svgPathStrokePercent = strokePercent; } - attr(svgEl, 'd', svgPathBuilder.getStr()); - - bindStyle(svgEl, style, el); - setTransform(svgEl, el.transform); + attrs.d = svgPathBuilder.getStr(); } -}; -export {svgPath as path}; + setTransform(attrs, el.transform); + setStyleAttrs(attrs, style, el, scope); + + scope.animation && createCSSAnimation(el, attrs, scope); -/*************************************************** - * IMAGE - **************************************************/ -const svgImage: SVGProxy = { - brush(el: ZRImage) { - const style = el.style; - let image = style.image; + return createVNode(svgElType, el.id + '', attrs); +} - if (image instanceof HTMLImageElement) { +export function brushSVGImage(el: ZRImage, scope: BrushScope) { + const style = el.style; + let image = style.image; + + if (image && !isString(image)) { + if (isImageLike(image)) { image = image.src; } // heatmap layer in geo may be a canvas - else if (image instanceof HTMLCanvasElement) { + else if (isCanvasLike(image)) { image = image.toDataURL(); } - if (!image) { - return; - } + } - const x = style.x || 0; - const y = style.y || 0; + if (!image) { + return; + } - const dw = style.width; - const dh = style.height; + const x = style.x || 0; + const y = style.y || 0; - let svgEl = el.__svgEl; - if (!svgEl) { - svgEl = createElement('image'); - el.__svgEl = svgEl; - } + const dw = style.width; + const dh = style.height; + + const attrs: SVGVNodeAttrs = { + href: image as string, + width: dw, + height: dh + }; + if (x) { + attrs.x = x; + } + if (y) { + attrs.y = y; + } + + setTransform(attrs, el.transform); + setStyleAttrs(attrs, style, el, scope); + + scope.animation && createCSSAnimation(el, attrs, scope); + + return createVNode('image', el.id + '', attrs); +}; + +export function brushSVGTSpan(el: TSpan, scope: BrushScope) { + const style = el.style; + + let text = style.text; + // Convert to string + text != null && (text += ''); + if (!text || isNaN(style.x) || isNaN(style.y)) { + return; + } - if (image !== el.__imageSrc) { - attrXLink(svgEl, 'href', image as string); - // Caching image src - el.__imageSrc = image as string; + // style.font has been normalized by `normalizeTextStyle`. + const font = style.font || DEFAULT_FONT; + + // Consider different font display differently in vertial align, we always + // set vertialAlign as 'middle', and use 'y' to locate text vertically. + const x = style.x || 0; + const y = adjustTextY(style.y || 0, getLineHeight(font), style.textBaseline); + const textAlign = TEXT_ALIGN_TO_ANCHOR[style.textAlign as keyof typeof TEXT_ALIGN_TO_ANCHOR] + || style.textAlign; + + const attrs: SVGVNodeAttrs = { + 'dominant-baseline': 'central', + 'text-anchor': textAlign + }; + + if (hasSeparateFont(style)) { + // Set separate font attributes if possible. Or some platform like PowerPoint may not support it. + let separatedFontStr = ''; + const fontStyle = style.fontStyle; + const fontSize = parseFontSize(style.fontSize); + if (!parseFloat(fontSize)) { // is 0px + return; } - attr(svgEl, 'width', dw + ''); - attr(svgEl, 'height', dh + ''); + const fontFamily = style.fontFamily || DEFAULT_FONT_FAMILY; + const fontWeight = style.fontWeight; + separatedFontStr += `font-size:${fontSize};font-family:${fontFamily};`; + + // TODO reduce the attribute to set. But should it inherit from the container element? + if (fontStyle && fontStyle !== 'normal') { + separatedFontStr += `font-style:${fontStyle};`; + } + if (fontWeight && fontWeight !== 'normal') { + separatedFontStr += `font-weight:${fontWeight};`; + } + attrs.style = separatedFontStr; + } + else { + // Use set font manually + attrs.style = `font: ${font}`; + } - attr(svgEl, 'x', x + ''); - attr(svgEl, 'y', y + ''); - bindStyle(svgEl, style, el); - setTransform(svgEl, el.transform); + if (text.match(/\s/)) { + // only enabled when have space in text. + attrs['xml:space'] = 'preserve'; } -}; -export {svgImage as image}; - -/*************************************************** - * TEXT - **************************************************/ -const TEXT_ALIGN_TO_ANCHOR = { - left: 'start', - right: 'end', - center: 'middle', - middle: 'middle' -}; + if (x) { + attrs.x = x; + } + if (y) { + attrs.y = y; + } + setTransform(attrs, el.transform); + setStyleAttrs(attrs, style, el, scope); + + scope.animation && createCSSAnimation(el, attrs, scope); + + return createVNode('text', el.id + '', attrs, undefined, text); +} -function adjustTextY(y: number, lineHeight: number, textBaseline: CanvasTextBaseline): number { - // TODO Other values. - if (textBaseline === 'top') { - y += lineHeight / 2; +export function brush(el: Displayable, scope: BrushScope): SVGVNode { + if (el instanceof Path) { + return brushSVGPath(el, scope); } - else if (textBaseline === 'bottom') { - y -= lineHeight / 2; + else if (el instanceof ZRImage) { + return brushSVGImage(el, scope); + } + else if (el instanceof TSpan) { + return brushSVGTSpan(el, scope); } - return y; } -const svgText: SVGProxy = { - brush(el: TSpan) { - const style = el.style; +function setShadow( + el: Displayable, + attrs: SVGVNodeAttrs, + scope: BrushScope +) { + const style = el.style; + if (hasShadow(style)) { + const shadowKey = getShadowKey(el); + const shadowCache = scope.shadowCache; + let shadowId = shadowCache[shadowKey]; + if (!shadowId) { + const globalScale = el.getGlobalScale(); + const scaleX = globalScale[0]; + const scaleY = globalScale[1]; + if (!scaleX || !scaleY) { + return; + } - let text = style.text; - // Convert to string - text != null && (text += ''); - if (!text || isNaN(style.x) || isNaN(style.y)) { - return; + const offsetX = style.shadowOffsetX || 0; + const offsetY = style.shadowOffsetY || 0; + const blur = style.shadowBlur; + const {opacity, color} = normalizeColor(style.shadowColor); + const stdDx = blur / 2 / scaleX; + const stdDy = blur / 2 / scaleY; + const stdDeviation = stdDx + ' ' + stdDy; + // Use a simple prefix to reduce the size + shadowId = scope.zrId + '-s' + scope.shadowIdx++; + scope.defs[shadowId] = createVNode( + 'filter', shadowId, + { + 'id': shadowId, + 'x': '-100%', + 'y': '-100%', + 'width': '300%', + 'height': '300%' + }, + [ + createVNode('feDropShadow', '', { + 'dx': offsetX / scaleX, + 'dy': offsetY / scaleY, + 'stdDeviation': stdDeviation, + 'flood-color': color, + 'flood-opacity': opacity + }) + ] + ); + shadowCache[shadowKey] = shadowId; } + attrs.filter = getIdURL(shadowId); + } +} - let textSvgEl = el.__svgEl as SVGTextElement; - if (!textSvgEl) { - textSvgEl = createElement('text') as SVGTextElement; - attrXML(textSvgEl, 'xml:space', 'preserve'); - el.__svgEl = textSvgEl; +function setGradient( + style: PathStyleProps, + attrs: SVGVNodeAttrs, + target: 'fill' | 'stroke', + scope: BrushScope +) { + const val = style[target] as GradientObject; + let gradientTag; + let gradientAttrs: SVGVNodeAttrs = { + 'gradientUnits': val.global + ? 'userSpaceOnUse' // x1, x2, y1, y2 in range of 0 to canvas width or height + : 'objectBoundingBox' // x1, x2, y1, y2 in range of 0 to 1] + }; + if (isLinearGradient(val)) { + gradientTag = 'linearGradient'; + gradientAttrs.x1 = val.x; + gradientAttrs.y1 = val.y; + gradientAttrs.x2 = val.x2; + gradientAttrs.y2 = val.y2; + } + else if (isRadialGradient(val)) { + gradientTag = 'radialGradient'; + gradientAttrs.cx = retrieve2(val.x, 0.5); + gradientAttrs.cy = retrieve2(val.y, 0.5); + gradientAttrs.r = retrieve2(val.r, 0.5); + } + else { + if (process.env.NODE_ENV !== 'production') { + logError('Illegal gradient type.'); } + return; + } - const font = style.font || DEFAULT_FONT; + const colors = val.colorStops; - // style.font has been normalized by `normalizeTextStyle`. - const textSvgElStyle = textSvgEl.style; - textSvgElStyle.font = font; + const colorStops = []; + for (let i = 0, len = colors.length; i < len; ++i) { + const offset = round4(colors[i].offset) * 100 + '%'; - textSvgEl.textContent = text; + const stopColor = colors[i].color; + // Fix Safari bug that stop-color not recognizing alpha #9014 + const {color, opacity} = normalizeColor(stopColor); - bindStyle(textSvgEl, style, el); - setTransform(textSvgEl, el.transform); + const stopsAttrs: SVGVNodeAttrs = { + 'offset': offset + }; + // stop-color cannot be color, since: + // The opacity value used for the gradient calculation is the + // *product* of the value of stop-opacity and the opacity of the + // value of stop-color. + // See https://www.w3.org/TR/SVG2/pservers.html#StopOpacityProperty - // Consider different font display differently in vertial align, we always - // set vertialAlign as 'middle', and use 'y' to locate text vertically. - const x = style.x || 0; - const y = adjustTextY(style.y || 0, getLineHeight(font), style.textBaseline); - const textAlign = TEXT_ALIGN_TO_ANCHOR[style.textAlign as keyof typeof TEXT_ALIGN_TO_ANCHOR] - || style.textAlign; + stopsAttrs['stop-color'] = color; + if (opacity < 1) { + stopsAttrs['stop-opacity'] = opacity; + } + colorStops.push( + createVNode('stop', i + '', stopsAttrs) + ); + } - attr(textSvgEl, 'dominant-baseline', 'central'); - attr(textSvgEl, 'text-anchor', textAlign); - attr(textSvgEl, 'x', x + ''); - attr(textSvgEl, 'y', y + ''); + // Use the whole html as cache key. + const gradientVNode = createVNode(gradientTag, '', gradientAttrs, colorStops); + const gradientKey = vNodeToString(gradientVNode); + const gradientCache = scope.gradientCache; + let gradientId = gradientCache[gradientKey]; + if (!gradientId) { + gradientId = scope.zrId + '-g' + scope.gradientIdx++; + gradientCache[gradientKey] = gradientId; + + gradientAttrs.id = gradientId; + scope.defs[gradientId] = createVNode( + gradientTag, gradientId, gradientAttrs, colorStops + ); } -}; -export {svgText as text}; + + attrs[target] = getIdURL(gradientId); +} + +function setPattern( + el: Displayable, + attrs: SVGVNodeAttrs, + target: 'fill' | 'stroke', + scope: BrushScope +) { + const val = el.style[target] as ImagePatternObject | SVGPatternObject; + const patternAttrs: SVGVNodeAttrs = { + 'patternUnits': 'userSpaceOnUse' + }; + let child: SVGVNode; + if (isImagePattern(val)) { + let imageWidth = val.imageWidth; + let imageHeight = val.imageHeight; + let imageSrc; + const patternImage = val.image; + if (isString(patternImage)) { + imageSrc = patternImage; + } + else if (isImageLike(patternImage)) { + imageSrc = patternImage.src; + } + else if (isCanvasLike(patternImage)) { + imageSrc = patternImage.toDataURL(); + } + + if (typeof Image === 'undefined') { + const errMsg = 'Image width/height must been given explictly in svg-ssr renderer.'; + assert(imageWidth, errMsg); + assert(imageHeight, errMsg); + } + else if (imageWidth == null || imageHeight == null) { + // TODO + const setSizeToVNode = (vNode: SVGVNode, img: ImageLike) => { + if (vNode) { + const svgEl = vNode.elm as SVGElement; + const width = (vNode.attrs.width = imageWidth || img.width); + const height = (vNode.attrs.height = imageHeight || img.height); + if (svgEl) { + svgEl.setAttribute('width', width as any); + svgEl.setAttribute('height', height as any); + } + } + }; + const createdImage = createOrUpdateImage( + imageSrc, null, el, (img) => { + setSizeToVNode(patternVNode, img); + setSizeToVNode(child, img); + } + ); + if (createdImage && createdImage.width && createdImage.height) { + // Loaded before + imageWidth = imageWidth || createdImage.width; + imageHeight = imageHeight || createdImage.height; + } + } + + child = createVNode( + 'image', + 'img', + { + href: imageSrc, + width: imageWidth, + height: imageHeight + } + ); + patternAttrs.width = imageWidth; + patternAttrs.height = imageHeight; + } + else if (val.svgElement) { // Only string supported in SSR. + // TODO it's not so good to use textContent as innerHTML + child = val.svgElement; + patternAttrs.width = val.svgWidth; + patternAttrs.height = val.svgHeight; + } + if (!child) { + return; + } + + patternAttrs.patternTransform = getSRTTransformString(val); + + // Use the whole html as cache key. + let patternVNode = createVNode( + 'pattern', + '', + patternAttrs, + [child] + ); + const patternKey = vNodeToString(patternVNode); + const patternCache = scope.patternCache; + let patternId = patternCache[patternKey]; + if (!patternId) { + patternId = scope.zrId + '-p' + scope.patternIdx++; + patternCache[patternKey] = patternId; + patternAttrs.id = patternId; + patternVNode = scope.defs[patternId] = createVNode( + 'pattern', + patternId, + patternAttrs, + [child] + ); + } + + attrs[target] = getIdURL(patternId); +} + +export function setClipPath( + clipPath: Path, + attrs: SVGVNodeAttrs, + scope: BrushScope +) { + const {clipPathCache, defs} = scope; + let clipPathId = clipPathCache[clipPath.id]; + if (!clipPathId) { + clipPathId = scope.zrId + '-c' + scope.clipPathIdx++; + const clipPathAttrs: SVGVNodeAttrs = { + id: clipPathId + }; + + clipPathCache[clipPath.id] = clipPathId; + defs[clipPathId] = createVNode( + 'clipPath', clipPathId, clipPathAttrs, + [brushSVGPath(clipPath, scope)] + ); + } + attrs['clip-path'] = getIdURL(clipPathId); +} diff --git a/src/svg/helper.ts b/src/svg/helper.ts new file mode 100644 index 000000000..02c1e46c1 --- /dev/null +++ b/src/svg/helper.ts @@ -0,0 +1,192 @@ +// Shared methods of svg and svg-ssr + +import { MatrixArray } from '../core/matrix'; +import Transformable, { TransformProp } from '../core/Transformable'; +import { RADIAN_TO_DEGREE, retrieve2, logError, isFunction } from '../core/util'; +import Displayable from '../graphic/Displayable'; +import { GradientObject } from '../graphic/Gradient'; +import { LinearGradientObject } from '../graphic/LinearGradient'; +import Path from '../graphic/Path'; +import { ImagePatternObject, PatternObject, SVGPatternObject } from '../graphic/Pattern'; +import { RadialGradientObject } from '../graphic/RadialGradient'; +import { parse } from '../tool/color'; +import env from '../core/env'; + +const mathRound = Math.round; + +export function normalizeColor(color: string): { color: string; opacity: number; } { + let opacity; + if (!color || color === 'transparent') { + color = 'none'; + } + else if (typeof color === 'string' && color.indexOf('rgba') > -1) { + const arr = parse(color); + if (arr) { + // TODO use hex? + color = 'rgb(' + arr[0] + ',' + arr[1] + ',' + arr[2] + ')'; + opacity = arr[3]; + } + } + return { + color, + opacity: opacity == null ? 1 : opacity + }; +} +const EPSILON = 1e-4; +export function isAroundZero(transform: number) { + return transform < EPSILON && transform > -EPSILON; +} + +export function round3(transform: number) { + return mathRound(transform * 1e3) / 1e3; +} +export function round4(transform: number) { + return mathRound(transform * 1e4) / 1e4; +} +export function round1(transform: number) { + return mathRound(transform * 10) / 10; +} + +export function getMatrixStr(m: MatrixArray) { + return 'matrix(' + // Avoid large string of matrix + // PENDING If have precision issue when scaled + + round3(m[0]) + ',' + + round3(m[1]) + ',' + + round3(m[2]) + ',' + + round3(m[3]) + ',' + + round4(m[4]) + ',' + + round4(m[5]) + + ')'; +} + +export const TEXT_ALIGN_TO_ANCHOR = { + left: 'start', + right: 'end', + center: 'middle', + middle: 'middle' +}; + +export function adjustTextY(y: number, lineHeight: number, textBaseline: CanvasTextBaseline): number { + // TODO Other baselines. + if (textBaseline === 'top') { + y += lineHeight / 2; + } + else if (textBaseline === 'bottom') { + y -= lineHeight / 2; + } + return y; +} + + +export function hasShadow(style: Displayable['style']) { + // TODO: textBoxShadowBlur is not supported yet + return style + && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY); +} + +export function getShadowKey(displayable: Displayable) { + const style = displayable.style; + const globalScale = displayable.getGlobalScale(); + return [ + style.shadowColor, + (style.shadowBlur || 0).toFixed(2), // Reduce the precision + (style.shadowOffsetX || 0).toFixed(2), + (style.shadowOffsetY || 0).toFixed(2), + globalScale[0], + globalScale[1] + ].join(','); +} + +export function getClipPathsKey(clipPaths: Path[]) { + let key: number[] = []; + if (clipPaths) { + for (let i = 0; i < clipPaths.length; i++) { + const clipPath = clipPaths[i]; + key.push(clipPath.id); + } + } + return key.join(','); +} + +export function isImagePattern(val: any): val is ImagePatternObject { + return val && (!!(val as ImagePatternObject).image); +} +export function isSVGPattern(val: any): val is SVGPatternObject { + return val && (!!(val as SVGPatternObject).svgElement); +} +export function isPattern(val: any): val is PatternObject { + return isImagePattern(val) || isSVGPattern(val); +} + +export function isLinearGradient(val: GradientObject): val is LinearGradientObject { + return val.type === 'linear'; +} + +export function isRadialGradient(val: GradientObject): val is RadialGradientObject { + return val.type === 'radial'; +} + +export function isGradient(val: any): val is GradientObject { + return val && ( + (val as GradientObject).type === 'linear' + || (val as GradientObject).type === 'radial' + ); +} + +export function getIdURL(id: string) { + return `url(#${id})`; +} + +export function getPathPrecision(el: Path) { + const scale = el.getGlobalScale(); + const size = Math.max(scale[0], scale[1]); + return Math.max(Math.ceil(Math.log(size) / Math.log(10)), 1); +} + +export function getSRTTransformString( + transform: Partial> +) { + const x = transform.x || 0; + const y = transform.y || 0; + const rotation = (transform.rotation || 0) * RADIAN_TO_DEGREE; + const scaleX = retrieve2(transform.scaleX, 1); + const scaleY = retrieve2(transform.scaleY, 1); + const skewX = transform.skewX || 0; + const skewY = transform.skewY || 0; + const res = []; + if (x || y) { + // TODO not using px unit? + res.push(`translate(${x}px,${y}px)`); + } + if (rotation) { + res.push(`rotate(${rotation})`); + } + if (scaleX !== 1 || scaleY !== 1) { + res.push(`scale(${scaleX},${scaleY})`); + } + if (skewX || skewY) { + res.push(`skew(${mathRound(skewX * RADIAN_TO_DEGREE)}deg, ${mathRound(skewY * RADIAN_TO_DEGREE)}deg)`); + } + + return res.join(' '); +} + +export const encodeBase64 = (function () { + if (env.hasGlobalWindow && isFunction(window.btoa)) { + return function (str: string) { + return window.btoa(unescape(str)); + }; + } + if (typeof Buffer !== 'undefined') { + return function (str: string) { + return Buffer.from(str).toString('base64'); + }; + } + return function (str: string): string { + if (process.env.NODE_ENV !== 'production') { + logError('Base64 isn\'t natively supported in the current environment.'); + } + return null; + }; +})(); \ No newline at end of file diff --git a/src/svg/mapStyleToAttrs.ts b/src/svg/mapStyleToAttrs.ts new file mode 100644 index 000000000..486f3bda7 --- /dev/null +++ b/src/svg/mapStyleToAttrs.ts @@ -0,0 +1,110 @@ + +import Path, { DEFAULT_PATH_STYLE, PathStyleProps } from '../graphic/Path'; +import ZRImage, { ImageStyleProps } from '../graphic/Image'; +import TSpan, { TSpanStyleProps } from '../graphic/TSpan'; +import { getLineDash } from '../canvas/dashStyle'; +import { map } from '../core/util'; +import { normalizeColor } from './helper'; + +type AllStyleOption = PathStyleProps | TSpanStyleProps | ImageStyleProps; + +const NONE = 'none'; +const mathRound = Math.round; + +function pathHasFill(style: AllStyleOption): style is PathStyleProps { + const fill = (style as PathStyleProps).fill; + return fill != null && fill !== NONE; +} + +function pathHasStroke(style: AllStyleOption): style is PathStyleProps { + const stroke = (style as PathStyleProps).stroke; + return stroke != null && stroke !== NONE; +} + +const strokeProps = ['lineCap', 'miterLimit', 'lineJoin'] as const; +const svgStrokeProps = map(strokeProps, prop => `stroke-${prop.toLowerCase()}`); + +export default function mapStyleToAttrs( + updateAttr: (key: string, val: string | number) => void, + style: AllStyleOption, + el: Path | TSpan | ZRImage, + /** + * Will try not to set the attribute if it's using default value if not using forceUpdate. + * Mainly for reduce the generated size in svg-ssr mode. + */ + forceUpdate: boolean +): void { + const opacity = style.opacity == null ? 1 : style.opacity; + + // only set opacity. stroke and fill cannot be applied to svg image + if (el instanceof ZRImage) { + updateAttr('opacity', opacity); + return; + } + + if (pathHasFill(style)) { + const fill = normalizeColor(style.fill as string); + updateAttr('fill', fill.color); + const fillOpacity = style.fillOpacity != null + ? style.fillOpacity * fill.opacity * opacity + : fill.opacity * opacity; + if (forceUpdate || fillOpacity < 1) { + updateAttr('fill-opacity', fillOpacity); + } + } + else { + updateAttr('fill', NONE); + } + + if (pathHasStroke(style)) { + const stroke = normalizeColor(style.stroke as string); + updateAttr('stroke', stroke.color); + const strokeScale = style.strokeNoScale + ? (el as Path).getLineScale() + : 1; + const strokeWidth = (strokeScale ? (style.lineWidth || 0) / strokeScale : 0); + const strokeOpacity = style.strokeOpacity != null + ? style.strokeOpacity * stroke.opacity * opacity + : stroke.opacity * opacity; + const strokeFirst = style.strokeFirst; + + if (forceUpdate || strokeWidth !== 1) { + updateAttr('stroke-width', strokeWidth); + } + // stroke then fill for text; fill then stroke for others + if (forceUpdate || strokeFirst) { + updateAttr('paint-order', strokeFirst ? 'stroke' : 'fill'); + } + if (forceUpdate || strokeOpacity < 1) { + updateAttr('stroke-opacity', strokeOpacity); + } + + if (style.lineDash) { + let [lineDash, lineDashOffset] = getLineDash(el); + if (lineDash) { + lineDashOffset = mathRound(lineDashOffset || 0); + updateAttr('stroke-dasharray', lineDash.join(',')); + if (lineDashOffset || forceUpdate) { + updateAttr('stroke-dashoffset', lineDashOffset); + } + } + } + else if (forceUpdate) { + // Reset if force update. + updateAttr('stroke-dasharray', NONE); + } + + // PENDING reset + for (let i = 0; i < strokeProps.length; i++) { + const propName = strokeProps[i]; + if (forceUpdate || style[propName] !== DEFAULT_PATH_STYLE[propName]) { + const val = style[propName] || DEFAULT_PATH_STYLE[propName]; + // TODO reset + val && updateAttr(svgStrokeProps[i], val); + } + } + } + else if (forceUpdate) { + updateAttr('stroke', NONE); + } +} diff --git a/src/svg/patch.ts b/src/svg/patch.ts new file mode 100644 index 000000000..aeba565c8 --- /dev/null +++ b/src/svg/patch.ts @@ -0,0 +1,318 @@ +/** + * Virtual DOM patching + * Modified from snabbdom https://github.com/snabbdom/snabbdom/blob/master/src/init.ts + * + * The design has been simplified to focus on the purpose in SVG rendering in SVG. + * + * Licensed under the MIT License + * https://github.com/paldepind/snabbdom/blob/master/LICENSE + */ + +import { isArray, isObject } from '../core/util'; +import { createElement, createVNode, SVGVNode, XMLNS, XML_NAMESPACE, XLINKNS } from './core'; +import * as api from './domapi'; + +const colonChar = 58; +const xChar = 120; +const emptyNode = createVNode('', ''); + +type NonUndefined = T extends undefined ? never : T; + +function isUndef(s: any): boolean { + return s === undefined; +} + +function isDef(s: A): s is NonUndefined { + return s !== undefined; +} + +function createKeyToOldIdx( + children: SVGVNode[], + beginIdx: number, + endIdx: number +): KeyToIndexMap { + const map: KeyToIndexMap = {}; + for (let i = beginIdx; i <= endIdx; ++i) { + const key = children[i].key; + if (key !== undefined) { + if (process.env.NODE_ENV !== 'production') { + if (map[key] != null) { + console.error(`Duplicate key ${key}`); + } + } + map[key] = i; + } + } + return map; +} + +function sameVnode(vnode1: SVGVNode, vnode2: SVGVNode): boolean { + const isSameKey = vnode1.key === vnode2.key; + const isSameTag = vnode1.tag === vnode2.tag; + + return isSameTag && isSameKey; +} + +type KeyToIndexMap = { [key: string]: number }; + +function createElm(vnode: SVGVNode): Node { + let i: any; + const children = vnode.children; + const tag = vnode.tag; + // if (tag === '!') { + // if (isUndef(vnode.text)) { + // vnode.text = ''; + // } + // vnode.elm = api.createComment(vnode.text!); + // } + // else + if (isDef(tag)) { + const elm = (vnode.elm = createElement(tag)); + + updateAttrs(emptyNode, vnode); + + if (isArray(children)) { + for (i = 0; i < children.length; ++i) { + const ch = children[i]; + if (ch != null) { + api.appendChild(elm, createElm(ch)); + } + } + } + else if (isDef(vnode.text) && !isObject(vnode.text)) { + api.appendChild(elm, api.createTextNode(vnode.text)); + } + } + else { + vnode.elm = api.createTextNode(vnode.text!); + } + return vnode.elm; +} + +function addVnodes( + parentElm: Node, + before: Node | null, + vnodes: SVGVNode[], + startIdx: number, + endIdx: number +) { + for (; startIdx <= endIdx; ++startIdx) { + const ch = vnodes[startIdx]; + if (ch != null) { + api.insertBefore(parentElm, createElm(ch), before); + } + } +} + +function removeVnodes(parentElm: Node, vnodes: SVGVNode[], startIdx: number, endIdx: number): void { + for (; startIdx <= endIdx; ++startIdx) { + const ch = vnodes[startIdx]; + if (ch != null) { + if (isDef(ch.tag)) { + const parent = api.parentNode(ch.elm); + api.removeChild(parent, ch.elm); + } + else { + // Text node + api.removeChild(parentElm, ch.elm!); + } + } + } +} + +export function updateAttrs(oldVnode: SVGVNode, vnode: SVGVNode): void { + let key: string; + const elm = vnode.elm as Element; + const oldAttrs = oldVnode && oldVnode.attrs || {}; + const attrs = vnode.attrs || {}; + + if (oldAttrs === attrs) { + return; + } + + // update modified attributes, add new attributes + // eslint-disable-next-line + for (key in attrs) { + const cur = attrs[key]; + const old = oldAttrs[key]; + if (old !== cur) { + if (cur === true) { + elm.setAttribute(key, ''); + } + else if (cur === false) { + elm.removeAttribute(key); + } + else { + if (key.charCodeAt(0) !== xChar) { + elm.setAttribute(key, cur as any); + } + // TODO + else if (key === 'xmlns:xlink' || key === 'xmlns') { + elm.setAttributeNS(XMLNS, key, cur as any); + } + else if (key.charCodeAt(3) === colonChar) { + // Assume xml namespace + elm.setAttributeNS(XML_NAMESPACE, key, cur as any); + } + else if (key.charCodeAt(5) === colonChar) { + // Assume xlink namespace + elm.setAttributeNS(XLINKNS, key, cur as any); + } + else { + elm.setAttribute(key, cur as any); + } + } + } + } + + // remove removed attributes + // use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value) + // the other option is to remove all attributes with value == undefined + for (key in oldAttrs) { + if (!(key in attrs)) { + elm.removeAttribute(key); + } + } +} + + +function updateChildren(parentElm: Node, oldCh: SVGVNode[], newCh: SVGVNode[]) { + let oldStartIdx = 0; + let newStartIdx = 0; + let oldEndIdx = oldCh.length - 1; + let oldStartVnode = oldCh[0]; + let oldEndVnode = oldCh[oldEndIdx]; + let newEndIdx = newCh.length - 1; + let newStartVnode = newCh[0]; + let newEndVnode = newCh[newEndIdx]; + let oldKeyToIdx: KeyToIndexMap | undefined; + let idxInOld: number; + let elmToMove: SVGVNode; + let before: any; + + while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { + if (oldStartVnode == null) { + oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left + } + else if (oldEndVnode == null) { + oldEndVnode = oldCh[--oldEndIdx]; + } + else if (newStartVnode == null) { + newStartVnode = newCh[++newStartIdx]; + } + else if (newEndVnode == null) { + newEndVnode = newCh[--newEndIdx]; + } + else if (sameVnode(oldStartVnode, newStartVnode)) { + patchVnode(oldStartVnode, newStartVnode); + oldStartVnode = oldCh[++oldStartIdx]; + newStartVnode = newCh[++newStartIdx]; + } + else if (sameVnode(oldEndVnode, newEndVnode)) { + patchVnode(oldEndVnode, newEndVnode); + oldEndVnode = oldCh[--oldEndIdx]; + newEndVnode = newCh[--newEndIdx]; + } + else if (sameVnode(oldStartVnode, newEndVnode)) { + // Vnode moved right + patchVnode(oldStartVnode, newEndVnode); + api.insertBefore(parentElm, oldStartVnode.elm!, api.nextSibling(oldEndVnode.elm!)); + oldStartVnode = oldCh[++oldStartIdx]; + newEndVnode = newCh[--newEndIdx]; + } + else if (sameVnode(oldEndVnode, newStartVnode)) { + // Vnode moved left + patchVnode(oldEndVnode, newStartVnode); + api.insertBefore(parentElm, oldEndVnode.elm!, oldStartVnode.elm!); + oldEndVnode = oldCh[--oldEndIdx]; + newStartVnode = newCh[++newStartIdx]; + } + else { + if (isUndef(oldKeyToIdx)) { + oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); + } + idxInOld = oldKeyToIdx[newStartVnode.key]; + if (isUndef(idxInOld)) { + // New element + api.insertBefore(parentElm, createElm(newStartVnode), oldStartVnode.elm!); + } + else { + elmToMove = oldCh[idxInOld]; + if (elmToMove.tag !== newStartVnode.tag) { + api.insertBefore(parentElm, createElm(newStartVnode), oldStartVnode.elm!); + } + else { + patchVnode(elmToMove, newStartVnode); + oldCh[idxInOld] = undefined; + api.insertBefore(parentElm, elmToMove.elm!, oldStartVnode.elm!); + } + } + newStartVnode = newCh[++newStartIdx]; + } + } + if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) { + if (oldStartIdx > oldEndIdx) { + before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm; + addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx); + } + else { + removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx); + } + } +} + +function patchVnode(oldVnode: SVGVNode, vnode: SVGVNode) { + const elm = (vnode.elm = oldVnode.elm)!; + const oldCh = oldVnode.children; + const ch = vnode.children; + if (oldVnode === vnode) { + return; + } + + updateAttrs(oldVnode, vnode); + + if (isUndef(vnode.text)) { + if (isDef(oldCh) && isDef(ch)) { + if (oldCh !== ch) { + updateChildren(elm, oldCh, ch); + } + } + else if (isDef(ch)) { + if (isDef(oldVnode.text)) { + api.setTextContent(elm, ''); + } + addVnodes(elm, null, ch, 0, ch.length - 1); + } + else if (isDef(oldCh)) { + removeVnodes(elm, oldCh, 0, oldCh.length - 1); + } + else if (isDef(oldVnode.text)) { + api.setTextContent(elm, ''); + } + } + else if (oldVnode.text !== vnode.text) { + if (isDef(oldCh)) { + removeVnodes(elm, oldCh, 0, oldCh.length - 1); + } + api.setTextContent(elm, vnode.text!); + } +} + +export default function patch(oldVnode: SVGVNode, vnode: SVGVNode): SVGVNode { + if (sameVnode(oldVnode, vnode)) { + patchVnode(oldVnode, vnode); + } + else { + const elm = oldVnode.elm!; + const parent = api.parentNode(elm); + + createElm(vnode); + + if (parent !== null) { + api.insertBefore(parent, vnode.elm!, api.nextSibling(elm)); + removeVnodes(parent, [oldVnode], 0, 0); + } + } + + return vnode; +} diff --git a/src/tool/color.ts b/src/tool/color.ts index fb0cab500..39ca53418 100644 --- a/src/tool/color.ts +++ b/src/tool/color.ts @@ -559,9 +559,9 @@ export function lum(color: string, backgroundLum: number) { * Generate a random color */ export function random(): string { - let r = Math.round(Math.random() * 255); - let g = Math.round(Math.random() * 255); - let b = Math.round(Math.random() * 255); - - return 'rgb(' + r + ',' + g + ',' + b + ')'; + return stringify([ + Math.round(Math.random() * 255), + Math.round(Math.random() * 255), + Math.round(Math.random() * 255) + ], 'rgb'); } \ No newline at end of file diff --git a/src/tool/parseSVG.ts b/src/tool/parseSVG.ts index 7f52f19dc..cbcc2a804 100644 --- a/src/tool/parseSVG.ts +++ b/src/tool/parseSVG.ts @@ -136,8 +136,10 @@ class SVGParser { const svg = parseXML(xml); - if (!svg) { - throw new Error('Illegal svg'); + if (process.env.NODE_ENV !== 'production') { + if (!svg) { + throw new Error('Illegal svg'); + } } this._defsUsePending = []; diff --git a/src/vml/Painter.ts b/src/vml/Painter.ts deleted file mode 100644 index 2d55f5726..000000000 --- a/src/vml/Painter.ts +++ /dev/null @@ -1,200 +0,0 @@ -// @ts-nocheck -/** - * VML Painter. - */ - -import {logError, each} from '../core/util'; -import * as vmlCore from './core'; - -function parseInt10(val) { - return parseInt(val, 10); -} - -/** - * @alias module:zrender/vml/Painter - */ -function VMLPainter(root, storage) { - - vmlCore.initVML(); - - this.root = root; - - this.storage = storage; - - var vmlViewport = document.createElement('div'); - - var vmlRoot = document.createElement('div'); - - vmlViewport.style.cssText = 'display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;'; - - vmlRoot.style.cssText = 'position:absolute;left:0;top:0;'; - - root.appendChild(vmlViewport); - - this._vmlRoot = vmlRoot; - this._vmlViewport = vmlViewport; - - this.resize(); - - // Modify storage - var oldDelFromStorage = storage.delFromStorage; - var oldAddToStorage = storage.addToStorage; - storage.delFromStorage = function (el) { - oldDelFromStorage.call(storage, el); - - if (el) { - el.onRemove && el.onRemove(vmlRoot); - } - }; - - storage.addToStorage = function (el) { - // Displayable already has a vml node - el.onAdd && el.onAdd(vmlRoot); - - oldAddToStorage.call(storage, el); - }; - - this._firstPaint = true; -} - -VMLPainter.prototype = { - - constructor: VMLPainter, - - getType: function () { - return 'vml'; - }, - - /** - * @return {HTMLDivElement} - */ - getViewportRoot: function () { - return this._vmlViewport; - }, - - getViewportRootOffset: function () { - var viewportRoot = this.getViewportRoot(); - if (viewportRoot) { - return { - offsetLeft: viewportRoot.offsetLeft || 0, - offsetTop: viewportRoot.offsetTop || 0 - }; - } - }, - - /** - * 刷新 - */ - refresh: function () { - - var list = this.storage.getDisplayList(true, true); - - this._paintList(list); - }, - - _paintList: function (list) { - var vmlRoot = this._vmlRoot; - for (var i = 0; i < list.length; i++) { - var el = list[i]; - if (el.invisible || el.ignore) { - if (!el.__alreadyNotVisible) { - el.onRemove(vmlRoot); - } - // Set as already invisible - el.__alreadyNotVisible = true; - } - else { - if (el.__alreadyNotVisible) { - el.onAdd(vmlRoot); - } - el.__alreadyNotVisible = false; - if (el.__dirty) { - el.beforeBrush && el.beforeBrush(); - (el.brushVML || el.brush).call(el, vmlRoot); - el.afterBrush && el.afterBrush(); - } - } - el.__dirty = false; - } - - if (this._firstPaint) { - // Detached from document at first time - // to avoid page refreshing too many times - - // FIXME 如果每次都先 removeChild 可能会导致一些填充和描边的效果改变 - this._vmlViewport.appendChild(vmlRoot); - this._firstPaint = false; - } - }, - - resize: function (width, height) { - var width = width == null ? this._getWidth() : width; - var height = height == null ? this._getHeight() : height; - - if (this._width !== width || this._height !== height) { - this._width = width; - this._height = height; - - var vmlViewportStyle = this._vmlViewport.style; - vmlViewportStyle.width = width + 'px'; - vmlViewportStyle.height = height + 'px'; - } - }, - - dispose: function () { - this.root.innerHTML = ''; - - this._vmlRoot = - this._vmlViewport = - this.storage = null; - }, - - getWidth: function () { - return this._width; - }, - - getHeight: function () { - return this._height; - }, - - clear: function () { - if (this._vmlViewport) { - this.root.removeChild(this._vmlViewport); - } - }, - - _getWidth: function () { - var root = this.root; - var stl = root.currentStyle; - - return ((root.clientWidth || parseInt10(stl.width)) - - parseInt10(stl.paddingLeft) - - parseInt10(stl.paddingRight)) | 0; - }, - - _getHeight: function () { - var root = this.root; - var stl = root.currentStyle; - - return ((root.clientHeight || parseInt10(stl.height)) - - parseInt10(stl.paddingTop) - - parseInt10(stl.paddingBottom)) | 0; - } -}; - -// Not supported methods -function createMethodNotSupport(method) { - return function () { - logError('In IE8.0 VML mode painter not support method "' + method + '"'); - }; -} - -// Unsupported methods -each([ - 'getLayer', 'insertLayer', 'eachLayer', 'eachBuiltinLayer', 'eachOtherLayer', 'getLayers', - 'modLayer', 'delLayer', 'clearLayer', 'toDataURL', 'pathToImage' -], function (name) { - VMLPainter.prototype[name] = createMethodNotSupport(name); -}); - -export default VMLPainter; \ No newline at end of file diff --git a/src/vml/core.ts b/src/vml/core.ts deleted file mode 100644 index fe84edae6..000000000 --- a/src/vml/core.ts +++ /dev/null @@ -1,48 +0,0 @@ -// @ts-nocheck -import env from '../core/env'; - - -var urn = 'urn:schemas-microsoft-com:vml'; -var win = typeof window === 'undefined' ? null : window; - -var vmlInited = false; - -export var doc = win && win.document; - -export function createNode(tagName) { - return doCreateNode(tagName); -} - -// Avoid assign to an exported variable, for transforming to cjs. -var doCreateNode; - -if (doc && !env.canvasSupported) { - try { - !doc.namespaces.zrvml && doc.namespaces.add('zrvml', urn); - doCreateNode = function (tagName) { - return doc.createElement(''); - }; - } - catch (e) { - doCreateNode = function (tagName) { - return doc.createElement('<' + tagName + ' xmlns="' + urn + '" class="zrvml">'); - }; - } -} - -// From raphael -export function initVML() { - if (vmlInited || !doc) { - return; - } - vmlInited = true; - - var styleSheets = doc.styleSheets; - if (styleSheets.length < 31) { - doc.createStyleSheet().addRule('.zrvml', 'behavior:url(#default#VML)'); - } - else { - // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx - styleSheets[0].addRule('.zrvml', 'behavior:url(#default#VML)'); - } -} diff --git a/src/vml/graphic.ts b/src/vml/graphic.ts deleted file mode 100644 index b81ea6e07..000000000 --- a/src/vml/graphic.ts +++ /dev/null @@ -1,1061 +0,0 @@ -// http://www.w3.org/TR/NOTE-VML -// TODO Use proxy like svg instead of overwrite brush methods -// @ts-nocheck - -import env from '../core/env'; -import {applyTransform} from '../core/vector'; -import BoundingRect from '../core/BoundingRect'; -import * as colorTool from '../tool/color'; -import * as textContain from '../graphic/text/parse'; -import Displayable from '../graphic/Displayable'; -import ZRImage from '../graphic/Image'; -import Text from '../graphic/TSpan'; -import Path from '../graphic/Path'; -import PathProxy from '../core/PathProxy'; -import Gradient from '../graphic/Gradient'; -import * as vmlCore from './core'; - -var CMD = PathProxy.CMD; -var round = Math.round; -var sqrt = Math.sqrt; -var abs = Math.abs; -var cos = Math.cos; -var sin = Math.sin; -var mathMax = Math.max; - -if (!env.canvasSupported) { - - var comma = ','; - var imageTransformPrefix = 'progid:DXImageTransform.Microsoft'; - - var Z = 21600; - var Z2 = Z / 2; - - var ZLEVEL_BASE = 100000; - var Z_BASE = 1000; - - var initRootElStyle = function (el) { - el.style.cssText = 'position:absolute;left:0;top:0;width:1px;height:1px;'; - el.coordsize = Z + ',' + Z; - el.coordorigin = '0,0'; - }; - - var encodeHtmlAttribute = function (s) { - return String(s).replace(/&/g, '&').replace(/"/g, '"'); - }; - - var rgb2Str = function (r, g, b) { - return 'rgb(' + [r, g, b].join(',') + ')'; - }; - - var append = function (parent, child) { - if (child && parent && child.parentNode !== parent) { - parent.appendChild(child); - } - }; - - var remove = function (parent, child) { - if (child && parent && child.parentNode === parent) { - parent.removeChild(child); - } - }; - - var getZIndex = function (zlevel, z, z2) { - // z 的取值范围为 [0, 1000] - return (parseFloat(zlevel) || 0) * ZLEVEL_BASE + (parseFloat(z) || 0) * Z_BASE + z2; - }; - - var parsePercent = textHelper.parsePercent; - - /*************************************************** - * PATH - **************************************************/ - - var setColorAndOpacity = function (el, color, opacity) { - var colorArr = colorTool.parse(color); - opacity = +opacity; - if (isNaN(opacity)) { - opacity = 1; - } - if (colorArr) { - el.color = rgb2Str(colorArr[0], colorArr[1], colorArr[2]); - el.opacity = opacity * colorArr[3]; - } - }; - - var getColorAndAlpha = function (color) { - var colorArr = colorTool.parse(color); - return [ - rgb2Str(colorArr[0], colorArr[1], colorArr[2]), - colorArr[3] - ]; - }; - - var updateFillNode = function (el, style, zrEl) { - // TODO pattern - var fill = style.fill; - if (fill != null) { - // Modified from excanvas - if (fill instanceof Gradient) { - var gradientType; - var angle = 0; - var focus = [0, 0]; - // additional offset - var shift = 0; - // scale factor for offset - var expansion = 1; - var rect = zrEl.getBoundingRect(); - var rectWidth = rect.width; - var rectHeight = rect.height; - if (fill.type === 'linear') { - gradientType = 'gradient'; - var transform = zrEl.transform; - var p0 = [fill.x * rectWidth, fill.y * rectHeight]; - var p1 = [fill.x2 * rectWidth, fill.y2 * rectHeight]; - if (transform) { - applyTransform(p0, p0, transform); - applyTransform(p1, p1, transform); - } - var dx = p1[0] - p0[0]; - var dy = p1[1] - p0[1]; - angle = Math.atan2(dx, dy) * 180 / Math.PI; - // The angle should be a non-negative number. - if (angle < 0) { - angle += 360; - } - - // Very small angles produce an unexpected result because they are - // converted to a scientific notation string. - if (angle < 1e-6) { - angle = 0; - } - } - else { - gradientType = 'gradientradial'; - var p0 = [fill.x * rectWidth, fill.y * rectHeight]; - var transform = zrEl.transform; - var scale = zrEl.scale; - var width = rectWidth; - var height = rectHeight; - focus = [ - // Percent in bounding rect - (p0[0] - rect.x) / width, - (p0[1] - rect.y) / height - ]; - if (transform) { - applyTransform(p0, p0, transform); - } - - width /= scale[0] * Z; - height /= scale[1] * Z; - var dimension = mathMax(width, height); - shift = 2 * 0 / dimension; - expansion = 2 * fill.r / dimension - shift; - } - - // We need to sort the color stops in ascending order by offset, - // otherwise IE won't interpret it correctly. - var stops = fill.colorStops.slice(); - stops.sort(function (cs1, cs2) { - return cs1.offset - cs2.offset; - }); - - var length = stops.length; - // Color and alpha list of first and last stop - var colorAndAlphaList = []; - var colors = []; - for (var i = 0; i < length; i++) { - var stop = stops[i]; - var colorAndAlpha = getColorAndAlpha(stop.color); - colors.push(stop.offset * expansion + shift + ' ' + colorAndAlpha[0]); - if (i === 0 || i === length - 1) { - colorAndAlphaList.push(colorAndAlpha); - } - } - - if (length >= 2) { - var color1 = colorAndAlphaList[0][0]; - var color2 = colorAndAlphaList[1][0]; - var opacity1 = colorAndAlphaList[0][1] * style.opacity; - var opacity2 = colorAndAlphaList[1][1] * style.opacity; - - el.type = gradientType; - el.method = 'none'; - el.focus = '100%'; - el.angle = angle; - el.color = color1; - el.color2 = color2; - el.colors = colors.join(','); - // When colors attribute is used, the meanings of opacity and o:opacity2 - // are reversed. - el.opacity = opacity2; - // FIXME g_o_:opacity ? - el.opacity2 = opacity1; - } - if (gradientType === 'radial') { - el.focusposition = focus.join(','); - } - } - else { - // FIXME Change from Gradient fill to color fill - setColorAndOpacity(el, fill, style.opacity); - } - } - }; - - var updateStrokeNode = function (el, style) { - // if (style.lineJoin != null) { - // el.joinstyle = style.lineJoin; - // } - // if (style.miterLimit != null) { - // el.miterlimit = style.miterLimit * Z; - // } - // if (style.lineCap != null) { - // el.endcap = style.lineCap; - // } - if (style.lineDash) { - el.dashstyle = style.lineDash.join(' '); - } - if (style.stroke != null && !(style.stroke instanceof Gradient)) { - setColorAndOpacity(el, style.stroke, style.opacity); - } - }; - - var updateFillAndStroke = function (vmlEl, type, style, zrEl) { - var isFill = type === 'fill'; - var el = vmlEl.getElementsByTagName(type)[0]; - // Stroke must have lineWidth - if (style[type] != null && style[type] !== 'none' && (isFill || (!isFill && style.lineWidth))) { - vmlEl[isFill ? 'filled' : 'stroked'] = 'true'; - // FIXME Remove before updating, or set `colors` will throw error - if (style[type] instanceof Gradient) { - remove(vmlEl, el); - } - if (!el) { - el = vmlCore.createNode(type); - } - - isFill ? updateFillNode(el, style, zrEl) : updateStrokeNode(el, style); - append(vmlEl, el); - } - else { - vmlEl[isFill ? 'filled' : 'stroked'] = 'false'; - remove(vmlEl, el); - } - }; - - var points = [[], [], []]; - var pathDataToString = function (path, m) { - var M = CMD.M; - var C = CMD.C; - var L = CMD.L; - var A = CMD.A; - var Q = CMD.Q; - - var str = []; - var nPoint; - var cmdStr; - var cmd; - var i; - var xi; - var yi; - var data = path.data; - var dataLength = path.len(); - for (i = 0; i < dataLength;) { - cmd = data[i++]; - cmdStr = ''; - nPoint = 0; - switch (cmd) { - case M: - cmdStr = ' m '; - nPoint = 1; - xi = data[i++]; - yi = data[i++]; - points[0][0] = xi; - points[0][1] = yi; - break; - case L: - cmdStr = ' l '; - nPoint = 1; - xi = data[i++]; - yi = data[i++]; - points[0][0] = xi; - points[0][1] = yi; - break; - case Q: - case C: - cmdStr = ' c '; - nPoint = 3; - var x1 = data[i++]; - var y1 = data[i++]; - var x2 = data[i++]; - var y2 = data[i++]; - var x3; - var y3; - if (cmd === Q) { - // Convert quadratic to cubic using degree elevation - x3 = x2; - y3 = y2; - x2 = (x2 + 2 * x1) / 3; - y2 = (y2 + 2 * y1) / 3; - x1 = (xi + 2 * x1) / 3; - y1 = (yi + 2 * y1) / 3; - } - else { - x3 = data[i++]; - y3 = data[i++]; - } - points[0][0] = x1; - points[0][1] = y1; - points[1][0] = x2; - points[1][1] = y2; - points[2][0] = x3; - points[2][1] = y3; - - xi = x3; - yi = y3; - break; - case A: - var x = 0; - var y = 0; - var sx = 1; - var sy = 1; - var angle = 0; - if (m) { - // Extract SRT from matrix - x = m[4]; - y = m[5]; - sx = sqrt(m[0] * m[0] + m[1] * m[1]); - sy = sqrt(m[2] * m[2] + m[3] * m[3]); - angle = Math.atan2(-m[1] / sy, m[0] / sx); - } - - var cx = data[i++]; - var cy = data[i++]; - var rx = data[i++]; - var ry = data[i++]; - var startAngle = data[i++] + angle; - var endAngle = data[i++] + startAngle + angle; - // FIXME - // var psi = data[i++]; - i++; - var clockwise = data[i++]; - - var x0 = cx + cos(startAngle) * rx; - var y0 = cy + sin(startAngle) * ry; - - var x1 = cx + cos(endAngle) * rx; - var y1 = cy + sin(endAngle) * ry; - - var type = clockwise ? ' wa ' : ' at '; - if (Math.abs(x0 - x1) < 1e-4) { - // IE won't render arches drawn counter clockwise if x0 == x1. - if (Math.abs(endAngle - startAngle) > 1e-2) { - // Offset x0 by 1/80 of a pixel. Use something - // that can be represented in binary - if (clockwise) { - x0 += 270 / Z; - } - } - else { - // Avoid case draw full circle - if (Math.abs(y0 - cy) < 1e-4) { - if ((clockwise && x0 < cx) || (!clockwise && x0 > cx)) { - y1 -= 270 / Z; - } - else { - y1 += 270 / Z; - } - } - else if ((clockwise && y0 < cy) || (!clockwise && y0 > cy)) { - x1 += 270 / Z; - } - else { - x1 -= 270 / Z; - } - } - } - str.push( - type, - round(((cx - rx) * sx + x) * Z - Z2), comma, - round(((cy - ry) * sy + y) * Z - Z2), comma, - round(((cx + rx) * sx + x) * Z - Z2), comma, - round(((cy + ry) * sy + y) * Z - Z2), comma, - round((x0 * sx + x) * Z - Z2), comma, - round((y0 * sy + y) * Z - Z2), comma, - round((x1 * sx + x) * Z - Z2), comma, - round((y1 * sy + y) * Z - Z2) - ); - - xi = x1; - yi = y1; - break; - case CMD.R: - var p0 = points[0]; - var p1 = points[1]; - // x0, y0 - p0[0] = data[i++]; - p0[1] = data[i++]; - // x1, y1 - p1[0] = p0[0] + data[i++]; - p1[1] = p0[1] + data[i++]; - - if (m) { - applyTransform(p0, p0, m); - applyTransform(p1, p1, m); - } - - p0[0] = round(p0[0] * Z - Z2); - p1[0] = round(p1[0] * Z - Z2); - p0[1] = round(p0[1] * Z - Z2); - p1[1] = round(p1[1] * Z - Z2); - str.push( - // x0, y0 - ' m ', p0[0], comma, p0[1], - // x1, y0 - ' l ', p1[0], comma, p0[1], - // x1, y1 - ' l ', p1[0], comma, p1[1], - // x0, y1 - ' l ', p0[0], comma, p1[1] - ); - break; - case CMD.Z: - // FIXME Update xi, yi - str.push(' x '); - } - - if (nPoint > 0) { - str.push(cmdStr); - for (var k = 0; k < nPoint; k++) { - var p = points[k]; - - m && applyTransform(p, p, m); - // 不 round 会非常慢 - str.push( - round(p[0] * Z - Z2), comma, round(p[1] * Z - Z2), - k < nPoint - 1 ? comma : '' - ); - } - } - } - - return str.join(''); - }; - - // Rewrite the original path method - Path.prototype.brushVML = function (vmlRoot) { - var style = this.style; - - var vmlEl = this._vmlEl; - if (!vmlEl) { - vmlEl = vmlCore.createNode('shape'); - initRootElStyle(vmlEl); - - this._vmlEl = vmlEl; - } - - updateFillAndStroke(vmlEl, 'fill', style, this); - updateFillAndStroke(vmlEl, 'stroke', style, this); - - var m = this.transform; - var needTransform = m != null; - var strokeEl = vmlEl.getElementsByTagName('stroke')[0]; - if (strokeEl) { - var lineWidth = style.lineWidth; - // Get the line scale. - // Determinant of this.m_ means how much the area is enlarged by the - // transformation. So its square root can be used as a scale factor - // for width. - if (needTransform && !style.strokeNoScale) { - var det = m[0] * m[3] - m[1] * m[2]; - lineWidth *= sqrt(abs(det)); - } - strokeEl.weight = lineWidth + 'px'; - } - - var path = this.path || (this.path = new PathProxy()); - if (this.__dirtyPath) { - path.beginPath(); - path.subPixelOptimize = false; - this.buildPath(path, this.shape); - path.toStatic(); - this.__dirtyPath = false; - } - - vmlEl.path = pathDataToString(path, this.transform); - - vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); - - // Append to root - append(vmlRoot, vmlEl); - - // Text - if (style.text != null) { - this.drawRectText(vmlRoot, this.getBoundingRect()); - } - else { - this.removeRectText(vmlRoot); - } - }; - - Path.prototype.onRemove = function (vmlRoot) { - remove(vmlRoot, this._vmlEl); - this.removeRectText(vmlRoot); - }; - - Path.prototype.onAdd = function (vmlRoot) { - append(vmlRoot, this._vmlEl); - this.appendRectText(vmlRoot); - }; - - /*************************************************** - * IMAGE - **************************************************/ - var isImage = function (img) { - // FIXME img instanceof Image 如果 img 是一个字符串的时候,IE8 下会报错 - return (typeof img === 'object') && img.tagName && img.tagName.toUpperCase() === 'IMG'; - // return img instanceof Image; - }; - - // Rewrite the original path method - ZRImage.prototype.brushVML = function (vmlRoot) { - var style = this.style; - var image = style.image; - - // Image original width, height - var ow; - var oh; - - if (isImage(image)) { - var src = image.src; - if (src === this._imageSrc) { - ow = this._imageWidth; - oh = this._imageHeight; - } - else { - var imageRuntimeStyle = image.runtimeStyle; - var oldRuntimeWidth = imageRuntimeStyle.width; - var oldRuntimeHeight = imageRuntimeStyle.height; - imageRuntimeStyle.width = 'auto'; - imageRuntimeStyle.height = 'auto'; - - // get the original size - ow = image.width; - oh = image.height; - - // and remove overides - imageRuntimeStyle.width = oldRuntimeWidth; - imageRuntimeStyle.height = oldRuntimeHeight; - - // Caching image original width, height and src - this._imageSrc = src; - this._imageWidth = ow; - this._imageHeight = oh; - } - image = src; - } - else { - if (image === this._imageSrc) { - ow = this._imageWidth; - oh = this._imageHeight; - } - } - if (!image) { - return; - } - - var x = style.x || 0; - var y = style.y || 0; - - var dw = style.width; - var dh = style.height; - - var sw = style.sWidth; - var sh = style.sHeight; - var sx = style.sx || 0; - var sy = style.sy || 0; - - var hasCrop = sw && sh; - - var vmlEl = this._vmlEl; - if (!vmlEl) { - // FIXME 使用 group 在 left, top 都不是 0 的时候就无法显示了。 - // vmlEl = vmlCore.createNode('group'); - vmlEl = vmlCore.doc.createElement('div'); - initRootElStyle(vmlEl); - - this._vmlEl = vmlEl; - } - - var vmlElStyle = vmlEl.style; - var hasRotation = false; - var m; - var scaleX = 1; - var scaleY = 1; - if (this.transform) { - m = this.transform; - scaleX = sqrt(m[0] * m[0] + m[1] * m[1]); - scaleY = sqrt(m[2] * m[2] + m[3] * m[3]); - - hasRotation = m[1] || m[2]; - } - if (hasRotation) { - // If filters are necessary (rotation exists), create them - // filters are bog-slow, so only create them if abbsolutely necessary - // The following check doesn't account for skews (which don't exist - // in the canvas spec (yet) anyway. - // From excanvas - var p0 = [x, y]; - var p1 = [x + dw, y]; - var p2 = [x, y + dh]; - var p3 = [x + dw, y + dh]; - applyTransform(p0, p0, m); - applyTransform(p1, p1, m); - applyTransform(p2, p2, m); - applyTransform(p3, p3, m); - - var maxX = mathMax(p0[0], p1[0], p2[0], p3[0]); - var maxY = mathMax(p0[1], p1[1], p2[1], p3[1]); - - var transformFilter = []; - transformFilter.push('M11=', m[0] / scaleX, comma, - 'M12=', m[2] / scaleY, comma, - 'M21=', m[1] / scaleX, comma, - 'M22=', m[3] / scaleY, comma, - 'Dx=', round(x * scaleX + m[4]), comma, - 'Dy=', round(y * scaleY + m[5])); - - vmlElStyle.padding = '0 ' + round(maxX) + 'px ' + round(maxY) + 'px 0'; - // FIXME DXImageTransform 在 IE11 的兼容模式下不起作用 - vmlElStyle.filter = imageTransformPrefix + '.Matrix(' - + transformFilter.join('') + ', SizingMethod=clip)'; - - } - else { - if (m) { - x = x * scaleX + m[4]; - y = y * scaleY + m[5]; - } - vmlElStyle.filter = ''; - vmlElStyle.left = round(x) + 'px'; - vmlElStyle.top = round(y) + 'px'; - } - - var imageEl = this._imageEl; - var cropEl = this._cropEl; - - if (!imageEl) { - imageEl = vmlCore.doc.createElement('div'); - this._imageEl = imageEl; - } - var imageELStyle = imageEl.style; - if (hasCrop) { - // Needs know image original width and height - if (!(ow && oh)) { - var tmpImage = new Image(); - var self = this; - tmpImage.onload = function () { - tmpImage.onload = null; - ow = tmpImage.width; - oh = tmpImage.height; - // Adjust image width and height to fit the ratio destinationSize / sourceSize - imageELStyle.width = round(scaleX * ow * dw / sw) + 'px'; - imageELStyle.height = round(scaleY * oh * dh / sh) + 'px'; - - // Caching image original width, height and src - self._imageWidth = ow; - self._imageHeight = oh; - self._imageSrc = image; - }; - tmpImage.src = image; - } - else { - imageELStyle.width = round(scaleX * ow * dw / sw) + 'px'; - imageELStyle.height = round(scaleY * oh * dh / sh) + 'px'; - } - - if (!cropEl) { - cropEl = vmlCore.doc.createElement('div'); - cropEl.style.overflow = 'hidden'; - this._cropEl = cropEl; - } - var cropElStyle = cropEl.style; - cropElStyle.width = round((dw + sx * dw / sw) * scaleX); - cropElStyle.height = round((dh + sy * dh / sh) * scaleY); - cropElStyle.filter = imageTransformPrefix + '.Matrix(Dx=' - + (-sx * dw / sw * scaleX) + ',Dy=' + (-sy * dh / sh * scaleY) + ')'; - - if (!cropEl.parentNode) { - vmlEl.appendChild(cropEl); - } - if (imageEl.parentNode !== cropEl) { - cropEl.appendChild(imageEl); - } - } - else { - imageELStyle.width = round(scaleX * dw) + 'px'; - imageELStyle.height = round(scaleY * dh) + 'px'; - - vmlEl.appendChild(imageEl); - - if (cropEl && cropEl.parentNode) { - vmlEl.removeChild(cropEl); - this._cropEl = null; - } - } - - var filterStr = ''; - var alpha = style.opacity; - if (alpha < 1) { - filterStr += '.Alpha(opacity=' + round(alpha * 100) + ') '; - } - filterStr += imageTransformPrefix + '.AlphaImageLoader(src=' + image + ', SizingMethod=scale)'; - - imageELStyle.filter = filterStr; - - vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); - - // Append to root - append(vmlRoot, vmlEl); - - // Text - if (style.text != null) { - this.drawRectText(vmlRoot, this.getBoundingRect()); - } - }; - - ZRImage.prototype.onRemove = function (vmlRoot) { - remove(vmlRoot, this._vmlEl); - - this._vmlEl = null; - this._cropEl = null; - this._imageEl = null; - - this.removeRectText(vmlRoot); - }; - - ZRImage.prototype.onAdd = function (vmlRoot) { - append(vmlRoot, this._vmlEl); - this.appendRectText(vmlRoot); - }; - - - /*************************************************** - * TEXT - **************************************************/ - - var DEFAULT_STYLE_NORMAL = 'normal'; - - var fontStyleCache = {}; - var fontStyleCacheCount = 0; - var MAX_FONT_CACHE_SIZE = 100; - var fontEl = document.createElement('div'); - - var getFontStyle = function (fontString) { - var fontStyle = fontStyleCache[fontString]; - if (!fontStyle) { - // Clear cache - if (fontStyleCacheCount > MAX_FONT_CACHE_SIZE) { - fontStyleCacheCount = 0; - fontStyleCache = {}; - } - - var style = fontEl.style; - var fontFamily; - try { - style.font = fontString; - fontFamily = style.fontFamily.split(',')[0]; - } - catch (e) { - } - - fontStyle = { - style: style.fontStyle || DEFAULT_STYLE_NORMAL, - variant: style.fontVariant || DEFAULT_STYLE_NORMAL, - weight: style.fontWeight || DEFAULT_STYLE_NORMAL, - size: parseFloat(style.fontSize || 12) | 0, - family: fontFamily || 'Microsoft YaHei' - }; - - fontStyleCache[fontString] = fontStyle; - fontStyleCacheCount++; - } - return fontStyle; - }; - - var textMeasureEl; - // Overwrite measure text method - textContain.$override('measureText', function (text, textFont) { - var doc = vmlCore.doc; - if (!textMeasureEl) { - textMeasureEl = doc.createElement('div'); - textMeasureEl.style.cssText = 'position:absolute;top:-20000px;left:0;' - + 'padding:0;margin:0;border:none;white-space:pre;'; - vmlCore.doc.body.appendChild(textMeasureEl); - } - - try { - textMeasureEl.style.font = textFont; - } - catch (ex) { - // Ignore failures to set to invalid font. - } - textMeasureEl.innerHTML = ''; - // Don't use innerHTML or innerText because they allow markup/whitespace. - textMeasureEl.appendChild(doc.createTextNode(text)); - return { - width: textMeasureEl.offsetWidth - }; - }); - - var tmpRect = new BoundingRect(0, 0, 0, 0); - - var drawRectText = function (vmlRoot, rect, textRect, fromTextEl) { - - var style = this.style; - - // Optimize, avoid normalize every time. - this.__dirty && textHelper.normalizeTextStyle(style, true); - - var text = style.text; - // Convert to string - text != null && (text += ''); - if (!text) { - return; - } - - // Convert rich text to plain text. Rich text is not supported in - // IE8-, but tags in rich text template will be removed. - if (style.rich) { - var contentBlock = textContain.parseRichText(text, style); - text = []; - for (var i = 0; i < contentBlock.lines.length; i++) { - var tokens = contentBlock.lines[i].tokens; - var textLine = []; - for (var j = 0; j < tokens.length; j++) { - textLine.push(tokens[j].text); - } - text.push(textLine.join('')); - } - text = text.join('\n'); - } - - var x; - var y; - var align = style.textAlign; - var verticalAlign = style.textVerticalAlign; - - var fontStyle = getFontStyle(style.font); - // FIXME encodeHtmlAttribute ? - var font = fontStyle.style + ' ' + fontStyle.variant + ' ' + fontStyle.weight + ' ' - + fontStyle.size + 'px "' + fontStyle.family + '"'; - - textRect = textRect || textContain.getBoundingRect( - text, font, align, verticalAlign, style.textPadding, style.textLineHeight - ); - - // Transform rect to view space - var m = this.transform; - // Ignore transform for text in other element - if (m && !fromTextEl) { - tmpRect.copy(rect); - tmpRect.applyTransform(m); - rect = tmpRect; - } - - if (!fromTextEl) { - var textPosition = style.textPosition; - // Text position represented by coord - if (textPosition instanceof Array) { - x = rect.x + parsePercent(textPosition[0], rect.width); - y = rect.y + parsePercent(textPosition[1], rect.height); - - align = align || 'left'; - } - else { - var res = this.calculateTextPosition - ? this.calculateTextPosition({}, style, rect) - : textContain.calculateTextPosition({}, style, rect); - x = res.x; - y = res.y; - - // Default align and baseline when has textPosition - align = align || res.align; - verticalAlign = verticalAlign || res.verticalAlign; - } - } - else { - x = rect.x; - y = rect.y; - } - - x = textContain.adjustTextX(x, textRect.width, align); - y = textContain.adjustTextY(y, textRect.height, verticalAlign); - - // Force baseline 'middle' - y += textRect.height / 2; - - // var fontSize = fontStyle.size; - // 1.75 is an arbitrary number, as there is no info about the text baseline - // switch (baseline) { - // case 'hanging': - // case 'top': - // y += fontSize / 1.75; - // break; - // case 'middle': - // break; - // default: - // // case null: - // // case 'alphabetic': - // // case 'ideographic': - // // case 'bottom': - // y -= fontSize / 2.25; - // break; - // } - - // switch (align) { - // case 'left': - // break; - // case 'center': - // x -= textRect.width / 2; - // break; - // case 'right': - // x -= textRect.width; - // break; - // case 'end': - // align = elementStyle.direction == 'ltr' ? 'right' : 'left'; - // break; - // case 'start': - // align = elementStyle.direction == 'rtl' ? 'right' : 'left'; - // break; - // default: - // align = 'left'; - // } - - var createNode = vmlCore.createNode; - - var textVmlEl = this._textVmlEl; - var pathEl; - var textPathEl; - var skewEl; - if (!textVmlEl) { - textVmlEl = createNode('line'); - pathEl = createNode('path'); - textPathEl = createNode('textpath'); - skewEl = createNode('skew'); - - // FIXME Why here is not cammel case - // Align 'center' seems wrong - textPathEl.style['v-text-align'] = 'left'; - - initRootElStyle(textVmlEl); - - pathEl.textpathok = true; - textPathEl.on = true; - - textVmlEl.from = '0 0'; - textVmlEl.to = '1000 0.05'; - - append(textVmlEl, skewEl); - append(textVmlEl, pathEl); - append(textVmlEl, textPathEl); - - this._textVmlEl = textVmlEl; - } - else { - // 这里是在前面 appendChild 保证顺序的前提下 - skewEl = textVmlEl.firstChild; - pathEl = skewEl.nextSibling; - textPathEl = pathEl.nextSibling; - } - - var coords = [x, y]; - var textVmlElStyle = textVmlEl.style; - // Ignore transform for text in other element - if (m && fromTextEl) { - applyTransform(coords, coords, m); - - skewEl.on = true; - - skewEl.matrix = m[0].toFixed(3) + comma + m[2].toFixed(3) + comma - + m[1].toFixed(3) + comma + m[3].toFixed(3) + ',0,0'; - - // Text position - skewEl.offset = (round(coords[0]) || 0) + ',' + (round(coords[1]) || 0); - // Left top point as origin - skewEl.origin = '0 0'; - - textVmlElStyle.left = '0px'; - textVmlElStyle.top = '0px'; - } - else { - skewEl.on = false; - textVmlElStyle.left = round(x) + 'px'; - textVmlElStyle.top = round(y) + 'px'; - } - - textPathEl.string = encodeHtmlAttribute(text); - // TODO - try { - textPathEl.style.font = font; - } - // Error font format - catch (e) {} - - updateFillAndStroke(textVmlEl, 'fill', { - fill: style.textFill, - opacity: style.opacity - }, this); - updateFillAndStroke(textVmlEl, 'stroke', { - stroke: style.textStroke, - opacity: style.opacity, - lineDash: style.lineDash || null // style.lineDash can be `false`. - }, this); - - textVmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); - - // Attached to root - append(vmlRoot, textVmlEl); - }; - - var removeRectText = function (vmlRoot) { - remove(vmlRoot, this._textVmlEl); - this._textVmlEl = null; - }; - - var appendRectText = function (vmlRoot) { - append(vmlRoot, this._textVmlEl); - }; - - var list = [RectText, Displayable, ZRImage, Path, Text]; - - // In case Displayable has been mixed in RectText - for (var i = 0; i < list.length; i++) { - var proto = list[i].prototype; - proto.drawRectText = drawRectText; - proto.removeRectText = removeRectText; - proto.appendRectText = appendRectText; - } - - Text.prototype.brushVML = function (vmlRoot) { - var style = this.style; - if (style.text != null) { - this.drawRectText(vmlRoot, { - x: style.x || 0, y: style.y || 0, - width: 0, height: 0 - }, this.getBoundingRect(), true); - } - else { - this.removeRectText(vmlRoot); - } - }; - - Text.prototype.onRemove = function (vmlRoot) { - this.removeRectText(vmlRoot); - }; - - Text.prototype.onAdd = function (vmlRoot) { - this.appendRectText(vmlRoot); - }; -} \ No newline at end of file diff --git a/src/zrender.ts b/src/zrender.ts index af82a7823..0bfb47685 100644 --- a/src/zrender.ts +++ b/src/zrender.ts @@ -13,7 +13,7 @@ import * as zrUtil from './core/util'; import Handler from './Handler'; import Storage from './Storage'; import {PainterBase} from './PainterBase'; -import Animation from './animation/Animation'; +import Animation, {getTime} from './animation/Animation'; import HandlerProxy from './dom/HandlerProxy'; import Element, { ElementEventCallback } from './Element'; import { Dictionary, ElementEventName, RenderedEvent, WithThisType } from './core/types'; @@ -21,17 +21,12 @@ import { LayerConfig } from './canvas/Layer'; import { GradientObject } from './graphic/Gradient'; import { PatternObject } from './graphic/Pattern'; import { EventCallback } from './core/Eventful'; -import TSpan from './graphic/TSpan'; -import ZRImage from './graphic/Image'; import Displayable from './graphic/Displayable'; import { lum } from './tool/color'; import { DARK_MODE_THRESHOLD } from './config'; -import Path from './graphic/Path'; import Group from './graphic/Group'; -const useVML = !env.canvasSupported; - type PainterBaseCtor = { new(dom: HTMLElement, storage: Storage, ...args: any[]): PainterBase } @@ -68,8 +63,10 @@ function isDarkMode(backgroundColor: string | GradientObject | PatternObject): b } class ZRender { - - dom: HTMLElement + /** + * Not necessary if using SSR painter like svg-ssr + */ + dom?: HTMLElement id: number @@ -92,7 +89,7 @@ class ZRender { private _backgroundColor: string | GradientObject | PatternObject; - constructor(id: number, dom: HTMLElement, opts?: ZRenderInitOpt) { + constructor(id: number, dom?: HTMLElement, opts?: ZRenderInitOpt) { opts = opts || {}; /** @@ -106,17 +103,14 @@ class ZRender { let rendererType = opts.renderer || 'canvas'; - // TODO WebGL - if (useVML) { - throw new Error('IE8 support has been dropped since 5.0'); - } - if (!painterCtors[rendererType]) { // Use the first registered renderer. rendererType = zrUtil.keys(painterCtors)[0]; } - if (!painterCtors[rendererType]) { - throw new Error(`Renderer '${rendererType}' is not imported. Please import it first.`); + if (process.env.NODE_ENV !== 'production') { + if (!painterCtors[rendererType]) { + throw new Error(`Renderer '${rendererType}' is not imported. Please import it first.`); + } } opts.useDirtyRect = opts.useDirtyRect == null @@ -124,21 +118,25 @@ class ZRender { : opts.useDirtyRect; const painter = new painterCtors[rendererType](dom, storage, opts, id); + const ssrMode = opts.ssr || painter.ssrOnly; this.storage = storage; this.painter = painter; - const handerProxy = (!env.node && !env.worker) + const handerProxy = (!env.node && !env.worker && !ssrMode) ? new HandlerProxy(painter.getViewportRoot(), painter.root) : null; this.handler = new Handler(storage, painter, handerProxy, painter.root); this.animation = new Animation({ stage: { - update: () => this._flush(true) + update: ssrMode ? null : () => this._flush(true) } }); - this.animation.start(); + + if (!ssrMode) { + this.animation.start(); + } } /** @@ -207,7 +205,6 @@ class ZRender { */ refreshImmediately(fromInside?: boolean) { // const start = new Date(); - if (!fromInside) { // Update animation if refreshImmediately is invoked from outside. // Not trigger stage update to call flush again. Which may refresh twice @@ -220,12 +217,6 @@ class ZRender { this.painter.refresh(); // Avoid trigger zr.refresh in Element#beforeUpdate hook this._needsRefresh = false; - - // const end = new Date(); - // const log = document.getElementById('log'); - // if (log) { - // log.innerHTML = log.innerHTML + '
' + (end - start); - // } } /** @@ -247,7 +238,7 @@ class ZRender { private _flush(fromInside?: boolean) { let triggerRendered; - const start = new Date().getTime(); + const start = getTime(); if (this._needsRefresh) { triggerRendered = true; this.refreshImmediately(fromInside); @@ -257,7 +248,7 @@ class ZRender { triggerRendered = true; this.refreshHoverImmediately(); } - const end = new Date().getTime(); + const end = getTime(); if (triggerRendered) { this._stillFrameAccum = 0; @@ -291,27 +282,6 @@ class ZRender { this._stillFrameAccum = 0; } - /** - * Add element to hover layer - */ - addHover(el: Displayable) { - // deprecated. - } - - /** - * Add element from hover layer - */ - removeHover(el: Path | TSpan | ZRImage) { - // deprecated. - } - - /** - * Clear all hover elements in hover layer - */ - clearHover() { - // deprecated. - } - /** * Refresh hover in next frame */ @@ -363,28 +333,6 @@ class ZRender { return this.painter.getHeight(); } - /** - * Export the canvas as Base64 URL - * @param {string} type - * @param {string} [backgroundColor='#fff'] - * @return {string} Base64 URL - */ - // toDataURL: function(type, backgroundColor) { - // return this.painter.getRenderedCanvas({ - // backgroundColor: backgroundColor - // }).toDataURL(type); - // }, - - /** - * Converting a path to image. - * It has much better performance of drawing image rather than drawing a vector path. - */ - pathToImage(e: Path, dpr: number) { - if (this.painter.pathToImage) { - return this.painter.pathToImage(e, dpr); - } - } - /** * Set default cursor * @param cursorStyle='default' 例如 crosshair @@ -477,12 +425,15 @@ export interface ZRenderInitOpt { width?: number | string // 10, 10px, 'auto' height?: number | string useDirtyRect?: boolean + ssr?: boolean // If enable ssr mode. } /** * Initializing a zrender instance + * + * @param dom Not necessary if using SSR painter like svg-ssr */ -export function init(dom: HTMLElement, opts?: ZRenderInitOpt) { +export function init(dom?: HTMLElement | null, opts?: ZRenderInitOpt) { const zr = new ZRender(zrUtil.guid(), dom, opts); instances[zr.id] = zr; return zr; diff --git a/test/animation-additive-simple.html b/test/animation-additive-simple.html index 00724e609..a09ea5d4b 100644 --- a/test/animation-additive-simple.html +++ b/test/animation-additive-simple.html @@ -75,7 +75,6 @@ hexogonNormal.animateTo({ rotation, - scale, scaleX: scale, scaleY: scale }, { diff --git a/test/animation-cubic-easing.html b/test/animation-cubic-easing.html new file mode 100644 index 000000000..800a249d1 --- /dev/null +++ b/test/animation-cubic-easing.html @@ -0,0 +1,81 @@ + + + + + Animation Keyframe Easing + + + + + + + +
+

SVG SSR

+
+ + + \ No newline at end of file diff --git a/test/animation-keyframe-easing.html b/test/animation-keyframe-easing.html new file mode 100644 index 000000000..d692b966b --- /dev/null +++ b/test/animation-keyframe-easing.html @@ -0,0 +1,50 @@ + + + + + Animation Keyframe Easing + + + + + +
+ + + \ No newline at end of file diff --git a/test/animation.html b/test/animation.html index 69e436d69..970890f14 100644 --- a/test/animation.html +++ b/test/animation.html @@ -23,6 +23,12 @@ gradient.addColorStop(0, 'red'); gradient.addColorStop(1, 'black'); + + var gradient2 = new zrender.LinearGradient(); + gradient2.addColorStop(0, 'black'); + gradient2.addColorStop(0.5, 'blue'); + gradient2.addColorStop(1, 'white'); + var circle = new zrender.Circle({ position: [100, 100], scale: [1, 1], @@ -52,6 +58,11 @@ position: [200, 0] }) .start(); + circle.animate('style', true) + .when(1000, { + fill: gradient2 + }) + .start(); circle.animate('', true) .when(1000, { position: [200, 0] diff --git a/test/animation2.html b/test/animation2.html deleted file mode 100644 index a30ce2ac3..000000000 --- a/test/animation2.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - Animation - - - - - - -
- - \ No newline at end of file diff --git a/test/asciiWidthMap.html b/test/asciiWidthMap.html new file mode 100644 index 000000000..d158b29c5 --- /dev/null +++ b/test/asciiWidthMap.html @@ -0,0 +1,26 @@ + + + + + + + ASCII width map + + + + + \ No newline at end of file diff --git a/test/benchmark.html b/test/benchmark.html index f3188b1da..f5791d8fe 100644 --- a/test/benchmark.html +++ b/test/benchmark.html @@ -50,7 +50,7 @@ var renderMode = hasParam('svg') ? 'svg' : 'canvas'; var zr = zrender.init(document.getElementById('main'), { - renderer: renderMode + renderer: 'svg-ssr' }); var stats = new Stats(); diff --git a/test/boundingbox.html b/test/boundingbox.html index 61e7b4298..9396edddc 100644 --- a/test/boundingbox.html +++ b/test/boundingbox.html @@ -3,22 +3,27 @@ 包围盒计算测试 - -
- + \ No newline at end of file diff --git a/test/css-transform-inverse.html b/test/css-transform-inverse.html index f235303f3..c27c9eb11 100644 --- a/test/css-transform-inverse.html +++ b/test/css-transform-inverse.html @@ -24,8 +24,6 @@ - - @@ -179,52 +177,58 @@ - + diff --git a/test/cubic.html b/test/cubic.html index 72c857480..ce821090f 100644 --- a/test/cubic.html +++ b/test/cubic.html @@ -3,14 +3,19 @@ cubic 函数测试 - - - + diff --git a/test/lib/esl.js b/test/lib/esl.js deleted file mode 100644 index 1f3ec7758..000000000 --- a/test/lib/esl.js +++ /dev/null @@ -1 +0,0 @@ -var define,require,esl;!function(n){function e(n,e){function r(n){0===n.indexOf(".")&&i.push(n)}var i=[];if("string"==typeof n?r(n):$(n,function(n){r(n)}),i.length>0)throw new Error("[REQUIRE_FATAL]Relative ID is not allowed in global require: "+i.join(", "));var o=C.waitSeconds;return o&&n instanceof Array&&(D&&clearTimeout(D),D=setTimeout(t,1e3*o)),_(n,e)}function t(){function n(a,u){if(!o[a]&&!l(a,N)){o[a]=1,l(a,L)||r[a]||(r[a]=1,e.push(a));var f=T[a];f?u&&(r[a]||(r[a]=1,e.push(a)),$(f.depMs,function(e){n(e.absId,e.hard)})):i[a]||(i[a]=1,t.push(a))}}var e=[],t=[],r={},i={},o={};for(var a in F)n(a,1);if(e.length||t.length)throw new Error("[MODULE_TIMEOUT]Hang( "+(e.join(", ")||"none")+" ) Miss( "+(t.join(", ")||"none")+" )")}function r(n){$(H,function(e){a(n,e.deps,e.factory)}),H.length=0,u(n)}function i(n,e,t){if(null==t&&(null==e?(t=n,n=null):(t=e,e=null,n instanceof Array&&(e=n,n=null))),null!=t){var r=window.opera;if(!n&&document.attachEvent&&(!r||"[object Opera]"!==r.toString())){var i=S();n=i&&i.getAttribute("data-require-id")}n?a(n,e,t):H[0]={deps:e,factory:t}}}function o(){var n=C.config[this.id];return n&&"object"==typeof n?n:{}}function a(n,e,t){T[n]||(T[n]={id:n,depsDec:e,deps:e||["require","exports","module"],factoryDeps:[],factory:t,exports:{},config:o,state:z,require:w(n),depMs:[],depMkv:{},depRs:[],depPMs:[]})}function u(n){var e=T[n];if(e&&!l(n,B)){var t=e.deps,r=e.factory,i=0;"function"==typeof r&&(i=Math.min(r.length,t.length),!e.depsDec&&r.toString().replace(/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/gm,"").replace(/require\(\s*(['"'])([^'"]+)\1\s*\)/g,function(n,e,r){t.push(r)}));var o=[];$(t,function(t,r){var a,u,f=I(t),c=q(f.mod,n);c&&!P[c]?(f.res&&(u={id:t,mod:c,res:f.res},F[c]=1,e.depPMs.push(c),e.depRs.push(u)),a=e.depMkv[c],a||(a={id:f.mod,absId:c,hard:i>r},e.depMs.push(a),e.depMkv[c]=a,o.push(c))):a={absId:c},i>r&&e.factoryDeps.push(u||a)}),e.state=B,s(n),m(o)}}function f(){for(var n in F)c(n),d(n)}function c(n){function e(n){if(!l(n,B))return!1;if(l(n,L)||t[n])return!0;t[n]=1;var r=T[n],i=!0;return $(r.depMs,function(n){return i=e(n.absId)}),i&&$(r.depRs,function(n){return i=!(!n.absId||!l(n.absId,N))}),i&&(r.state=L),i}var t={};e(n)}function s(e){function t(){if(!r&&i.state===L){r=1;var t=1,o=[];if($(i.factoryDeps,function(n){var e=n.absId;return P[e]||(d(e),l(e,N))?void o.push(e):(t=0,!1)}),t){try{var a=p(o,{require:i.require,exports:i.exports,module:i}),u=i.factory,f="function"==typeof u?u.apply(n,a):u;null!=f&&(i.exports=f),i.invokeFactory=null,delete F[e]}catch(c){if(r=0,/^\[MODULE_MISS\]"([^"]+)/.test(c.message)){var s=i.depMkv[RegExp.$1];return void(s&&(s.hard=1))}throw c}g(e)}}}var r,i=T[e];i.invokeFactory=t,$(i.depPMs,function(n){v(n,function(){$(i.depRs,function(t){t.absId||t.mod!==n||(t.absId=q(t.id,e),m([t.absId],f))})})})}function l(n,e){return T[n]&&T[n].state>=e}function d(n){var e=T[n];e&&e.invokeFactory&&e.invokeFactory()}function p(n,e){var t=[];return $(n,function(n,r){t[r]=e[n]||h(n)}),t}function v(n,e){if(l(n,N))return void e();var t=Q[n];t||(t=Q[n]=[]),t.push(e)}function g(n){var e=Q[n]||[],t=T[n];t.state=N;for(var r=e.length;r--;)e[r]();e.length=0,delete Q[n]}function h(n){return l(n,N)?T[n].exports:null}function m(e,t,r,i){function o(){if(!a){var r=1;$(e,function(n){return P[n]?void 0:r=!!l(n,N)}),r&&(a=1,"function"==typeof t&&t.apply(n,p(e,P)))}}if("string"==typeof e){if(d(e),!l(e,N))throw new Error('[MODULE_MISS]"'+e+'" is not exists!');return h(e)}i=i||{};var a=0;e instanceof Array&&(o(),a||($(e,function(n){P[n]||l(n,N)||(v(n,o),i[n]||(n.indexOf("!")>0?b:y)(n,r),u(n))}),f()))}function y(n){function e(){var e=t.readyState;if("undefined"==typeof e||/^(loaded|complete)$/.test(e)){t.onload=t.onreadystatechange=null,t=null,r(n);for(var i in F)u(i);f()}}if(!G[n]&&!T[n]){G[n]=1;var t=document.createElement("script");t.setAttribute("data-require-id",n),t.src=E(n+".js"),t.async=!0,t.readyState?t.onreadystatechange=e:t.onload=e,U(t)}}function b(n,e){function t(e){u.exports=e||!0,g(n)}function i(r){var i=e?T[e].require:_;r.load(a.res,i,t,o.call({id:n}))}if(!T[n]){var a=I(n),u={id:n,state:B};T[n]=u,t.fromText=function(n,e){F[n]=1,new Function(e)(),r(n)},i(h(a.mod))}}function M(n,e){var t=R(n,1,e);return t.sort(j),t}function k(){C.baseUrl=C.baseUrl.replace(/\/$/,"")+"/",J=M(C.paths),V=M(C.map,1),$(V,function(n){n.v=M(n.v)}),K=[],$(C.packages,function(n){var e=n;"string"==typeof n&&(e={name:n.split("/")[0],location:n,main:"main"}),e.location=e.location||e.name,e.main=(e.main||"main").replace(/\.js$/i,""),e.reg=O(e.name),K.push(e)}),K.sort(j),W=M(C.urlArgs,1),X=M(C.noRequests),$(X,function(n){var e=n.v,t={};n.v=t,e instanceof Array||(e=[e]),$(e,function(n){t[n]=1})})}function x(n,e,t){$(e,function(e){return e.reg.test(n)?(t(e.v,e.k,e),!1):void 0})}function E(n){var e=/(\.[a-z0-9]+)$/i,t=/(\?[^#]*)$/,r="",i=n,o="";t.test(n)&&(o=RegExp.$1,n=n.replace(t,"")),e.test(n)&&(r=RegExp.$1,i=n.replace(e,""));var a,u=i;return x(i,J,function(n,e){u=u.replace(e,n),a=1}),a||x(i,K,function(n,e,t){u=u.replace(t.name,t.location)}),/^([a-z]{2,10}:\/)?\//i.test(u)||(u=C.baseUrl+u),u+=r+o,x(i,W,function(n){u+=(u.indexOf("?")>0?"&":"?")+n}),u}function w(n){function e(e,r){if("string"==typeof e)return t[e]||(t[e]=m(q(e,n))),t[e];if(e instanceof Array){var i=[],o=[],a=[];$(e,function(e,t){var r=I(e),u=q(r.mod,n);o.push(u),F[u]=1,r.res?(i.push(u),a[t]=null):a[t]=u});var u={};$(o,function(n){var e;x(n,X,function(n){e=n}),e&&(e["*"]?u[n]=1:$(o,function(t){return e[t]?(u[n]=1,!1):void 0}))}),m(o,function(){$(a,function(t,r){null==t&&(a[r]=q(e[r],n))}),m(a,r,n)},n,u)}}var t={};return e.toUrl=function(e){return E(q(e,n))},e}function q(n,e){if(!n)return"";e=e||"";var t=I(n);if(!t)return n;var r=t.res,i=A(t.mod,e);if($(K,function(n){var e=n.name;return e===i?(i=e+"/"+n.main,!1):void 0}),x(e,V,function(n){x(i,n,function(n,e){i=i.replace(e,n)})}),r){var o=h(i);r=o.normalize?o.normalize(r,function(n){return q(n,e)}):q(r,e),i+="!"+r}return i}function A(n,e){if(0===n.indexOf(".")){var t=e.split("/"),r=n.split("/"),i=t.length-1,o=r.length,a=0,u=0;n:for(var f=0;o>f;f++)switch(r[f]){case"..":if(!(i>a))break n;a++,u++;break;case".":u++;break;default:break n}return t.length=i-a,r=r.slice(u),t.concat(r).join("/")}return n}function I(n){var e=n.split("!");return e[0]?{mod:e[0],res:e[1]}:null}function R(n,e,t){var r=[];for(var i in n)if(n.hasOwnProperty(i)){var o={k:i,v:n[i]};r.push(o),e&&(o.reg="*"===i&&t?/^/:O(i))}return r}function S(){if(Y)return Y;if(Z&&"interactive"===Z.readyState)return Z;for(var n=document.getElementsByTagName("script"),e=n.length;e--;){var t=n[e];if("interactive"===t.readyState)return Z=t,t}}function U(n){Y=n,ee?ne.insertBefore(n,ee):ne.appendChild(n),Y=null}function O(n){return new RegExp("^"+n+"(/|$)")}function $(n,e){if(n instanceof Array)for(var t=0,r=n.length;r>t&&e(n[t],t)!==!1;t++);}function j(n,e){var t=n.k||n.name,r=e.k||e.name;return"*"===r?-1:"*"===t?1:r.length-t.length}var D,T={},F={},z=1,B=2,L=3,N=4,P={require:e,exports:1,module:1},_=w(),C={baseUrl:"./",paths:{},config:{},map:{},packages:[],waitSeconds:0,noRequests:{},urlArgs:{}};e.version="1.8.8",e.loader="esl",e.toUrl=_.toUrl;var H=[];i.amd={};var Q={},G={};e.config=function(n){if(n){for(var e in C){var t=n[e],r=C[e];if(t)if("urlArgs"===e&&"string"==typeof t)C.urlArgs["*"]=t;else if(r instanceof Array)r.push.apply(r,t);else if("object"==typeof r)for(var i in t)r[i]=t[i];else C[e]=t}k()}},k();var J,K,V,W,X,Y,Z,ne=document.getElementsByTagName("head")[0],ee=document.getElementsByTagName("base")[0];ee&&(ne=ee.parentNode),define||(define=i,require||(require=e),esl=e)}(this); \ No newline at end of file diff --git a/test/lib/requireES.js b/test/lib/requireES.js deleted file mode 100644 index 12290f3bd..000000000 --- a/test/lib/requireES.js +++ /dev/null @@ -1,349 +0,0 @@ -/** - * Load es modules in browser. - * rollup.browser.js is required. - * - * [Usage]: - * - * // AMD config like. - * requireES.config({ - * baseUrl: '..', - * paths: { - * ... - * }, - * packages: [ - * {...}, ... - * ], - * urlArgs: +new Date(), - * sourceMap: true // Enable sourceMap for debugging. `false` by default. - * }); - * - * requireES([ - * 'xxx/moduleA', - * 'yyy/moduleB' - * ], function (moduleA, moduleB) { - * ... - * }); - * - * [Caution]: - * - * 1) Modules are not shared between different calling of `requireES(...)`. - * - * 2) Whether import `*` or `default` is determined by the module itself. - * That is, if the module (like `xxx/SomeClz`) only export `default` , it - * imports `default`, otherwise (like `xxx/util`) it imports `*`. - */ - -/* global define, ActiveXObject */ - -(function (global, factory) { - typeof define === 'function' && define.amd - ? define(['rollup'], factory) - : (global.requireES = factory(global.rollup)); - }(this, function (rollup) { 'use strict'; - - var TOP_MODULE_NAME = 'topModuleInRequireES'; - - var amdCfg = { - baseUrl: cwd(), - paths: {}, - packages: [], - urlArgs: null - }; - - /** - * Like AMD config. - * - * @param {Object} cfg { - * @param {string} [cfg.baseUrl='.'] - * @param {Object} [cfg.paths={}] - * @param {Array.} [cfg.packages=[]] - * @param {string} [cfg.urlArgs=''] - * @param {boolean} [cfg.sourceMap=false] - */ - function amdConfig(cfg) { - if (cfg.baseUrl != null) { - amdCfg.baseUrl = resolve(cwd(), cfg.baseUrl); - } - if (cfg.paths) { - amdCfg.paths = extend({}, cfg.paths); - } - if (cfg.packages) { - amdCfg.packages.length = 0; - for (var i = 0; i < cfg.packages.length; i++) { - amdCfg.packages[i] = extend({}, cfg.packages[i]); - } - } - if (cfg.urlArgs != null) { - amdCfg.urlArgs = cfg.urlArgs; - } - if (cfg.sourceMap != null) { - amdCfg.sourceMap = cfg.sourceMap; - } - } - - /** - * Load es modules and convert to AMD modules. - * - * @param {Array.} moduleIds like ['./echarts', ...] - * @param {Function} onload Arguments: loaded modules, - * which has been converted to AMD module. - */ - function requireES(moduleIds, onload) { - - if (!(moduleIds instanceof Array)) { - throw new Error('`path` should be an array'); - } - - if (!moduleIds.length) { - return; - } - - var topCode = generateTopModuleCode(moduleIds); - - rollup.rollup({ - input: TOP_MODULE_NAME, - legacy: true, - plugins: [{ - resolveId: function (importee, importor) { - if (importee === TOP_MODULE_NAME) { - return importee; - } - // console.log('resolveid', importee, importor); - return getAbsolutePath( - importee, - importor !== TOP_MODULE_NAME ? importor : null - ); - }, - load: function (path) { - if (path === TOP_MODULE_NAME) { - return topCode; - } - // TODO Use tag to void browser cache and cache manually. - return ajax(location.origin + path); - } - }] - }).then(function (bundle) { - return bundle.generate({ - format: 'iife', - legacy: true, - // But only bundle.write support generating inline source map. - sourcemap: 'inline', - name: TOP_MODULE_NAME - }); - }).then(function (result) { - - var code = result.code; - - if (amdCfg.sourceMap) { - code = addSourceMap(code, result.map); - } - - var modules = (new Function( - 'var __DEV__ = true; ' - + code - + '\n return ' + TOP_MODULE_NAME - ))(); - - var exportsList = []; - for (var i = 0; i < moduleIds.length; i++) { - var mod = modules['m' + i]; - // Guess whether `*` or `default` is required: if only `default` - // exported, like 'xxx/SomeClz', `default` is required. - if (onlyDefaultExported(mod)) { - mod = mod['default']; - } - exportsList.push(mod); - } - onload && onload.apply(null, exportsList); - }); - } - - requireES.config = amdConfig; - - function onlyDefaultExported(mod) { - for (var name in mod) { - if (mod.hasOwnProperty(name)) { - if (name !== 'default') { - return false; - } - } - } - return true; - } - - function generateTopModuleCode(moduleIds) { - var code = []; - - for (var i = 0; i < moduleIds.length; i++) { - var moduleId = moduleIds[i]; - code.push('import * as m' + i + ' from "' + moduleId + '";'); - } - - for (var i = 0; i < moduleIds.length; i++) { - code.push('export {m' + i + '};'); - } - - return code.join('\n'); - } - - // Get absolute path. `basePath` can be omitted if moduleId is absolute. - function getAbsolutePath(moduleId, basePath) { - moduleId = addExt(moduleId); - - for (var path in amdCfg.paths) { - if (amdCfg.paths.hasOwnProperty(path)) { - if (moduleId.indexOf(path) === 0) { - moduleId = moduleId.replace(path, amdCfg.paths[path]); - return resolve(amdCfg.baseUrl, moduleId); - } - } - } - - for (var i = 0; i < amdCfg.packages.length; i++) { - var packageCfg = amdCfg.packages[i]; - var moduleIdArr = moduleId.split('/'); - if (moduleIdArr[0] === packageCfg.name) { - moduleIdArr[0] = packageCfg.location; - if (!moduleIdArr[1]) { - moduleIdArr[1] = packageCfg.main; - } - moduleId = moduleIdArr.join('/'); - return resolve(amdCfg.baseUrl, moduleId); - } - } - - if (basePath) { - moduleId = resolve(dir(basePath), moduleId); - } - - if (moduleId.charAt(0) !== '/') { - throw new Error('"' + moduleId + '" can not be found.'); - } - - return moduleId; - } - - function addExt(moduleId) { - if (moduleId.split('/').pop().indexOf('.') < 0) { - moduleId += '.js'; - } - return moduleId; - } - - function ajax(toUrl) { - if (amdCfg.urlArgs != null) { - toUrl += '?' + amdCfg.urlArgs; - } - - return new Promise(function (promiseResolve, promiseReject) { - var xhr = window.XMLHttpRequest - ? new XMLHttpRequest() - : new ActiveXObject('Microsoft.XMLHTTP'); - - xhr.open('GET', toUrl, true); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - (xhr.status >= 200 && xhr.status < 300) - ? promiseResolve(xhr.responseText) - : promiseReject({ - status: xhr.status, - content: xhr.responseText - }); - xhr.onreadystatechange = new Function(); - xhr = null; - } - }; - - xhr.send(null); - }); - } - - // Nodejs `path.resolve`. - function resolve() { - var resolvedPath = ''; - var resolvedAbsolute; - - for (var i = arguments.length - 1; i >= 0 && !resolvedAbsolute; i--) { - var path = arguments[i]; - if (path) { - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path[0] === '/'; - } - } - - if (!resolvedAbsolute) { - throw new Error('At least one absolute path should be input.'); - } - - // Normalize the path - resolvedPath = normalizePathArray(resolvedPath.split('/'), false).join('/'); - - return '/' + resolvedPath; - } - - // resolves . and .. elements in a path array with directory names there - // must be no slashes or device names (c:\) in the array - // (so also no leading and trailing slashes - it does not distinguish - // relative and absolute paths) - function normalizePathArray(parts, allowAboveRoot) { - var res = []; - for (var i = 0; i < parts.length; i++) { - var p = parts[i]; - - // ignore empty parts - if (!p || p === '.') { - continue; - } - - if (p === '..') { - if (res.length && res[res.length - 1] !== '..') { - res.pop(); - } else if (allowAboveRoot) { - res.push('..'); - } - } else { - res.push(p); - } - } - - return res; - } - - function addSourceMap(code, map) { - // Use unescape(encodeURIComponent) to avoid the error on Chrome: - // Uncaught (in promise) DOMException: Failed to execute 'btoa' on 'Window': - // The string to be encoded contains characters outside of the Latin1 range - var dataURI = btoa(unescape(encodeURIComponent(map.toString()))); // jshint ignore:line - dataURI = 'data:application/json;charset=utf-8;base64,' + dataURI; - - // Split the string to prevent sourcemap tooling from mistaking - // this for an actual sourceMappingURL. - code += '//# ' + 'sourceMa' + 'ppingURL' + '=' + dataURI + '\n'; - - return code; - } - - function cwd() { - // Only support that works in browser. - return dir(location.pathname); - } - - function dir(path) { - if (path) { - return path.charAt(path.length - 1) === '/' ? path : resolve(path, '..'); - } - } - - function extend(target, source) { - for (var key in source) { - if (source.hasOwnProperty(key)) { - target[key] = source[key]; - } - } - return target; - } - - return requireES; - -})); diff --git a/test/lib/rollup.browser.js b/test/lib/rollup.browser.js deleted file mode 100644 index 5800e748e..000000000 --- a/test/lib/rollup.browser.js +++ /dev/null @@ -1,10626 +0,0 @@ -/* - Rollup.js v0.50.0 - Sat Sep 16 2017 09:48:09 GMT-0400 (EDT) - commit b949eb08169115ff66648838cbc4833379bf9440 - - - https://github.com/rollup/rollup - - Released under the MIT License. -*/ - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.rollup = {}))); -}(this, (function (exports) { 'use strict'; - -const DEBUG = false; -const map = new Map; - -let timeStartHelper; -let timeEndHelper; - -if ( typeof process === 'undefined' || typeof process.hrtime === 'undefined' ) { - timeStartHelper = function timeStartHelper () { - return window.performance.now(); - }; - - timeEndHelper = function timeEndHelper ( previous ) { - return window.performance.now() - previous; - }; -} else { - timeStartHelper = function timeStartHelper () { - return process.hrtime(); - }; - - timeEndHelper = function timeEndHelper ( previous ) { - const hrtime = process.hrtime( previous ); - return hrtime[0] * 1e3 + Math.floor( hrtime[1] / 1e6 ); - }; -} - -function timeStart ( label ) { - if ( !map.has( label ) ) { - map.set( label, { - time: 0 - }); - } - map.get( label ).start = timeStartHelper(); -} - -function timeEnd ( label ) { - if ( map.has( label ) ) { - const item = map.get( label ); - item.time += timeEndHelper( item.start ); - } -} - -function flushTime ( log ) { - if ( log === void 0 ) log = defaultLog; - - for ( const item of map.entries() ) { - log( item[0], item[1].time ); - } - map.clear(); -} - -function defaultLog ( label, time ) { - if ( DEBUG ) { - /* eslint-disable no-console */ - console.info( '%dms: %s', time, label ); - /* eslint-enable no-console */ - } -} - -const absolutePath = /^(?:\/|(?:[A-Za-z]:)?[\\|/])/; -const relativePath = /^\.?\.\//; - -function isAbsolute ( path ) { - return absolutePath.test( path ); -} - -function isRelative ( path ) { - return relativePath.test( path ); -} - -function normalize ( path ) { - return path.replace( /\\/g, '/' ); -} - -function basename ( path ) { - return path.split( /(\/|\\)/ ).pop(); -} - -function dirname ( path ) { - const match = /(\/|\\)[^/\\]*$/.exec( path ); - if ( !match ) { return '.'; } - - const dir = path.slice( 0, -match[0].length ); - - // If `dir` is the empty string, we're at root. - return dir ? dir : '/'; -} - -function extname ( path ) { - const match = /\.[^.]+$/.exec( basename( path ) ); - if ( !match ) { return ''; } - return match[0]; -} - -function relative ( from, to ) { - const fromParts = from.split( /[/\\]/ ).filter( Boolean ); - const toParts = to.split( /[/\\]/ ).filter( Boolean ); - - while ( fromParts[0] && toParts[0] && fromParts[0] === toParts[0] ) { - fromParts.shift(); - toParts.shift(); - } - - while ( toParts[0] === '.' || toParts[0] === '..' ) { - const toPart = toParts.shift(); - if ( toPart === '..' ) { - fromParts.pop(); - } - } - - while ( fromParts.pop() ) { - toParts.unshift( '..' ); - } - - return toParts.join( '/' ); -} - -function resolve () { - var paths = [], len = arguments.length; - while ( len-- ) paths[ len ] = arguments[ len ]; - - let resolvedParts = paths.shift().split( /[/\\]/ ); - - paths.forEach( path => { - if ( isAbsolute( path ) ) { - resolvedParts = path.split( /[/\\]/ ); - } else { - const parts = path.split( /[/\\]/ ); - - while ( parts[0] === '.' || parts[0] === '..' ) { - const part = parts.shift(); - if ( part === '..' ) { - resolvedParts.pop(); - } - } - - resolvedParts.push.apply( resolvedParts, parts ); - } - }); - - return resolvedParts.join( '/' ); // TODO windows... -} - -const nope = method => `Cannot use fs.${method} inside browser`; - -const lstatSync = nope( 'lstatSync' ); -const readdirSync = nope( 'readdirSync' ); -const readFileSync = nope( 'readFileSync' ); -const realpathSync = nope( 'realpathSync' ); -const writeFile = nope( 'writeFile' ); - -var keys = Object.keys; - -function blank () { - return Object.create( null ); -} - -function forOwn ( object, func ) { - Object.keys( object ).forEach( key => func( object[ key ], key ) ); -} - -function assign ( target ) { - var sources = [], len = arguments.length - 1; - while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; - - sources.forEach( source => { - for ( const key in source ) { - if ( source.hasOwnProperty( key ) ) { target[ key ] = source[ key ]; } - } - }); - - return target; -} - -function mapSequence ( array, fn ) { - const results = []; - let promise = Promise.resolve(); - - function next ( member, i ) { - return Promise.resolve( fn( member ) ).then( value => results[i] = value ); - } - - for ( let i = 0; i < array.length; i += 1 ) { - promise = promise.then( () => next( array[i], i ) ); - } - - return promise.then( () => results ); -} - -function validateKeys ( actualKeys, allowedKeys ) { - let i = actualKeys.length; - - while ( i-- ) { - const key = actualKeys[i]; - - if ( allowedKeys.indexOf( key ) === -1 ) { - return new Error( - `Unexpected key '${ key }' found, expected one of: ${ allowedKeys.join( ', ' ) }` - ); - } - } -} - -function error ( props ) { - // use the same constructor as props (if it's an error object) - // so that err.name is preserved etc - // (Object.keys below does not update these values because they - // are properties on the prototype chain) - // basically if props is a SyntaxError it will not be overriden as a generic Error - const constructor = (props instanceof Error) ? props.constructor : Error; - const err = new constructor( props.message ); - - Object.keys( props ).forEach( key => { - err[ key ] = props[ key ]; - }); - - throw err; -} - -// this looks ridiculous, but it prevents sourcemap tooling from mistaking -// this for an actual sourceMappingURL -let SOURCEMAPPING_URL = 'sourceMa'; -SOURCEMAPPING_URL += 'ppingURL'; - -const SOURCEMAPPING_URL_RE = new RegExp( `^#\\s+${SOURCEMAPPING_URL}=.+\\n?` ); - -var charToInteger = {}; -var integerToChar = {}; - -'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split( '' ).forEach( function ( char, i ) { - charToInteger[ char ] = i; - integerToChar[ i ] = char; -}); - -function decode$1 ( string ) { - var result = [], - len = string.length, - i, - hasContinuationBit, - shift = 0, - value = 0, - integer, - shouldNegate; - - for ( i = 0; i < len; i += 1 ) { - integer = charToInteger[ string[i] ]; - - if ( integer === undefined ) { - throw new Error( 'Invalid character (' + string[i] + ')' ); - } - - hasContinuationBit = integer & 32; - - integer &= 31; - value += integer << shift; - - if ( hasContinuationBit ) { - shift += 5; - } else { - shouldNegate = value & 1; - value >>= 1; - - result.push( shouldNegate ? -value : value ); - - // reset - value = shift = 0; - } - } - - return result; -} - -function encode$1 ( value ) { - var result, i; - - if ( typeof value === 'number' ) { - result = encodeInteger( value ); - } else { - result = ''; - for ( i = 0; i < value.length; i += 1 ) { - result += encodeInteger( value[i] ); - } - } - - return result; -} - -function encodeInteger ( num ) { - var result = '', clamped; - - if ( num < 0 ) { - num = ( -num << 1 ) | 1; - } else { - num <<= 1; - } - - do { - clamped = num & 31; - num >>= 5; - - if ( num > 0 ) { - clamped |= 32; - } - - result += integerToChar[ clamped ]; - } while ( num > 0 ); - - return result; -} - -function decodeSegments ( encodedSegments ) { - var i = encodedSegments.length; - var segments = new Array( i ); - - while ( i-- ) { segments[i] = decode$1( encodedSegments[i] ); } - return segments; -} - -function decode$$1 ( mappings ) { - var sourceFileIndex = 0; // second field - var sourceCodeLine = 0; // third field - var sourceCodeColumn = 0; // fourth field - var nameIndex = 0; // fifth field - - var lines = mappings.split( ';' ); - var numLines = lines.length; - var decoded = new Array( numLines ); - - var i; - var j; - var line; - var generatedCodeColumn; - var decodedLine; - var segments; - var segment; - var result; - - for ( i = 0; i < numLines; i += 1 ) { - line = lines[i]; - - generatedCodeColumn = 0; // first field - reset each time - decodedLine = []; - - segments = decodeSegments( line.split( ',' ) ); - - for ( j = 0; j < segments.length; j += 1 ) { - segment = segments[j]; - - if ( !segment.length ) { - break; - } - - generatedCodeColumn += segment[0]; - - result = [ generatedCodeColumn ]; - decodedLine.push( result ); - - if ( segment.length === 1 ) { - // only one field! - continue; - } - - sourceFileIndex += segment[1]; - sourceCodeLine += segment[2]; - sourceCodeColumn += segment[3]; - - result.push( sourceFileIndex, sourceCodeLine, sourceCodeColumn ); - - if ( segment.length === 5 ) { - nameIndex += segment[4]; - result.push( nameIndex ); - } - } - - decoded[i] = decodedLine; - } - - return decoded; -} - -function encode$$1 ( decoded ) { - var offsets = { - generatedCodeColumn: 0, - sourceFileIndex: 0, // second field - sourceCodeLine: 0, // third field - sourceCodeColumn: 0, // fourth field - nameIndex: 0 // fifth field - }; - - return decoded.map( function (line) { - offsets.generatedCodeColumn = 0; // first field - reset each time - return line.map( encodeSegment ).join( ',' ); - }).join( ';' ); - - function encodeSegment ( segment ) { - if ( !segment.length ) { - return segment; - } - - var result = new Array( segment.length ); - - result[0] = segment[0] - offsets.generatedCodeColumn; - offsets.generatedCodeColumn = segment[0]; - - if ( segment.length === 1 ) { - // only one field! - return encode$1( result ); - } - - result[1] = segment[1] - offsets.sourceFileIndex; - result[2] = segment[2] - offsets.sourceCodeLine; - result[3] = segment[3] - offsets.sourceCodeColumn; - - offsets.sourceFileIndex = segment[1]; - offsets.sourceCodeLine = segment[2]; - offsets.sourceCodeColumn = segment[3]; - - if ( segment.length === 5 ) { - result[4] = segment[4] - offsets.nameIndex; - offsets.nameIndex = segment[4]; - } - - return encode$1( result ); - } -} - -var charToInteger$1 = {}; -var integerToChar$1 = {}; - -'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split( '' ).forEach( function ( char, i ) { - charToInteger$1[ char ] = i; - integerToChar$1[ i ] = char; -}); - - - -function encode ( value ) { - var result; - - if ( typeof value === 'number' ) { - result = encodeInteger$1( value ); - } else { - result = ''; - for ( var i = 0; i < value.length; i += 1 ) { - result += encodeInteger$1( value[i] ); - } - } - - return result; -} - -function encodeInteger$1 ( num ) { - var result = ''; - - if ( num < 0 ) { - num = ( -num << 1 ) | 1; - } else { - num <<= 1; - } - - do { - var clamped = num & 31; - num >>= 5; - - if ( num > 0 ) { - clamped |= 32; - } - - result += integerToChar$1[ clamped ]; - } while ( num > 0 ); - - return result; -} - -function Chunk ( start, end, content ) { - this.start = start; - this.end = end; - this.original = content; - - this.intro = ''; - this.outro = ''; - - this.content = content; - this.storeName = false; - this.edited = false; - - // we make these non-enumerable, for sanity while debugging - Object.defineProperties( this, { - previous: { writable: true, value: null }, - next: { writable: true, value: null } - }); -} - -Chunk.prototype = { - appendLeft: function appendLeft ( content ) { - this.outro += content; - }, - - appendRight: function appendRight ( content ) { - this.intro = this.intro + content; - }, - - clone: function clone () { - var chunk = new Chunk( this.start, this.end, this.original ); - - chunk.intro = this.intro; - chunk.outro = this.outro; - chunk.content = this.content; - chunk.storeName = this.storeName; - chunk.edited = this.edited; - - return chunk; - }, - - contains: function contains ( index ) { - return this.start < index && index < this.end; - }, - - eachNext: function eachNext ( fn ) { - var chunk = this; - while ( chunk ) { - fn( chunk ); - chunk = chunk.next; - } - }, - - eachPrevious: function eachPrevious ( fn ) { - var chunk = this; - while ( chunk ) { - fn( chunk ); - chunk = chunk.previous; - } - }, - - edit: function edit ( content, storeName, contentOnly ) { - this.content = content; - if ( !contentOnly ) { - this.intro = ''; - this.outro = ''; - } - this.storeName = storeName; - - this.edited = true; - - return this; - }, - - prependLeft: function prependLeft ( content ) { - this.outro = content + this.outro; - }, - - prependRight: function prependRight ( content ) { - this.intro = content + this.intro; - }, - - split: function split ( index ) { - var sliceIndex = index - this.start; - - var originalBefore = this.original.slice( 0, sliceIndex ); - var originalAfter = this.original.slice( sliceIndex ); - - this.original = originalBefore; - - var newChunk = new Chunk( index, this.end, originalAfter ); - newChunk.outro = this.outro; - this.outro = ''; - - this.end = index; - - if ( this.edited ) { - // TODO is this block necessary?... - newChunk.edit( '', false ); - this.content = ''; - } else { - this.content = originalBefore; - } - - newChunk.next = this.next; - if ( newChunk.next ) { newChunk.next.previous = newChunk; } - newChunk.previous = this; - this.next = newChunk; - - return newChunk; - }, - - toString: function toString () { - return this.intro + this.content + this.outro; - }, - - trimEnd: function trimEnd ( rx ) { - this.outro = this.outro.replace( rx, '' ); - if ( this.outro.length ) { return true; } - - var trimmed = this.content.replace( rx, '' ); - - if ( trimmed.length ) { - if ( trimmed !== this.content ) { - this.split( this.start + trimmed.length ).edit( '', false ); - } - - return true; - } else { - this.edit( '', false ); - - this.intro = this.intro.replace( rx, '' ); - if ( this.intro.length ) { return true; } - } - }, - - trimStart: function trimStart ( rx ) { - this.intro = this.intro.replace( rx, '' ); - if ( this.intro.length ) { return true; } - - var trimmed = this.content.replace( rx, '' ); - - if ( trimmed.length ) { - if ( trimmed !== this.content ) { - this.split( this.end - trimmed.length ); - this.edit( '', false ); - } - - return true; - } else { - this.edit( '', false ); - - this.outro = this.outro.replace( rx, '' ); - if ( this.outro.length ) { return true; } - } - } -}; - -var _btoa; - -if ( typeof window !== 'undefined' && typeof window.btoa === 'function' ) { - _btoa = window.btoa; -} else if ( typeof Buffer === 'function' ) { - _btoa = function (str) { return new Buffer( str ).toString( 'base64' ); }; -} else { - _btoa = function () { - throw new Error( 'Unsupported environment: `window.btoa` or `Buffer` should be supported.' ); - }; -} - -var btoa = _btoa; - -function SourceMap ( properties ) { - this.version = 3; - - this.file = properties.file; - this.sources = properties.sources; - this.sourcesContent = properties.sourcesContent; - this.names = properties.names; - this.mappings = properties.mappings; -} - -SourceMap.prototype = { - toString: function toString () { - return JSON.stringify( this ); - }, - - toUrl: function toUrl () { - return 'data:application/json;charset=utf-8;base64,' + btoa( this.toString() ); - } -}; - -function guessIndent ( code ) { - var lines = code.split( '\n' ); - - var tabbed = lines.filter( function (line) { return /^\t+/.test( line ); } ); - var spaced = lines.filter( function (line) { return /^ {2,}/.test( line ); } ); - - if ( tabbed.length === 0 && spaced.length === 0 ) { - return null; - } - - // More lines tabbed than spaced? Assume tabs, and - // default to tabs in the case of a tie (or nothing - // to go on) - if ( tabbed.length >= spaced.length ) { - return '\t'; - } - - // Otherwise, we need to guess the multiple - var min = spaced.reduce( function ( previous, current ) { - var numSpaces = /^ +/.exec( current )[0].length; - return Math.min( numSpaces, previous ); - }, Infinity ); - - return new Array( min + 1 ).join( ' ' ); -} - -function getRelativePath ( from, to ) { - var fromParts = from.split( /[\/\\]/ ); - var toParts = to.split( /[\/\\]/ ); - - fromParts.pop(); // get dirname - - while ( fromParts[0] === toParts[0] ) { - fromParts.shift(); - toParts.shift(); - } - - if ( fromParts.length ) { - var i = fromParts.length; - while ( i-- ) { fromParts[i] = '..'; } - } - - return fromParts.concat( toParts ).join( '/' ); -} - -var toString$1 = Object.prototype.toString; - -function isObject ( thing ) { - return toString$1.call( thing ) === '[object Object]'; -} - -function getLocator ( source ) { - var originalLines = source.split( '\n' ); - - var start = 0; - var lineRanges = originalLines.map( function ( line, i ) { - var end = start + line.length + 1; - var range = { start: start, end: end, line: i }; - - start = end; - return range; - }); - - var i = 0; - - function rangeContains ( range, index ) { - return range.start <= index && index < range.end; - } - - function getLocation ( range, index ) { - return { line: range.line, column: index - range.start }; - } - - return function locate ( index ) { - var range = lineRanges[i]; - - var d = index >= range.end ? 1 : -1; - - while ( range ) { - if ( rangeContains( range, index ) ) { return getLocation( range, index ); } - - i += d; - range = lineRanges[i]; - } - }; -} - -function Mappings ( hires ) { - var this$1 = this; - - var offsets = { - generatedCodeColumn: 0, - sourceIndex: 0, - sourceCodeLine: 0, - sourceCodeColumn: 0, - sourceCodeName: 0 - }; - - var generatedCodeLine = 0; - var generatedCodeColumn = 0; - - this.raw = []; - var rawSegments = this.raw[ generatedCodeLine ] = []; - - var pending = null; - - this.addEdit = function ( sourceIndex, content, original, loc, nameIndex ) { - if ( content.length ) { - rawSegments.push([ - generatedCodeColumn, - sourceIndex, - loc.line, - loc.column, - nameIndex ]); - } else if ( pending ) { - rawSegments.push( pending ); - } - - this$1.advance( content ); - pending = null; - }; - - this.addUneditedChunk = function ( sourceIndex, chunk, original, loc, sourcemapLocations ) { - var originalCharIndex = chunk.start; - var first = true; - - while ( originalCharIndex < chunk.end ) { - if ( hires || first || sourcemapLocations[ originalCharIndex ] ) { - rawSegments.push([ - generatedCodeColumn, - sourceIndex, - loc.line, - loc.column, - -1 - ]); - } - - if ( original[ originalCharIndex ] === '\n' ) { - loc.line += 1; - loc.column = 0; - generatedCodeLine += 1; - this$1.raw[ generatedCodeLine ] = rawSegments = []; - generatedCodeColumn = 0; - } else { - loc.column += 1; - generatedCodeColumn += 1; - } - - originalCharIndex += 1; - first = false; - } - - pending = [ - generatedCodeColumn, - sourceIndex, - loc.line, - loc.column, - -1 ]; - }; - - this.advance = function (str) { - if ( !str ) { return; } - - var lines = str.split( '\n' ); - var lastLine = lines.pop(); - - if ( lines.length ) { - generatedCodeLine += lines.length; - this$1.raw[ generatedCodeLine ] = rawSegments = []; - generatedCodeColumn = lastLine.length; - } else { - generatedCodeColumn += lastLine.length; - } - }; - - this.encode = function () { - return this$1.raw.map( function (segments) { - var generatedCodeColumn = 0; - - return segments.map( function (segment) { - var arr = [ - segment[0] - generatedCodeColumn, - segment[1] - offsets.sourceIndex, - segment[2] - offsets.sourceCodeLine, - segment[3] - offsets.sourceCodeColumn - ]; - - generatedCodeColumn = segment[0]; - offsets.sourceIndex = segment[1]; - offsets.sourceCodeLine = segment[2]; - offsets.sourceCodeColumn = segment[3]; - - if ( ~segment[4] ) { - arr.push( segment[4] - offsets.sourceCodeName ); - offsets.sourceCodeName = segment[4]; - } - - return encode( arr ); - }).join( ',' ); - }).join( ';' ); - }; -} - -var Stats = function Stats () { - Object.defineProperties( this, { - startTimes: { value: {} } - }); -}; - -Stats.prototype.time = function time ( label ) { - this.startTimes[ label ] = process.hrtime(); -}; - -Stats.prototype.timeEnd = function timeEnd ( label ) { - var elapsed = process.hrtime( this.startTimes[ label ] ); - - if ( !this[ label ] ) { this[ label ] = 0; } - this[ label ] += elapsed[0] * 1e3 + elapsed[1] * 1e-6; -}; - -var warned = { - insertLeft: false, - insertRight: false, - storeName: false -}; - -function MagicString$1 ( string, options ) { - if ( options === void 0 ) options = {}; - - var chunk = new Chunk( 0, string.length, string ); - - Object.defineProperties( this, { - original: { writable: true, value: string }, - outro: { writable: true, value: '' }, - intro: { writable: true, value: '' }, - firstChunk: { writable: true, value: chunk }, - lastChunk: { writable: true, value: chunk }, - lastSearchedChunk: { writable: true, value: chunk }, - byStart: { writable: true, value: {} }, - byEnd: { writable: true, value: {} }, - filename: { writable: true, value: options.filename }, - indentExclusionRanges: { writable: true, value: options.indentExclusionRanges }, - sourcemapLocations: { writable: true, value: {} }, - storedNames: { writable: true, value: {} }, - indentStr: { writable: true, value: guessIndent( string ) } - }); - - this.byStart[ 0 ] = chunk; - this.byEnd[ string.length ] = chunk; -} - -MagicString$1.prototype = { - addSourcemapLocation: function addSourcemapLocation ( char ) { - this.sourcemapLocations[ char ] = true; - }, - - append: function append ( content ) { - if ( typeof content !== 'string' ) { throw new TypeError( 'outro content must be a string' ); } - - this.outro += content; - return this; - }, - - appendLeft: function appendLeft ( index, content ) { - if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); } - - this._split( index ); - - var chunk = this.byEnd[ index ]; - - if ( chunk ) { - chunk.appendLeft( content ); - } else { - this.intro += content; - } - - return this; - }, - - appendRight: function appendRight ( index, content ) { - if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); } - - this._split( index ); - - var chunk = this.byStart[ index ]; - - if ( chunk ) { - chunk.appendRight( content ); - } else { - this.outro += content; - } - - return this; - }, - - clone: function clone () { - var cloned = new MagicString$1( this.original, { filename: this.filename }); - - var originalChunk = this.firstChunk; - var clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone(); - - while ( originalChunk ) { - cloned.byStart[ clonedChunk.start ] = clonedChunk; - cloned.byEnd[ clonedChunk.end ] = clonedChunk; - - var nextOriginalChunk = originalChunk.next; - var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone(); - - if ( nextClonedChunk ) { - clonedChunk.next = nextClonedChunk; - nextClonedChunk.previous = clonedChunk; - - clonedChunk = nextClonedChunk; - } - - originalChunk = nextOriginalChunk; - } - - cloned.lastChunk = clonedChunk; - - if ( this.indentExclusionRanges ) { - cloned.indentExclusionRanges = this.indentExclusionRanges.slice(); - } - - Object.keys( this.sourcemapLocations ).forEach( function (loc) { - cloned.sourcemapLocations[ loc ] = true; - }); - - return cloned; - }, - - generateMap: function generateMap ( options ) { - var this$1 = this; - - options = options || {}; - - var sourceIndex = 0; - var names = Object.keys( this.storedNames ); - var mappings = new Mappings( options.hires ); - - var locate = getLocator( this.original ); - - if ( this.intro ) { - mappings.advance( this.intro ); - } - - this.firstChunk.eachNext( function (chunk) { - var loc = locate( chunk.start ); - - if ( chunk.intro.length ) { mappings.advance( chunk.intro ); } - - if ( chunk.edited ) { - mappings.addEdit( sourceIndex, chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1 ); - } else { - mappings.addUneditedChunk( sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations ); - } - - if ( chunk.outro.length ) { mappings.advance( chunk.outro ); } - }); - - var map = new SourceMap({ - file: ( options.file ? options.file.split( /[\/\\]/ ).pop() : null ), - sources: [ options.source ? getRelativePath( options.file || '', options.source ) : null ], - sourcesContent: options.includeContent ? [ this.original ] : [ null ], - names: names, - mappings: mappings.encode() - }); - return map; - }, - - getIndentString: function getIndentString () { - return this.indentStr === null ? '\t' : this.indentStr; - }, - - indent: function indent ( indentStr, options ) { - var this$1 = this; - - var pattern = /^[^\r\n]/gm; - - if ( isObject( indentStr ) ) { - options = indentStr; - indentStr = undefined; - } - - indentStr = indentStr !== undefined ? indentStr : ( this.indentStr || '\t' ); - - if ( indentStr === '' ) { return this; } // noop - - options = options || {}; - - // Process exclusion ranges - var isExcluded = {}; - - if ( options.exclude ) { - var exclusions = typeof options.exclude[0] === 'number' ? [ options.exclude ] : options.exclude; - exclusions.forEach( function (exclusion) { - for ( var i = exclusion[0]; i < exclusion[1]; i += 1 ) { - isExcluded[i] = true; - } - }); - } - - var shouldIndentNextCharacter = options.indentStart !== false; - var replacer = function (match) { - if ( shouldIndentNextCharacter ) { return ("" + indentStr + match); } - shouldIndentNextCharacter = true; - return match; - }; - - this.intro = this.intro.replace( pattern, replacer ); - - var charIndex = 0; - - var chunk = this.firstChunk; - - while ( chunk ) { - var end = chunk.end; - - if ( chunk.edited ) { - if ( !isExcluded[ charIndex ] ) { - chunk.content = chunk.content.replace( pattern, replacer ); - - if ( chunk.content.length ) { - shouldIndentNextCharacter = chunk.content[ chunk.content.length - 1 ] === '\n'; - } - } - } else { - charIndex = chunk.start; - - while ( charIndex < end ) { - if ( !isExcluded[ charIndex ] ) { - var char = this$1.original[ charIndex ]; - - if ( char === '\n' ) { - shouldIndentNextCharacter = true; - } else if ( char !== '\r' && shouldIndentNextCharacter ) { - shouldIndentNextCharacter = false; - - if ( charIndex === chunk.start ) { - chunk.prependRight( indentStr ); - } else { - this$1._splitChunk( chunk, charIndex ); - chunk = chunk.next; - chunk.prependRight( indentStr ); - } - } - } - - charIndex += 1; - } - } - - charIndex = chunk.end; - chunk = chunk.next; - } - - this.outro = this.outro.replace( pattern, replacer ); - - return this; - }, - - insert: function insert () { - throw new Error( 'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)' ); - }, - - insertLeft: function insertLeft ( index, content ) { - if ( !warned.insertLeft ) { - console.warn( 'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead' ); // eslint-disable-line no-console - warned.insertLeft = true; - } - - return this.appendLeft( index, content ); - }, - - insertRight: function insertRight ( index, content ) { - if ( !warned.insertRight ) { - console.warn( 'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead' ); // eslint-disable-line no-console - warned.insertRight = true; - } - - return this.prependRight( index, content ); - }, - - move: function move ( start, end, index ) { - if ( index >= start && index <= end ) { throw new Error( 'Cannot move a selection inside itself' ); } - - this._split( start ); - this._split( end ); - this._split( index ); - - var first = this.byStart[ start ]; - var last = this.byEnd[ end ]; - - var oldLeft = first.previous; - var oldRight = last.next; - - var newRight = this.byStart[ index ]; - if ( !newRight && last === this.lastChunk ) { return this; } - var newLeft = newRight ? newRight.previous : this.lastChunk; - - if ( oldLeft ) { oldLeft.next = oldRight; } - if ( oldRight ) { oldRight.previous = oldLeft; } - - if ( newLeft ) { newLeft.next = first; } - if ( newRight ) { newRight.previous = last; } - - if ( !first.previous ) { this.firstChunk = last.next; } - if ( !last.next ) { - this.lastChunk = first.previous; - this.lastChunk.next = null; - } - - first.previous = newLeft; - last.next = newRight || null; - - if ( !newLeft ) { this.firstChunk = first; } - if ( !newRight ) { this.lastChunk = last; } - - return this; - }, - - overwrite: function overwrite ( start, end, content, options ) { - var this$1 = this; - - if ( typeof content !== 'string' ) { throw new TypeError( 'replacement content must be a string' ); } - - while ( start < 0 ) { start += this$1.original.length; } - while ( end < 0 ) { end += this$1.original.length; } - - if ( end > this.original.length ) { throw new Error( 'end is out of bounds' ); } - if ( start === end ) { throw new Error( 'Cannot overwrite a zero-length range – use appendLeft or prependRight instead' ); } - - this._split( start ); - this._split( end ); - - if ( options === true ) { - if ( !warned.storeName ) { - console.warn( 'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string' ); // eslint-disable-line no-console - warned.storeName = true; - } - - options = { storeName: true }; - } - var storeName = options !== undefined ? options.storeName : false; - var contentOnly = options !== undefined ? options.contentOnly : false; - - if ( storeName ) { - var original = this.original.slice( start, end ); - this.storedNames[ original ] = true; - } - - var first = this.byStart[ start ]; - var last = this.byEnd[ end ]; - - if ( first ) { - if ( end > first.end && first.next !== this.byStart[ first.end ] ) { - throw new Error( 'Cannot overwrite across a split point' ); - } - - first.edit( content, storeName, contentOnly ); - - if ( first !== last ) { - var chunk = first.next; - while ( chunk !== last ) { - chunk.edit( '', false ); - chunk = chunk.next; - } - - chunk.edit( '', false ); - } - } - - else { - // must be inserting at the end - var newChunk = new Chunk( start, end, '' ).edit( content, storeName ); - - // TODO last chunk in the array may not be the last chunk, if it's moved... - last.next = newChunk; - newChunk.previous = last; - } - - return this; - }, - - prepend: function prepend ( content ) { - if ( typeof content !== 'string' ) { throw new TypeError( 'outro content must be a string' ); } - - this.intro = content + this.intro; - return this; - }, - - prependLeft: function prependLeft ( index, content ) { - if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); } - - this._split( index ); - - var chunk = this.byEnd[ index ]; - - if ( chunk ) { - chunk.prependLeft( content ); - } else { - this.intro = content + this.intro; - } - - return this; - }, - - prependRight: function prependRight ( index, content ) { - if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); } - - this._split( index ); - - var chunk = this.byStart[ index ]; - - if ( chunk ) { - chunk.prependRight( content ); - } else { - this.outro = content + this.outro; - } - - return this; - }, - - remove: function remove ( start, end ) { - var this$1 = this; - - while ( start < 0 ) { start += this$1.original.length; } - while ( end < 0 ) { end += this$1.original.length; } - - if ( start === end ) { return this; } - - if ( start < 0 || end > this.original.length ) { throw new Error( 'Character is out of bounds' ); } - if ( start > end ) { throw new Error( 'end must be greater than start' ); } - - this._split( start ); - this._split( end ); - - var chunk = this.byStart[ start ]; - - while ( chunk ) { - chunk.intro = ''; - chunk.outro = ''; - chunk.edit( '' ); - - chunk = end > chunk.end ? this$1.byStart[ chunk.end ] : null; - } - - return this; - }, - - slice: function slice ( start, end ) { - var this$1 = this; - if ( start === void 0 ) start = 0; - if ( end === void 0 ) end = this.original.length; - - while ( start < 0 ) { start += this$1.original.length; } - while ( end < 0 ) { end += this$1.original.length; } - - var result = ''; - - // find start chunk - var chunk = this.firstChunk; - while ( chunk && ( chunk.start > start || chunk.end <= start ) ) { - - // found end chunk before start - if ( chunk.start < end && chunk.end >= end ) { - return result; - } - - chunk = chunk.next; - } - - if ( chunk && chunk.edited && chunk.start !== start ) { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); } - - var startChunk = chunk; - while ( chunk ) { - if ( chunk.intro && ( startChunk !== chunk || chunk.start === start ) ) { - result += chunk.intro; - } - - var containsEnd = chunk.start < end && chunk.end >= end; - if ( containsEnd && chunk.edited && chunk.end !== end ) { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); } - - var sliceStart = startChunk === chunk ? start - chunk.start : 0; - var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length; - - result += chunk.content.slice( sliceStart, sliceEnd ); - - if ( chunk.outro && ( !containsEnd || chunk.end === end ) ) { - result += chunk.outro; - } - - if ( containsEnd ) { - break; - } - - chunk = chunk.next; - } - - return result; - }, - - // TODO deprecate this? not really very useful - snip: function snip ( start, end ) { - var clone = this.clone(); - clone.remove( 0, start ); - clone.remove( end, clone.original.length ); - - return clone; - }, - - _split: function _split ( index ) { - var this$1 = this; - - if ( this.byStart[ index ] || this.byEnd[ index ] ) { return; } - - var chunk = this.lastSearchedChunk; - var searchForward = index > chunk.end; - - while ( true ) { - if ( chunk.contains( index ) ) { return this$1._splitChunk( chunk, index ); } - - chunk = searchForward ? - this$1.byStart[ chunk.end ] : - this$1.byEnd[ chunk.start ]; - } - }, - - _splitChunk: function _splitChunk ( chunk, index ) { - if ( chunk.edited && chunk.content.length ) { // zero-length edited chunks are a special case (overlapping replacements) - var loc = getLocator( this.original )( index ); - throw new Error( ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")") ); - } - - var newChunk = chunk.split( index ); - - this.byEnd[ index ] = chunk; - this.byStart[ index ] = newChunk; - this.byEnd[ newChunk.end ] = newChunk; - - if ( chunk === this.lastChunk ) { this.lastChunk = newChunk; } - - this.lastSearchedChunk = chunk; - return true; - }, - - toString: function toString () { - var str = this.intro; - - var chunk = this.firstChunk; - while ( chunk ) { - str += chunk.toString(); - chunk = chunk.next; - } - - return str + this.outro; - }, - - trimLines: function trimLines () { - return this.trim('[\\r\\n]'); - }, - - trim: function trim ( charType ) { - return this.trimStart( charType ).trimEnd( charType ); - }, - - trimEnd: function trimEnd ( charType ) { - var this$1 = this; - - var rx = new RegExp( ( charType || '\\s' ) + '+$' ); - - this.outro = this.outro.replace( rx, '' ); - if ( this.outro.length ) { return this; } - - var chunk = this.lastChunk; - - do { - var end = chunk.end; - var aborted = chunk.trimEnd( rx ); - - // if chunk was trimmed, we have a new lastChunk - if ( chunk.end !== end ) { - if ( this$1.lastChunk === chunk ) { - this$1.lastChunk = chunk.next; - } - - this$1.byEnd[ chunk.end ] = chunk; - this$1.byStart[ chunk.next.start ] = chunk.next; - this$1.byEnd[ chunk.next.end ] = chunk.next; - } - - if ( aborted ) { return this$1; } - chunk = chunk.previous; - } while ( chunk ); - - return this; - }, - - trimStart: function trimStart ( charType ) { - var this$1 = this; - - var rx = new RegExp( '^' + ( charType || '\\s' ) + '+' ); - - this.intro = this.intro.replace( rx, '' ); - if ( this.intro.length ) { return this; } - - var chunk = this.firstChunk; - - do { - var end = chunk.end; - var aborted = chunk.trimStart( rx ); - - if ( chunk.end !== end ) { - // special case... - if ( chunk === this$1.lastChunk ) { this$1.lastChunk = chunk.next; } - - this$1.byEnd[ chunk.end ] = chunk; - this$1.byStart[ chunk.next.start ] = chunk.next; - this$1.byEnd[ chunk.next.end ] = chunk.next; - } - - if ( aborted ) { return this$1; } - chunk = chunk.next; - } while ( chunk ); - - return this; - } -}; - -var hasOwnProp = Object.prototype.hasOwnProperty; - -function Bundle$1 ( options ) { - if ( options === void 0 ) options = {}; - - this.intro = options.intro || ''; - this.separator = options.separator !== undefined ? options.separator : '\n'; - - this.sources = []; - - this.uniqueSources = []; - this.uniqueSourceIndexByFilename = {}; -} - -Bundle$1.prototype = { - addSource: function addSource ( source ) { - if ( source instanceof MagicString$1 ) { - return this.addSource({ - content: source, - filename: source.filename, - separator: this.separator - }); - } - - if ( !isObject( source ) || !source.content ) { - throw new Error( 'bundle.addSource() takes an object with a `content` property, which should be an instance of MagicString, and an optional `filename`' ); - } - - [ 'filename', 'indentExclusionRanges', 'separator' ].forEach( function (option) { - if ( !hasOwnProp.call( source, option ) ) { source[ option ] = source.content[ option ]; } - }); - - if ( source.separator === undefined ) { // TODO there's a bunch of this sort of thing, needs cleaning up - source.separator = this.separator; - } - - if ( source.filename ) { - if ( !hasOwnProp.call( this.uniqueSourceIndexByFilename, source.filename ) ) { - this.uniqueSourceIndexByFilename[ source.filename ] = this.uniqueSources.length; - this.uniqueSources.push({ filename: source.filename, content: source.content.original }); - } else { - var uniqueSource = this.uniqueSources[ this.uniqueSourceIndexByFilename[ source.filename ] ]; - if ( source.content.original !== uniqueSource.content ) { - throw new Error( ("Illegal source: same filename (" + (source.filename) + "), different contents") ); - } - } - } - - this.sources.push( source ); - return this; - }, - - append: function append ( str, options ) { - this.addSource({ - content: new MagicString$1( str ), - separator: ( options && options.separator ) || '' - }); - - return this; - }, - - clone: function clone () { - var bundle = new Bundle$1({ - intro: this.intro, - separator: this.separator - }); - - this.sources.forEach( function (source) { - bundle.addSource({ - filename: source.filename, - content: source.content.clone(), - separator: source.separator - }); - }); - - return bundle; - }, - - generateMap: function generateMap ( options ) { - var this$1 = this; - if ( options === void 0 ) options = {}; - - var names = []; - this.sources.forEach( function (source) { - Object.keys( source.content.storedNames ).forEach( function (name) { - if ( !~names.indexOf( name ) ) { names.push( name ); } - }); - }); - - var mappings = new Mappings( options.hires ); - - if ( this.intro ) { - mappings.advance( this.intro ); - } - - this.sources.forEach( function ( source, i ) { - if ( i > 0 ) { - mappings.advance( this$1.separator ); - } - - var sourceIndex = source.filename ? this$1.uniqueSourceIndexByFilename[ source.filename ] : -1; - var magicString = source.content; - var locate = getLocator( magicString.original ); - - if ( magicString.intro ) { - mappings.advance( magicString.intro ); - } - - magicString.firstChunk.eachNext( function (chunk) { - var loc = locate( chunk.start ); - - if ( chunk.intro.length ) { mappings.advance( chunk.intro ); } - - if ( source.filename ) { - if ( chunk.edited ) { - mappings.addEdit( sourceIndex, chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1 ); - } else { - mappings.addUneditedChunk( sourceIndex, chunk, magicString.original, loc, magicString.sourcemapLocations ); - } - } - - else { - mappings.advance( chunk.content ); - } - - if ( chunk.outro.length ) { mappings.advance( chunk.outro ); } - }); - - if ( magicString.outro ) { - mappings.advance( magicString.outro ); - } - }); - - return new SourceMap({ - file: ( options.file ? options.file.split( /[\/\\]/ ).pop() : null ), - sources: this.uniqueSources.map( function (source) { - return options.file ? getRelativePath( options.file, source.filename ) : source.filename; - }), - sourcesContent: this.uniqueSources.map( function (source) { - return options.includeContent ? source.content : null; - }), - names: names, - mappings: mappings.encode() - }); - }, - - getIndentString: function getIndentString () { - var indentStringCounts = {}; - - this.sources.forEach( function (source) { - var indentStr = source.content.indentStr; - - if ( indentStr === null ) { return; } - - if ( !indentStringCounts[ indentStr ] ) { indentStringCounts[ indentStr ] = 0; } - indentStringCounts[ indentStr ] += 1; - }); - - return ( Object.keys( indentStringCounts ).sort( function ( a, b ) { - return indentStringCounts[a] - indentStringCounts[b]; - })[0] ) || '\t'; - }, - - indent: function indent ( indentStr ) { - var this$1 = this; - - if ( !arguments.length ) { - indentStr = this.getIndentString(); - } - - if ( indentStr === '' ) { return this; } // noop - - var trailingNewline = !this.intro || this.intro.slice( -1 ) === '\n'; - - this.sources.forEach( function ( source, i ) { - var separator = source.separator !== undefined ? source.separator : this$1.separator; - var indentStart = trailingNewline || ( i > 0 && /\r?\n$/.test( separator ) ); - - source.content.indent( indentStr, { - exclude: source.indentExclusionRanges, - indentStart: indentStart//: trailingNewline || /\r?\n$/.test( separator ) //true///\r?\n/.test( separator ) - }); - - // TODO this is a very slow way to determine this - trailingNewline = source.content.toString().slice( 0, -1 ) === '\n'; - }); - - if ( this.intro ) { - this.intro = indentStr + this.intro.replace( /^[^\n]/gm, function ( match, index ) { - return index > 0 ? indentStr + match : match; - }); - } - - return this; - }, - - prepend: function prepend ( str ) { - this.intro = str + this.intro; - return this; - }, - - toString: function toString () { - var this$1 = this; - - var body = this.sources.map( function ( source, i ) { - var separator = source.separator !== undefined ? source.separator : this$1.separator; - var str = ( i > 0 ? separator : '' ) + source.content.toString(); - - return str; - }).join( '' ); - - return this.intro + body; - }, - - trimLines: function trimLines () { - return this.trim('[\\r\\n]'); - }, - - trim: function trim ( charType ) { - return this.trimStart( charType ).trimEnd( charType ); - }, - - trimStart: function trimStart ( charType ) { - var this$1 = this; - - var rx = new RegExp( '^' + ( charType || '\\s' ) + '+' ); - this.intro = this.intro.replace( rx, '' ); - - if ( !this.intro ) { - var source; - var i = 0; - - do { - source = this$1.sources[i]; - - if ( !source ) { - break; - } - - source.content.trimStart( charType ); - i += 1; - } while ( source.content.toString() === '' ); // TODO faster way to determine non-empty source? - } - - return this; - }, - - trimEnd: function trimEnd ( charType ) { - var this$1 = this; - - var rx = new RegExp( ( charType || '\\s' ) + '+$' ); - - var source; - var i = this.sources.length - 1; - - do { - source = this$1.sources[i]; - - if ( !source ) { - this$1.intro = this$1.intro.replace( rx, '' ); - break; - } - - source.content.trimEnd( charType ); - i -= 1; - } while ( source.content.toString() === '' ); // TODO faster way to determine non-empty source? - - return this; - } -}; - -// Return the first non-falsy result from an array of -// maybe-sync, maybe-promise-returning functions -function first ( candidates ) { - return function () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - return candidates.reduce( ( promise, candidate ) => { - return promise.then( result => result != null ? - result : - Promise.resolve( candidate.apply( void 0, args ) ) ); - }, Promise.resolve() ); - }; -} - -function find ( array, fn ) { - for ( let i = 0; i < array.length; i += 1 ) { - if ( fn( array[i], i ) ) { return array[i]; } - } - - return null; -} - -// Reserved word lists for various dialects of the language - -var reservedWords = { - 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", - 5: "class enum extends super const export import", - 6: "enum", - strict: "implements interface let package private protected public static yield", - strictBind: "eval arguments" -}; - -// And the keywords - -var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; - -var keywords = { - 5: ecma5AndLessKeywords, - 6: ecma5AndLessKeywords + " const class extends export import super" -}; - -// ## Character categories - -// Big ugly regular expressions that match characters in the -// whitespace, identifier, and identifier-start categories. These -// are only applied when a character is found to actually have a -// code point above 128. -// Generated by `bin/generate-identifier-regex.js`. - -var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; -var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; - -var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); -var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); - -nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; - -// These are a run-length and offset encoded representation of the -// >0xffff code points that are a valid part of identifiers. The -// offset starts at 0x10000, and each pair of numbers represents an -// offset to the next range, and then a size of the range. They were -// generated by bin/generate-identifier-regex.js - -// eslint-disable-next-line comma-spacing -var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541]; - -// eslint-disable-next-line comma-spacing -var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239]; - -// This has a complexity linear to the value of the code. The -// assumption is that looking up astral identifier characters is -// rare. -function isInAstralSet(code, set) { - var pos = 0x10000; - for (var i = 0; i < set.length; i += 2) { - pos += set[i]; - if (pos > code) { return false } - pos += set[i + 1]; - if (pos >= code) { return true } - } -} - -// Test whether a given character code starts an identifier. - -function isIdentifierStart(code, astral) { - if (code < 65) { return code === 36 } - if (code < 91) { return true } - if (code < 97) { return code === 95 } - if (code < 123) { return true } - if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } - if (astral === false) { return false } - return isInAstralSet(code, astralIdentifierStartCodes) -} - -// Test whether a given character is part of an identifier. - -function isIdentifierChar(code, astral) { - if (code < 48) { return code === 36 } - if (code < 58) { return true } - if (code < 65) { return false } - if (code < 91) { return true } - if (code < 97) { return code === 95 } - if (code < 123) { return true } - if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } - if (astral === false) { return false } - return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) -} - -// ## Token types - -// The assignment of fine-grained, information-carrying type objects -// allows the tokenizer to store the information it has about a -// token in a way that is very cheap for the parser to look up. - -// All token type variables start with an underscore, to make them -// easy to recognize. - -// The `beforeExpr` property is used to disambiguate between regular -// expressions and divisions. It is set on all token types that can -// be followed by an expression (thus, a slash after them would be a -// regular expression). -// -// The `startsExpr` property is used to check if the token ends a -// `yield` expression. It is set on all token types that either can -// directly start an expression (like a quotation mark) or can -// continue an expression (like the body of a string). -// -// `isLoop` marks a keyword as starting a loop, which is important -// to know when parsing a label, in order to allow or disallow -// continue jumps to that label. - -var TokenType = function TokenType(label, conf) { - if ( conf === void 0 ) { conf = {}; } - - this.label = label; - this.keyword = conf.keyword; - this.beforeExpr = !!conf.beforeExpr; - this.startsExpr = !!conf.startsExpr; - this.isLoop = !!conf.isLoop; - this.isAssign = !!conf.isAssign; - this.prefix = !!conf.prefix; - this.postfix = !!conf.postfix; - this.binop = conf.binop || null; - this.updateContext = null; -}; - -function binop(name, prec) { - return new TokenType(name, {beforeExpr: true, binop: prec}) -} -var beforeExpr = {beforeExpr: true}; -var startsExpr = {startsExpr: true}; - -// Map keyword names to token types. - -var keywords$1 = {}; - -// Succinct definitions of keyword token types -function kw(name, options) { - if ( options === void 0 ) { options = {}; } - - options.keyword = name; - return keywords$1[name] = new TokenType(name, options) -} - -var types = { - num: new TokenType("num", startsExpr), - regexp: new TokenType("regexp", startsExpr), - string: new TokenType("string", startsExpr), - name: new TokenType("name", startsExpr), - eof: new TokenType("eof"), - - // Punctuation token types. - bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), - bracketR: new TokenType("]"), - braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), - braceR: new TokenType("}"), - parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), - parenR: new TokenType(")"), - comma: new TokenType(",", beforeExpr), - semi: new TokenType(";", beforeExpr), - colon: new TokenType(":", beforeExpr), - dot: new TokenType("."), - question: new TokenType("?", beforeExpr), - arrow: new TokenType("=>", beforeExpr), - template: new TokenType("template"), - invalidTemplate: new TokenType("invalidTemplate"), - ellipsis: new TokenType("...", beforeExpr), - backQuote: new TokenType("`", startsExpr), - dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), - - // Operators. These carry several kinds of properties to help the - // parser use them properly (the presence of these properties is - // what categorizes them as operators). - // - // `binop`, when present, specifies that this operator is a binary - // operator, and will refer to its precedence. - // - // `prefix` and `postfix` mark the operator as a prefix or postfix - // unary operator. - // - // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as - // binary operators with a very low precedence, that should result - // in AssignmentExpression nodes. - - eq: new TokenType("=", {beforeExpr: true, isAssign: true}), - assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), - incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), - prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), - logicalOR: binop("||", 1), - logicalAND: binop("&&", 2), - bitwiseOR: binop("|", 3), - bitwiseXOR: binop("^", 4), - bitwiseAND: binop("&", 5), - equality: binop("==/!=/===/!==", 6), - relational: binop("/<=/>=", 7), - bitShift: binop("<>/>>>", 8), - plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), - modulo: binop("%", 10), - star: binop("*", 10), - slash: binop("/", 10), - starstar: new TokenType("**", {beforeExpr: true}), - - // Keyword token types. - _break: kw("break"), - _case: kw("case", beforeExpr), - _catch: kw("catch"), - _continue: kw("continue"), - _debugger: kw("debugger"), - _default: kw("default", beforeExpr), - _do: kw("do", {isLoop: true, beforeExpr: true}), - _else: kw("else", beforeExpr), - _finally: kw("finally"), - _for: kw("for", {isLoop: true}), - _function: kw("function", startsExpr), - _if: kw("if"), - _return: kw("return", beforeExpr), - _switch: kw("switch"), - _throw: kw("throw", beforeExpr), - _try: kw("try"), - _var: kw("var"), - _const: kw("const"), - _while: kw("while", {isLoop: true}), - _with: kw("with"), - _new: kw("new", {beforeExpr: true, startsExpr: true}), - _this: kw("this", startsExpr), - _super: kw("super", startsExpr), - _class: kw("class", startsExpr), - _extends: kw("extends", beforeExpr), - _export: kw("export"), - _import: kw("import"), - _null: kw("null", startsExpr), - _true: kw("true", startsExpr), - _false: kw("false", startsExpr), - _in: kw("in", {beforeExpr: true, binop: 7}), - _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), - _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), - _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), - _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) -}; - -// Matches a whole line break (where CRLF is considered a single -// line break). Used to count lines. - -var lineBreak = /\r\n?|\n|\u2028|\u2029/; -var lineBreakG = new RegExp(lineBreak.source, "g"); - -function isNewLine(code) { - return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 -} - -var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; - -var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; - -var ref = Object.prototype; -var hasOwnProperty = ref.hasOwnProperty; -var toString = ref.toString; - -// Checks if an object has a property. - -function has(obj, propName) { - return hasOwnProperty.call(obj, propName) -} - -var isArray = Array.isArray || (function (obj) { return ( - toString.call(obj) === "[object Array]" -); }); - -// These are used when `options.locations` is on, for the -// `startLoc` and `endLoc` properties. - -var Position = function Position(line, col) { - this.line = line; - this.column = col; -}; - -Position.prototype.offset = function offset (n) { - return new Position(this.line, this.column + n) -}; - -var SourceLocation = function SourceLocation(p, start, end) { - this.start = start; - this.end = end; - if (p.sourceFile !== null) { this.source = p.sourceFile; } -}; - -// The `getLineInfo` function is mostly useful when the -// `locations` option is off (for performance reasons) and you -// want to find the line/column position for a given character -// offset. `input` should be the code string that the offset refers -// into. - -function getLineInfo(input, offset) { - for (var line = 1, cur = 0;;) { - lineBreakG.lastIndex = cur; - var match = lineBreakG.exec(input); - if (match && match.index < offset) { - ++line; - cur = match.index + match[0].length; - } else { - return new Position(line, offset - cur) - } - } -} - -// A second optional argument can be given to further configure -// the parser process. These options are recognized: - -var defaultOptions = { - // `ecmaVersion` indicates the ECMAScript version to parse. Must - // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support - // for strict mode, the set of reserved words, and support for - // new syntax features. The default is 7. - ecmaVersion: 7, - // `sourceType` indicates the mode the code should be parsed in. - // Can be either `"script"` or `"module"`. This influences global - // strict mode and parsing of `import` and `export` declarations. - sourceType: "script", - // `onInsertedSemicolon` can be a callback that will be called - // when a semicolon is automatically inserted. It will be passed - // th position of the comma as an offset, and if `locations` is - // enabled, it is given the location as a `{line, column}` object - // as second argument. - onInsertedSemicolon: null, - // `onTrailingComma` is similar to `onInsertedSemicolon`, but for - // trailing commas. - onTrailingComma: null, - // By default, reserved words are only enforced if ecmaVersion >= 5. - // Set `allowReserved` to a boolean value to explicitly turn this on - // an off. When this option has the value "never", reserved words - // and keywords can also not be used as property names. - allowReserved: null, - // When enabled, a return at the top level is not considered an - // error. - allowReturnOutsideFunction: false, - // When enabled, import/export statements are not constrained to - // appearing at the top of the program. - allowImportExportEverywhere: false, - // When enabled, hashbang directive in the beginning of file - // is allowed and treated as a line comment. - allowHashBang: false, - // When `locations` is on, `loc` properties holding objects with - // `start` and `end` properties in `{line, column}` form (with - // line being 1-based and column 0-based) will be attached to the - // nodes. - locations: false, - // A function can be passed as `onToken` option, which will - // cause Acorn to call that function with object in the same - // format as tokens returned from `tokenizer().getToken()`. Note - // that you are not allowed to call the parser from the - // callback—that will corrupt its internal state. - onToken: null, - // A function can be passed as `onComment` option, which will - // cause Acorn to call that function with `(block, text, start, - // end)` parameters whenever a comment is skipped. `block` is a - // boolean indicating whether this is a block (`/* */`) comment, - // `text` is the content of the comment, and `start` and `end` are - // character offsets that denote the start and end of the comment. - // When the `locations` option is on, two more parameters are - // passed, the full `{line, column}` locations of the start and - // end of the comments. Note that you are not allowed to call the - // parser from the callback—that will corrupt its internal state. - onComment: null, - // Nodes have their start and end characters offsets recorded in - // `start` and `end` properties (directly on the node, rather than - // the `loc` object, which holds line/column data. To also add a - // [semi-standardized][range] `range` property holding a `[start, - // end]` array with the same numbers, set the `ranges` option to - // `true`. - // - // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - ranges: false, - // It is possible to parse multiple files into a single AST by - // passing the tree produced by parsing the first file as - // `program` option in subsequent parses. This will add the - // toplevel forms of the parsed file to the `Program` (top) node - // of an existing parse tree. - program: null, - // When `locations` is on, you can pass this to record the source - // file in every node's `loc` object. - sourceFile: null, - // This value, if given, is stored in every node, whether - // `locations` is on or off. - directSourceFile: null, - // When enabled, parenthesized expressions are represented by - // (non-standard) ParenthesizedExpression nodes - preserveParens: false, - plugins: {} -}; - -// Interpret and default an options object - -function getOptions(opts) { - var options = {}; - - for (var opt in defaultOptions) - { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } - - if (options.ecmaVersion >= 2015) - { options.ecmaVersion -= 2009; } - - if (options.allowReserved == null) - { options.allowReserved = options.ecmaVersion < 5; } - - if (isArray(options.onToken)) { - var tokens = options.onToken; - options.onToken = function (token) { return tokens.push(token); }; - } - if (isArray(options.onComment)) - { options.onComment = pushComment(options, options.onComment); } - - return options -} - -function pushComment(options, array) { - return function(block, text, start, end, startLoc, endLoc) { - var comment = { - type: block ? "Block" : "Line", - value: text, - start: start, - end: end - }; - if (options.locations) - { comment.loc = new SourceLocation(this, startLoc, endLoc); } - if (options.ranges) - { comment.range = [start, end]; } - array.push(comment); - } -} - -// Registered plugins -var plugins = {}; - -function keywordRegexp(words) { - return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") -} - -var Parser = function Parser(options, input, startPos) { - this.options = options = getOptions(options); - this.sourceFile = options.sourceFile; - this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); - var reserved = ""; - if (!options.allowReserved) { - for (var v = options.ecmaVersion;; v--) - { if (reserved = reservedWords[v]) { break } } - if (options.sourceType == "module") { reserved += " await"; } - } - this.reservedWords = keywordRegexp(reserved); - var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; - this.reservedWordsStrict = keywordRegexp(reservedStrict); - this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind); - this.input = String(input); - - // Used to signal to callers of `readWord1` whether the word - // contained any escape sequences. This is needed because words with - // escape sequences must not be interpreted as keywords. - this.containsEsc = false; - - // Load plugins - this.loadPlugins(options.plugins); - - // Set up token state - - // The current position of the tokenizer in the input. - if (startPos) { - this.pos = startPos; - this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; - this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; - } else { - this.pos = this.lineStart = 0; - this.curLine = 1; - } - - // Properties of the current token: - // Its type - this.type = types.eof; - // For tokens that include more information than their type, the value - this.value = null; - // Its start and end offset - this.start = this.end = this.pos; - // And, if locations are used, the {line, column} object - // corresponding to those offsets - this.startLoc = this.endLoc = this.curPosition(); - - // Position information for the previous token - this.lastTokEndLoc = this.lastTokStartLoc = null; - this.lastTokStart = this.lastTokEnd = this.pos; - - // The context stack is used to superficially track syntactic - // context to predict whether a regular expression is allowed in a - // given position. - this.context = this.initialContext(); - this.exprAllowed = true; - - // Figure out if it's a module code. - this.inModule = options.sourceType === "module"; - this.strict = this.inModule || this.strictDirective(this.pos); - - // Used to signify the start of a potential arrow function - this.potentialArrowAt = -1; - - // Flags to track whether we are in a function, a generator, an async function. - this.inFunction = this.inGenerator = this.inAsync = false; - // Positions to delayed-check that yield/await does not exist in default parameters. - this.yieldPos = this.awaitPos = 0; - // Labels in scope. - this.labels = []; - - // If enabled, skip leading hashbang line. - if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") - { this.skipLineComment(2); } - - // Scope tracking for duplicate variable names (see scope.js) - this.scopeStack = []; - this.enterFunctionScope(); -}; - -// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them -Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) }; -Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) }; - -Parser.prototype.extend = function extend (name, f) { - this[name] = f(this[name]); -}; - -Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) { - var this$1 = this; - - for (var name in pluginConfigs) { - var plugin = plugins[name]; - if (!plugin) { throw new Error("Plugin '" + name + "' not found") } - plugin(this$1, pluginConfigs[name]); - } -}; - -Parser.prototype.parse = function parse () { - var node = this.options.program || this.startNode(); - this.nextToken(); - return this.parseTopLevel(node) -}; - -var pp = Parser.prototype; - -// ## Parser utilities - -var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/; -pp.strictDirective = function(start) { - var this$1 = this; - - for (;;) { - skipWhiteSpace.lastIndex = start; - start += skipWhiteSpace.exec(this$1.input)[0].length; - var match = literal.exec(this$1.input.slice(start)); - if (!match) { return false } - if ((match[1] || match[2]) == "use strict") { return true } - start += match[0].length; - } -}; - -// Predicate that tests whether the next token is of the given -// type, and if yes, consumes it as a side effect. - -pp.eat = function(type) { - if (this.type === type) { - this.next(); - return true - } else { - return false - } -}; - -// Tests whether parsed token is a contextual keyword. - -pp.isContextual = function(name) { - return this.type === types.name && this.value === name -}; - -// Consumes contextual keyword if possible. - -pp.eatContextual = function(name) { - return this.value === name && this.eat(types.name) -}; - -// Asserts that following token is given contextual keyword. - -pp.expectContextual = function(name) { - if (!this.eatContextual(name)) { this.unexpected(); } -}; - -// Test whether a semicolon can be inserted at the current position. - -pp.canInsertSemicolon = function() { - return this.type === types.eof || - this.type === types.braceR || - lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) -}; - -pp.insertSemicolon = function() { - if (this.canInsertSemicolon()) { - if (this.options.onInsertedSemicolon) - { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } - return true - } -}; - -// Consume a semicolon, or, failing that, see if we are allowed to -// pretend that there is a semicolon at this position. - -pp.semicolon = function() { - if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } -}; - -pp.afterTrailingComma = function(tokType, notNext) { - if (this.type == tokType) { - if (this.options.onTrailingComma) - { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } - if (!notNext) - { this.next(); } - return true - } -}; - -// Expect a token of a given type. If found, consume it, otherwise, -// raise an unexpected token error. - -pp.expect = function(type) { - this.eat(type) || this.unexpected(); -}; - -// Raise an unexpected token error. - -pp.unexpected = function(pos) { - this.raise(pos != null ? pos : this.start, "Unexpected token"); -}; - -function DestructuringErrors() { - this.shorthandAssign = - this.trailingComma = - this.parenthesizedAssign = - this.parenthesizedBind = - -1; -} - -pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { - if (!refDestructuringErrors) { return } - if (refDestructuringErrors.trailingComma > -1) - { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } - var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; - if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } -}; - -pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { - var pos = refDestructuringErrors ? refDestructuringErrors.shorthandAssign : -1; - if (!andThrow) { return pos >= 0 } - if (pos > -1) { this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns"); } -}; - -pp.checkYieldAwaitInDefaultParams = function() { - if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) - { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } - if (this.awaitPos) - { this.raise(this.awaitPos, "Await expression cannot be a default value"); } -}; - -pp.isSimpleAssignTarget = function(expr) { - if (expr.type === "ParenthesizedExpression") - { return this.isSimpleAssignTarget(expr.expression) } - return expr.type === "Identifier" || expr.type === "MemberExpression" -}; - -var pp$1 = Parser.prototype; - -// ### Statement parsing - -// Parse a program. Initializes the parser, reads any number of -// statements, and wraps them in a Program node. Optionally takes a -// `program` argument. If present, the statements will be appended -// to its body instead of creating a new node. - -pp$1.parseTopLevel = function(node) { - var this$1 = this; - - var exports = {}; - if (!node.body) { node.body = []; } - while (this.type !== types.eof) { - var stmt = this$1.parseStatement(true, true, exports); - node.body.push(stmt); - } - this.next(); - if (this.options.ecmaVersion >= 6) { - node.sourceType = this.options.sourceType; - } - return this.finishNode(node, "Program") -}; - -var loopLabel = {kind: "loop"}; -var switchLabel = {kind: "switch"}; - -pp$1.isLet = function() { - if (this.type !== types.name || this.options.ecmaVersion < 6 || this.value != "let") { return false } - skipWhiteSpace.lastIndex = this.pos; - var skip = skipWhiteSpace.exec(this.input); - var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); - if (nextCh === 91 || nextCh == 123) { return true } // '{' and '[' - if (isIdentifierStart(nextCh, true)) { - var pos = next + 1; - while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } - var ident = this.input.slice(next, pos); - if (!this.isKeyword(ident)) { return true } - } - return false -}; - -// check 'async [no LineTerminator here] function' -// - 'async /*foo*/ function' is OK. -// - 'async /*\n*/ function' is invalid. -pp$1.isAsyncFunction = function() { - if (this.type !== types.name || this.options.ecmaVersion < 8 || this.value != "async") - { return false } - - skipWhiteSpace.lastIndex = this.pos; - var skip = skipWhiteSpace.exec(this.input); - var next = this.pos + skip[0].length; - return !lineBreak.test(this.input.slice(this.pos, next)) && - this.input.slice(next, next + 8) === "function" && - (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) -}; - -// Parse a single statement. -// -// If expecting a statement and finding a slash operator, parse a -// regular expression literal. This is to handle cases like -// `if (foo) /blah/.exec(foo)`, where looking at the previous token -// does not help. - -pp$1.parseStatement = function(declaration, topLevel, exports) { - var starttype = this.type, node = this.startNode(), kind; - - if (this.isLet()) { - starttype = types._var; - kind = "let"; - } - - // Most types of statements are recognized by the keyword they - // start with. Many are trivial to parse, some require a bit of - // complexity. - - switch (starttype) { - case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) - case types._debugger: return this.parseDebuggerStatement(node) - case types._do: return this.parseDoStatement(node) - case types._for: return this.parseForStatement(node) - case types._function: - if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); } - return this.parseFunctionStatement(node, false) - case types._class: - if (!declaration) { this.unexpected(); } - return this.parseClass(node, true) - case types._if: return this.parseIfStatement(node) - case types._return: return this.parseReturnStatement(node) - case types._switch: return this.parseSwitchStatement(node) - case types._throw: return this.parseThrowStatement(node) - case types._try: return this.parseTryStatement(node) - case types._const: case types._var: - kind = kind || this.value; - if (!declaration && kind != "var") { this.unexpected(); } - return this.parseVarStatement(node, kind) - case types._while: return this.parseWhileStatement(node) - case types._with: return this.parseWithStatement(node) - case types.braceL: return this.parseBlock() - case types.semi: return this.parseEmptyStatement(node) - case types._export: - case types._import: - if (!this.options.allowImportExportEverywhere) { - if (!topLevel) - { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } - if (!this.inModule) - { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } - } - return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) - - // If the statement does not start with a statement keyword or a - // brace, it's an ExpressionStatement or LabeledStatement. We - // simply start parsing an expression, and afterwards, if the - // next token is a colon and the expression was a simple - // Identifier node, we switch to interpreting it as a label. - default: - if (this.isAsyncFunction() && declaration) { - this.next(); - return this.parseFunctionStatement(node, true) - } - - var maybeName = this.value, expr = this.parseExpression(); - if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) - { return this.parseLabeledStatement(node, maybeName, expr) } - else { return this.parseExpressionStatement(node, expr) } - } -}; - -pp$1.parseBreakContinueStatement = function(node, keyword) { - var this$1 = this; - - var isBreak = keyword == "break"; - this.next(); - if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } - else if (this.type !== types.name) { this.unexpected(); } - else { - node.label = this.parseIdent(); - this.semicolon(); - } - - // Verify that there is an actual destination to break or - // continue to. - var i = 0; - for (; i < this.labels.length; ++i) { - var lab = this$1.labels[i]; - if (node.label == null || lab.name === node.label.name) { - if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } - if (node.label && isBreak) { break } - } - } - if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } - return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") -}; - -pp$1.parseDebuggerStatement = function(node) { - this.next(); - this.semicolon(); - return this.finishNode(node, "DebuggerStatement") -}; - -pp$1.parseDoStatement = function(node) { - this.next(); - this.labels.push(loopLabel); - node.body = this.parseStatement(false); - this.labels.pop(); - this.expect(types._while); - node.test = this.parseParenExpression(); - if (this.options.ecmaVersion >= 6) - { this.eat(types.semi); } - else - { this.semicolon(); } - return this.finishNode(node, "DoWhileStatement") -}; - -// Disambiguating between a `for` and a `for`/`in` or `for`/`of` -// loop is non-trivial. Basically, we have to parse the init `var` -// statement or expression, disallowing the `in` operator (see -// the second parameter to `parseExpression`), and then check -// whether the next token is `in` or `of`. When there is no init -// part (semicolon immediately after the opening parenthesis), it -// is a regular `for` loop. - -pp$1.parseForStatement = function(node) { - this.next(); - this.labels.push(loopLabel); - this.enterLexicalScope(); - this.expect(types.parenL); - if (this.type === types.semi) { return this.parseFor(node, null) } - var isLet = this.isLet(); - if (this.type === types._var || this.type === types._const || isLet) { - var init$1 = this.startNode(), kind = isLet ? "let" : this.value; - this.next(); - this.parseVar(init$1, true, kind); - this.finishNode(init$1, "VariableDeclaration"); - if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 && - !(kind !== "var" && init$1.declarations[0].init)) - { return this.parseForIn(node, init$1) } - return this.parseFor(node, init$1) - } - var refDestructuringErrors = new DestructuringErrors; - var init = this.parseExpression(true, refDestructuringErrors); - if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { - this.toAssignable(init); - this.checkLVal(init); - this.checkPatternErrors(refDestructuringErrors, true); - return this.parseForIn(node, init) - } else { - this.checkExpressionErrors(refDestructuringErrors, true); - } - return this.parseFor(node, init) -}; - -pp$1.parseFunctionStatement = function(node, isAsync) { - this.next(); - return this.parseFunction(node, true, false, isAsync) -}; - -pp$1.isFunction = function() { - return this.type === types._function || this.isAsyncFunction() -}; - -pp$1.parseIfStatement = function(node) { - this.next(); - node.test = this.parseParenExpression(); - // allow function declarations in branches, but only in non-strict mode - node.consequent = this.parseStatement(!this.strict && this.isFunction()); - node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.isFunction()) : null; - return this.finishNode(node, "IfStatement") -}; - -pp$1.parseReturnStatement = function(node) { - if (!this.inFunction && !this.options.allowReturnOutsideFunction) - { this.raise(this.start, "'return' outside of function"); } - this.next(); - - // In `return` (and `break`/`continue`), the keywords with - // optional arguments, we eagerly look for a semicolon or the - // possibility to insert one. - - if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } - else { node.argument = this.parseExpression(); this.semicolon(); } - return this.finishNode(node, "ReturnStatement") -}; - -pp$1.parseSwitchStatement = function(node) { - var this$1 = this; - - this.next(); - node.discriminant = this.parseParenExpression(); - node.cases = []; - this.expect(types.braceL); - this.labels.push(switchLabel); - this.enterLexicalScope(); - - // Statements under must be grouped (by label) in SwitchCase - // nodes. `cur` is used to keep the node that we are currently - // adding statements to. - - var cur; - for (var sawDefault = false; this.type != types.braceR;) { - if (this$1.type === types._case || this$1.type === types._default) { - var isCase = this$1.type === types._case; - if (cur) { this$1.finishNode(cur, "SwitchCase"); } - node.cases.push(cur = this$1.startNode()); - cur.consequent = []; - this$1.next(); - if (isCase) { - cur.test = this$1.parseExpression(); - } else { - if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); } - sawDefault = true; - cur.test = null; - } - this$1.expect(types.colon); - } else { - if (!cur) { this$1.unexpected(); } - cur.consequent.push(this$1.parseStatement(true)); - } - } - this.exitLexicalScope(); - if (cur) { this.finishNode(cur, "SwitchCase"); } - this.next(); // Closing brace - this.labels.pop(); - return this.finishNode(node, "SwitchStatement") -}; - -pp$1.parseThrowStatement = function(node) { - this.next(); - if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) - { this.raise(this.lastTokEnd, "Illegal newline after throw"); } - node.argument = this.parseExpression(); - this.semicolon(); - return this.finishNode(node, "ThrowStatement") -}; - -// Reused empty array added for node fields that are always empty. - -var empty = []; - -pp$1.parseTryStatement = function(node) { - this.next(); - node.block = this.parseBlock(); - node.handler = null; - if (this.type === types._catch) { - var clause = this.startNode(); - this.next(); - this.expect(types.parenL); - clause.param = this.parseBindingAtom(); - this.enterLexicalScope(); - this.checkLVal(clause.param, "let"); - this.expect(types.parenR); - clause.body = this.parseBlock(false); - this.exitLexicalScope(); - node.handler = this.finishNode(clause, "CatchClause"); - } - node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; - if (!node.handler && !node.finalizer) - { this.raise(node.start, "Missing catch or finally clause"); } - return this.finishNode(node, "TryStatement") -}; - -pp$1.parseVarStatement = function(node, kind) { - this.next(); - this.parseVar(node, false, kind); - this.semicolon(); - return this.finishNode(node, "VariableDeclaration") -}; - -pp$1.parseWhileStatement = function(node) { - this.next(); - node.test = this.parseParenExpression(); - this.labels.push(loopLabel); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, "WhileStatement") -}; - -pp$1.parseWithStatement = function(node) { - if (this.strict) { this.raise(this.start, "'with' in strict mode"); } - this.next(); - node.object = this.parseParenExpression(); - node.body = this.parseStatement(false); - return this.finishNode(node, "WithStatement") -}; - -pp$1.parseEmptyStatement = function(node) { - this.next(); - return this.finishNode(node, "EmptyStatement") -}; - -pp$1.parseLabeledStatement = function(node, maybeName, expr) { - var this$1 = this; - - for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1) - { - var label = list[i$1]; - - if (label.name === maybeName) - { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared"); - } } - var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; - for (var i = this.labels.length - 1; i >= 0; i--) { - var label$1 = this$1.labels[i]; - if (label$1.statementStart == node.start) { - label$1.statementStart = this$1.start; - label$1.kind = kind; - } else { break } - } - this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); - node.body = this.parseStatement(true); - if (node.body.type == "ClassDeclaration" || - node.body.type == "VariableDeclaration" && node.body.kind != "var" || - node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) - { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); } - this.labels.pop(); - node.label = expr; - return this.finishNode(node, "LabeledStatement") -}; - -pp$1.parseExpressionStatement = function(node, expr) { - node.expression = expr; - this.semicolon(); - return this.finishNode(node, "ExpressionStatement") -}; - -// Parse a semicolon-enclosed block of statements, handling `"use -// strict"` declarations when `allowStrict` is true (used for -// function bodies). - -pp$1.parseBlock = function(createNewLexicalScope) { - var this$1 = this; - if ( createNewLexicalScope === void 0 ) { createNewLexicalScope = true; } - - var node = this.startNode(); - node.body = []; - this.expect(types.braceL); - if (createNewLexicalScope) { - this.enterLexicalScope(); - } - while (!this.eat(types.braceR)) { - var stmt = this$1.parseStatement(true); - node.body.push(stmt); - } - if (createNewLexicalScope) { - this.exitLexicalScope(); - } - return this.finishNode(node, "BlockStatement") -}; - -// Parse a regular `for` loop. The disambiguation code in -// `parseStatement` will already have parsed the init statement or -// expression. - -pp$1.parseFor = function(node, init) { - node.init = init; - this.expect(types.semi); - node.test = this.type === types.semi ? null : this.parseExpression(); - this.expect(types.semi); - node.update = this.type === types.parenR ? null : this.parseExpression(); - this.expect(types.parenR); - this.exitLexicalScope(); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, "ForStatement") -}; - -// Parse a `for`/`in` and `for`/`of` loop, which are almost -// same from parser's perspective. - -pp$1.parseForIn = function(node, init) { - var type = this.type === types._in ? "ForInStatement" : "ForOfStatement"; - this.next(); - node.left = init; - node.right = this.parseExpression(); - this.expect(types.parenR); - this.exitLexicalScope(); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, type) -}; - -// Parse a list of variable declarations. - -pp$1.parseVar = function(node, isFor, kind) { - var this$1 = this; - - node.declarations = []; - node.kind = kind; - for (;;) { - var decl = this$1.startNode(); - this$1.parseVarId(decl, kind); - if (this$1.eat(types.eq)) { - decl.init = this$1.parseMaybeAssign(isFor); - } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { - this$1.unexpected(); - } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) { - this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value"); - } else { - decl.init = null; - } - node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); - if (!this$1.eat(types.comma)) { break } - } - return node -}; - -pp$1.parseVarId = function(decl, kind) { - decl.id = this.parseBindingAtom(kind); - this.checkLVal(decl.id, kind, false); -}; - -// Parse a function declaration or literal (depending on the -// `isStatement` parameter). - -pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { - this.initFunction(node); - if (this.options.ecmaVersion >= 6 && !isAsync) - { node.generator = this.eat(types.star); } - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - - if (isStatement) { - node.id = isStatement === "nullableID" && this.type != types.name ? null : this.parseIdent(); - if (node.id) { - this.checkLVal(node.id, "var"); - } - } - - var oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; - this.inGenerator = node.generator; - this.inAsync = node.async; - this.yieldPos = 0; - this.awaitPos = 0; - this.inFunction = true; - this.enterFunctionScope(); - - if (!isStatement) - { node.id = this.type == types.name ? this.parseIdent() : null; } - - this.parseFunctionParams(node); - this.parseFunctionBody(node, allowExpressionBody); - - this.inGenerator = oldInGen; - this.inAsync = oldInAsync; - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - this.inFunction = oldInFunc; - return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") -}; - -pp$1.parseFunctionParams = function(node) { - this.expect(types.parenL); - node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); - this.checkYieldAwaitInDefaultParams(); -}; - -// Parse a class declaration or literal (depending on the -// `isStatement` parameter). - -pp$1.parseClass = function(node, isStatement) { - var this$1 = this; - - this.next(); - - this.parseClassId(node, isStatement); - this.parseClassSuper(node); - var classBody = this.startNode(); - var hadConstructor = false; - classBody.body = []; - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - if (this$1.eat(types.semi)) { continue } - var method = this$1.startNode(); - var isGenerator = this$1.eat(types.star); - var isAsync = false; - var isMaybeStatic = this$1.type === types.name && this$1.value === "static"; - this$1.parsePropertyName(method); - method.static = isMaybeStatic && this$1.type !== types.parenL; - if (method.static) { - if (isGenerator) { this$1.unexpected(); } - isGenerator = this$1.eat(types.star); - this$1.parsePropertyName(method); - } - if (this$1.options.ecmaVersion >= 8 && !isGenerator && !method.computed && - method.key.type === "Identifier" && method.key.name === "async" && this$1.type !== types.parenL && - !this$1.canInsertSemicolon()) { - isAsync = true; - this$1.parsePropertyName(method); - } - method.kind = "method"; - var isGetSet = false; - if (!method.computed) { - var key = method.key; - if (!isGenerator && !isAsync && key.type === "Identifier" && this$1.type !== types.parenL && (key.name === "get" || key.name === "set")) { - isGetSet = true; - method.kind = key.name; - key = this$1.parsePropertyName(method); - } - if (!method.static && (key.type === "Identifier" && key.name === "constructor" || - key.type === "Literal" && key.value === "constructor")) { - if (hadConstructor) { this$1.raise(key.start, "Duplicate constructor in the same class"); } - if (isGetSet) { this$1.raise(key.start, "Constructor can't have get/set modifier"); } - if (isGenerator) { this$1.raise(key.start, "Constructor can't be a generator"); } - if (isAsync) { this$1.raise(key.start, "Constructor can't be an async method"); } - method.kind = "constructor"; - hadConstructor = true; - } - } - this$1.parseClassMethod(classBody, method, isGenerator, isAsync); - if (isGetSet) { - var paramCount = method.kind === "get" ? 0 : 1; - if (method.value.params.length !== paramCount) { - var start = method.value.start; - if (method.kind === "get") - { this$1.raiseRecoverable(start, "getter should have no params"); } - else - { this$1.raiseRecoverable(start, "setter should have exactly one param"); } - } else { - if (method.kind === "set" && method.value.params[0].type === "RestElement") - { this$1.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } - } - } - } - node.body = this.finishNode(classBody, "ClassBody"); - return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") -}; - -pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) { - method.value = this.parseMethod(isGenerator, isAsync); - classBody.body.push(this.finishNode(method, "MethodDefinition")); -}; - -pp$1.parseClassId = function(node, isStatement) { - node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null; -}; - -pp$1.parseClassSuper = function(node) { - node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; -}; - -// Parses module export declaration. - -pp$1.parseExport = function(node, exports) { - var this$1 = this; - - this.next(); - // export * from '...' - if (this.eat(types.star)) { - this.expectContextual("from"); - node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); - this.semicolon(); - return this.finishNode(node, "ExportAllDeclaration") - } - if (this.eat(types._default)) { // export default ... - this.checkExport(exports, "default", this.lastTokStart); - var isAsync; - if (this.type === types._function || (isAsync = this.isAsyncFunction())) { - var fNode = this.startNode(); - this.next(); - if (isAsync) { this.next(); } - node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync); - } else if (this.type === types._class) { - var cNode = this.startNode(); - node.declaration = this.parseClass(cNode, "nullableID"); - } else { - node.declaration = this.parseMaybeAssign(); - this.semicolon(); - } - return this.finishNode(node, "ExportDefaultDeclaration") - } - // export var|const|let|function|class ... - if (this.shouldParseExportStatement()) { - node.declaration = this.parseStatement(true); - if (node.declaration.type === "VariableDeclaration") - { this.checkVariableExport(exports, node.declaration.declarations); } - else - { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } - node.specifiers = []; - node.source = null; - } else { // export { x, y as z } [from '...'] - node.declaration = null; - node.specifiers = this.parseExportSpecifiers(exports); - if (this.eatContextual("from")) { - node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); - } else { - // check for keywords used as local names - for (var i = 0, list = node.specifiers; i < list.length; i += 1) { - var spec = list[i]; - - this$1.checkUnreserved(spec.local); - } - - node.source = null; - } - this.semicolon(); - } - return this.finishNode(node, "ExportNamedDeclaration") -}; - -pp$1.checkExport = function(exports, name, pos) { - if (!exports) { return } - if (has(exports, name)) - { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } - exports[name] = true; -}; - -pp$1.checkPatternExport = function(exports, pat) { - var this$1 = this; - - var type = pat.type; - if (type == "Identifier") - { this.checkExport(exports, pat.name, pat.start); } - else if (type == "ObjectPattern") - { for (var i = 0, list = pat.properties; i < list.length; i += 1) - { - var prop = list[i]; - - this$1.checkPatternExport(exports, prop.value); - } } - else if (type == "ArrayPattern") - { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { - var elt = list$1[i$1]; - - if (elt) { this$1.checkPatternExport(exports, elt); } - } } - else if (type == "AssignmentPattern") - { this.checkPatternExport(exports, pat.left); } - else if (type == "ParenthesizedExpression") - { this.checkPatternExport(exports, pat.expression); } -}; - -pp$1.checkVariableExport = function(exports, decls) { - var this$1 = this; - - if (!exports) { return } - for (var i = 0, list = decls; i < list.length; i += 1) - { - var decl = list[i]; - - this$1.checkPatternExport(exports, decl.id); - } -}; - -pp$1.shouldParseExportStatement = function() { - return this.type.keyword === "var" || - this.type.keyword === "const" || - this.type.keyword === "class" || - this.type.keyword === "function" || - this.isLet() || - this.isAsyncFunction() -}; - -// Parses a comma-separated list of module exports. - -pp$1.parseExportSpecifiers = function(exports) { - var this$1 = this; - - var nodes = [], first = true; - // export { x, y as z } [from '...'] - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var node = this$1.startNode(); - node.local = this$1.parseIdent(true); - node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local; - this$1.checkExport(exports, node.exported.name, node.exported.start); - nodes.push(this$1.finishNode(node, "ExportSpecifier")); - } - return nodes -}; - -// Parses import declaration. - -pp$1.parseImport = function(node) { - this.next(); - // import '...' - if (this.type === types.string) { - node.specifiers = empty; - node.source = this.parseExprAtom(); - } else { - node.specifiers = this.parseImportSpecifiers(); - this.expectContextual("from"); - node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); - } - this.semicolon(); - return this.finishNode(node, "ImportDeclaration") -}; - -// Parses a comma-separated list of module imports. - -pp$1.parseImportSpecifiers = function() { - var this$1 = this; - - var nodes = [], first = true; - if (this.type === types.name) { - // import defaultObj, { x, y as z } from '...' - var node = this.startNode(); - node.local = this.parseIdent(); - this.checkLVal(node.local, "let"); - nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); - if (!this.eat(types.comma)) { return nodes } - } - if (this.type === types.star) { - var node$1 = this.startNode(); - this.next(); - this.expectContextual("as"); - node$1.local = this.parseIdent(); - this.checkLVal(node$1.local, "let"); - nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); - return nodes - } - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var node$2 = this$1.startNode(); - node$2.imported = this$1.parseIdent(true); - if (this$1.eatContextual("as")) { - node$2.local = this$1.parseIdent(); - } else { - this$1.checkUnreserved(node$2.imported); - node$2.local = node$2.imported; - } - this$1.checkLVal(node$2.local, "let"); - nodes.push(this$1.finishNode(node$2, "ImportSpecifier")); - } - return nodes -}; - -var pp$2 = Parser.prototype; - -// Convert existing expression atom to assignable pattern -// if possible. - -pp$2.toAssignable = function(node, isBinding) { - var this$1 = this; - - if (this.options.ecmaVersion >= 6 && node) { - switch (node.type) { - case "Identifier": - if (this.inAsync && node.name === "await") - { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); } - break - - case "ObjectPattern": - case "ArrayPattern": - break - - case "ObjectExpression": - node.type = "ObjectPattern"; - for (var i = 0, list = node.properties; i < list.length; i += 1) { - var prop = list[i]; - - if (prop.kind !== "init") { this$1.raise(prop.key.start, "Object pattern can't contain getter or setter"); } - this$1.toAssignable(prop.value, isBinding); - } - break - - case "ArrayExpression": - node.type = "ArrayPattern"; - this.toAssignableList(node.elements, isBinding); - break - - case "AssignmentExpression": - if (node.operator === "=") { - node.type = "AssignmentPattern"; - delete node.operator; - this.toAssignable(node.left, isBinding); - // falls through to AssignmentPattern - } else { - this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); - break - } - - case "AssignmentPattern": - break - - case "ParenthesizedExpression": - this.toAssignable(node.expression, isBinding); - break - - case "MemberExpression": - if (!isBinding) { break } - - default: - this.raise(node.start, "Assigning to rvalue"); - } - } - return node -}; - -// Convert list of expression atoms to binding list. - -pp$2.toAssignableList = function(exprList, isBinding) { - var this$1 = this; - - var end = exprList.length; - if (end) { - var last = exprList[end - 1]; - if (last && last.type == "RestElement") { - --end; - } else if (last && last.type == "SpreadElement") { - last.type = "RestElement"; - var arg = last.argument; - this.toAssignable(arg, isBinding); - --end; - } - - if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") - { this.unexpected(last.argument.start); } - } - for (var i = 0; i < end; i++) { - var elt = exprList[i]; - if (elt) { this$1.toAssignable(elt, isBinding); } - } - return exprList -}; - -// Parses spread element. - -pp$2.parseSpread = function(refDestructuringErrors) { - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeAssign(false, refDestructuringErrors); - return this.finishNode(node, "SpreadElement") -}; - -pp$2.parseRestBinding = function() { - var node = this.startNode(); - this.next(); - - // RestElement inside of a function parameter must be an identifier - if (this.options.ecmaVersion === 6 && this.type !== types.name) - { this.unexpected(); } - - node.argument = this.parseBindingAtom(); - - return this.finishNode(node, "RestElement") -}; - -// Parses lvalue (assignable) atom. - -pp$2.parseBindingAtom = function() { - if (this.options.ecmaVersion < 6) { return this.parseIdent() } - switch (this.type) { - case types.name: - return this.parseIdent() - - case types.bracketL: - var node = this.startNode(); - this.next(); - node.elements = this.parseBindingList(types.bracketR, true, true); - return this.finishNode(node, "ArrayPattern") - - case types.braceL: - return this.parseObj(true) - - default: - this.unexpected(); - } -}; - -pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { - var this$1 = this; - - var elts = [], first = true; - while (!this.eat(close)) { - if (first) { first = false; } - else { this$1.expect(types.comma); } - if (allowEmpty && this$1.type === types.comma) { - elts.push(null); - } else if (allowTrailingComma && this$1.afterTrailingComma(close)) { - break - } else if (this$1.type === types.ellipsis) { - var rest = this$1.parseRestBinding(); - this$1.parseBindingListItem(rest); - elts.push(rest); - if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } - this$1.expect(close); - break - } else { - var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc); - this$1.parseBindingListItem(elem); - elts.push(elem); - } - } - return elts -}; - -pp$2.parseBindingListItem = function(param) { - return param -}; - -// Parses assignment pattern around given atom if possible. - -pp$2.parseMaybeDefault = function(startPos, startLoc, left) { - left = left || this.parseBindingAtom(); - if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left } - var node = this.startNodeAt(startPos, startLoc); - node.left = left; - node.right = this.parseMaybeAssign(); - return this.finishNode(node, "AssignmentPattern") -}; - -// Verify that a node is an lval — something that can be assigned -// to. -// bindingType can be either: -// 'var' indicating that the lval creates a 'var' binding -// 'let' indicating that the lval creates a lexical ('let' or 'const') binding -// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references - -pp$2.checkLVal = function(expr, bindingType, checkClashes) { - var this$1 = this; - - switch (expr.type) { - case "Identifier": - if (this.strict && this.reservedWordsStrictBind.test(expr.name)) - { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } - if (checkClashes) { - if (has(checkClashes, expr.name)) - { this.raiseRecoverable(expr.start, "Argument name clash"); } - checkClashes[expr.name] = true; - } - if (bindingType && bindingType !== "none") { - if ( - bindingType === "var" && !this.canDeclareVarName(expr.name) || - bindingType !== "var" && !this.canDeclareLexicalName(expr.name) - ) { - this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared")); - } - if (bindingType === "var") { - this.declareVarName(expr.name); - } else { - this.declareLexicalName(expr.name); - } - } - break - - case "MemberExpression": - if (bindingType) { this.raiseRecoverable(expr.start, (bindingType ? "Binding" : "Assigning to") + " member expression"); } - break - - case "ObjectPattern": - for (var i = 0, list = expr.properties; i < list.length; i += 1) - { - var prop = list[i]; - - this$1.checkLVal(prop.value, bindingType, checkClashes); - } - break - - case "ArrayPattern": - for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { - var elem = list$1[i$1]; - - if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); } - } - break - - case "AssignmentPattern": - this.checkLVal(expr.left, bindingType, checkClashes); - break - - case "RestElement": - this.checkLVal(expr.argument, bindingType, checkClashes); - break - - case "ParenthesizedExpression": - this.checkLVal(expr.expression, bindingType, checkClashes); - break - - default: - this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); - } -}; - -// A recursive descent parser operates by defining functions for all -// syntactic elements, and recursively calling those, each function -// advancing the input stream and returning an AST node. Precedence -// of constructs (for example, the fact that `!x[1]` means `!(x[1])` -// instead of `(!x)[1]` is handled by the fact that the parser -// function that parses unary prefix operators is called first, and -// in turn calls the function that parses `[]` subscripts — that -// way, it'll receive the node for `x[1]` already parsed, and wraps -// *that* in the unary operator node. -// -// Acorn uses an [operator precedence parser][opp] to handle binary -// operator precedence, because it is much more compact than using -// the technique outlined above, which uses different, nesting -// functions to specify precedence, for all of the ten binary -// precedence levels that JavaScript defines. -// -// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser - -var pp$3 = Parser.prototype; - -// Check if property name clashes with already added. -// Object/class getters and setters are not allowed to clash — -// either with each other or with an init property — and in -// strict mode, init properties are also not allowed to be repeated. - -pp$3.checkPropClash = function(prop, propHash) { - if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) - { return } - var key = prop.key; - var name; - switch (key.type) { - case "Identifier": name = key.name; break - case "Literal": name = String(key.value); break - default: return - } - var kind = prop.kind; - if (this.options.ecmaVersion >= 6) { - if (name === "__proto__" && kind === "init") { - if (propHash.proto) { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } - propHash.proto = true; - } - return - } - name = "$" + name; - var other = propHash[name]; - if (other) { - var redefinition; - if (kind === "init") { - redefinition = this.strict && other.init || other.get || other.set; - } else { - redefinition = other.init || other[kind]; - } - if (redefinition) - { this.raiseRecoverable(key.start, "Redefinition of property"); } - } else { - other = propHash[name] = { - init: false, - get: false, - set: false - }; - } - other[kind] = true; -}; - -// ### Expression parsing - -// These nest, from the most general expression type at the top to -// 'atomic', nondivisible expression types at the bottom. Most of -// the functions will simply let the function(s) below them parse, -// and, *if* the syntactic construct they handle is present, wrap -// the AST node that the inner parser gave them in another node. - -// Parse a full expression. The optional arguments are used to -// forbid the `in` operator (in for loops initalization expressions) -// and provide reference for storing '=' operator inside shorthand -// property assignment in contexts where both object expression -// and object pattern might appear (so it's possible to raise -// delayed syntax error at correct position). - -pp$3.parseExpression = function(noIn, refDestructuringErrors) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); - if (this.type === types.comma) { - var node = this.startNodeAt(startPos, startLoc); - node.expressions = [expr]; - while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); } - return this.finishNode(node, "SequenceExpression") - } - return expr -}; - -// Parse an assignment expression. This includes applications of -// operators like `+=`. - -pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { - if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() } - - var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1; - if (refDestructuringErrors) { - oldParenAssign = refDestructuringErrors.parenthesizedAssign; - oldTrailingComma = refDestructuringErrors.trailingComma; - refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; - } else { - refDestructuringErrors = new DestructuringErrors; - ownDestructuringErrors = true; - } - - var startPos = this.start, startLoc = this.startLoc; - if (this.type == types.parenL || this.type == types.name) - { this.potentialArrowAt = this.start; } - var left = this.parseMaybeConditional(noIn, refDestructuringErrors); - if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } - if (this.type.isAssign) { - this.checkPatternErrors(refDestructuringErrors, true); - if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); } - var node = this.startNodeAt(startPos, startLoc); - node.operator = this.value; - node.left = this.type === types.eq ? this.toAssignable(left) : left; - refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly - this.checkLVal(left); - this.next(); - node.right = this.parseMaybeAssign(noIn); - return this.finishNode(node, "AssignmentExpression") - } else { - if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } - } - if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } - if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } - return left -}; - -// Parse a ternary conditional (`?:`) operator. - -pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprOps(noIn, refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - if (this.eat(types.question)) { - var node = this.startNodeAt(startPos, startLoc); - node.test = expr; - node.consequent = this.parseMaybeAssign(); - this.expect(types.colon); - node.alternate = this.parseMaybeAssign(noIn); - return this.finishNode(node, "ConditionalExpression") - } - return expr -}; - -// Start the precedence parser. - -pp$3.parseExprOps = function(noIn, refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseMaybeUnary(refDestructuringErrors, false); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) -}; - -// Parse binary operators with the operator precedence parsing -// algorithm. `left` is the left-hand side of the operator. -// `minPrec` provides context that allows the function to stop and -// defer further parser to one of its callers when it encounters an -// operator that has a lower precedence than the set it is parsing. - -pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { - var prec = this.type.binop; - if (prec != null && (!noIn || this.type !== types._in)) { - if (prec > minPrec) { - var logical = this.type === types.logicalOR || this.type === types.logicalAND; - var op = this.value; - this.next(); - var startPos = this.start, startLoc = this.startLoc; - var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); - var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); - return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) - } - } - return left -}; - -pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { - var node = this.startNodeAt(startPos, startLoc); - node.left = left; - node.operator = op; - node.right = right; - return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") -}; - -// Parse unary operators, both prefix and postfix. - -pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc, expr; - if (this.inAsync && this.isContextual("await")) { - expr = this.parseAwait(refDestructuringErrors); - sawUnary = true; - } else if (this.type.prefix) { - var node = this.startNode(), update = this.type === types.incDec; - node.operator = this.value; - node.prefix = true; - this.next(); - node.argument = this.parseMaybeUnary(null, true); - this.checkExpressionErrors(refDestructuringErrors, true); - if (update) { this.checkLVal(node.argument); } - else if (this.strict && node.operator === "delete" && - node.argument.type === "Identifier") - { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } - else { sawUnary = true; } - expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); - } else { - expr = this.parseExprSubscripts(refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - while (this.type.postfix && !this.canInsertSemicolon()) { - var node$1 = this$1.startNodeAt(startPos, startLoc); - node$1.operator = this$1.value; - node$1.prefix = false; - node$1.argument = expr; - this$1.checkLVal(expr); - this$1.next(); - expr = this$1.finishNode(node$1, "UpdateExpression"); - } - } - - if (!sawUnary && this.eat(types.starstar)) - { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } - else - { return expr } -}; - -// Parse call, dot, and `[]`-subscript expressions. - -pp$3.parseExprSubscripts = function(refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprAtom(refDestructuringErrors); - var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; - if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr } - var result = this.parseSubscripts(expr, startPos, startLoc); - if (refDestructuringErrors && result.type === "MemberExpression") { - if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } - if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } - } - return result -}; - -pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { - var this$1 = this; - - var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && - this.lastTokEnd == base.end && !this.canInsertSemicolon(); - for (var computed = (void 0);;) { - if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) { - var node = this$1.startNodeAt(startPos, startLoc); - node.object = base; - node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true); - node.computed = !!computed; - if (computed) { this$1.expect(types.bracketR); } - base = this$1.finishNode(node, "MemberExpression"); - } else if (!noCalls && this$1.eat(types.parenL)) { - var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos; - this$1.yieldPos = 0; - this$1.awaitPos = 0; - var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors); - if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) { - this$1.checkPatternErrors(refDestructuringErrors, false); - this$1.checkYieldAwaitInDefaultParams(); - this$1.yieldPos = oldYieldPos; - this$1.awaitPos = oldAwaitPos; - return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true) - } - this$1.checkExpressionErrors(refDestructuringErrors, true); - this$1.yieldPos = oldYieldPos || this$1.yieldPos; - this$1.awaitPos = oldAwaitPos || this$1.awaitPos; - var node$1 = this$1.startNodeAt(startPos, startLoc); - node$1.callee = base; - node$1.arguments = exprList; - base = this$1.finishNode(node$1, "CallExpression"); - } else if (this$1.type === types.backQuote) { - var node$2 = this$1.startNodeAt(startPos, startLoc); - node$2.tag = base; - node$2.quasi = this$1.parseTemplate({isTagged: true}); - base = this$1.finishNode(node$2, "TaggedTemplateExpression"); - } else { - return base - } - } -}; - -// Parse an atomic expression — either a single token that is an -// expression, an expression started by a keyword like `function` or -// `new`, or an expression wrapped in punctuation like `()`, `[]`, -// or `{}`. - -pp$3.parseExprAtom = function(refDestructuringErrors) { - var node, canBeArrow = this.potentialArrowAt == this.start; - switch (this.type) { - case types._super: - if (!this.inFunction) - { this.raise(this.start, "'super' outside of function or class"); } - - case types._this: - var type = this.type === types._this ? "ThisExpression" : "Super"; - node = this.startNode(); - this.next(); - return this.finishNode(node, type) - - case types.name: - var startPos = this.start, startLoc = this.startLoc; - var id = this.parseIdent(this.type !== types.name); - if (this.options.ecmaVersion >= 8 && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) - { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) } - if (canBeArrow && !this.canInsertSemicolon()) { - if (this.eat(types.arrow)) - { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } - if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name) { - id = this.parseIdent(); - if (this.canInsertSemicolon() || !this.eat(types.arrow)) - { this.unexpected(); } - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) - } - } - return id - - case types.regexp: - var value = this.value; - node = this.parseLiteral(value.value); - node.regex = {pattern: value.pattern, flags: value.flags}; - return node - - case types.num: case types.string: - return this.parseLiteral(this.value) - - case types._null: case types._true: case types._false: - node = this.startNode(); - node.value = this.type === types._null ? null : this.type === types._true; - node.raw = this.type.keyword; - this.next(); - return this.finishNode(node, "Literal") - - case types.parenL: - var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); - if (refDestructuringErrors) { - if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) - { refDestructuringErrors.parenthesizedAssign = start; } - if (refDestructuringErrors.parenthesizedBind < 0) - { refDestructuringErrors.parenthesizedBind = start; } - } - return expr - - case types.bracketL: - node = this.startNode(); - this.next(); - node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); - return this.finishNode(node, "ArrayExpression") - - case types.braceL: - return this.parseObj(false, refDestructuringErrors) - - case types._function: - node = this.startNode(); - this.next(); - return this.parseFunction(node, false) - - case types._class: - return this.parseClass(this.startNode(), false) - - case types._new: - return this.parseNew() - - case types.backQuote: - return this.parseTemplate() - - default: - this.unexpected(); - } -}; - -pp$3.parseLiteral = function(value) { - var node = this.startNode(); - node.value = value; - node.raw = this.input.slice(this.start, this.end); - this.next(); - return this.finishNode(node, "Literal") -}; - -pp$3.parseParenExpression = function() { - this.expect(types.parenL); - var val = this.parseExpression(); - this.expect(types.parenR); - return val -}; - -pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; - if (this.options.ecmaVersion >= 6) { - this.next(); - - var innerStartPos = this.start, innerStartLoc = this.startLoc; - var exprList = [], first = true, lastIsComma = false; - var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart, innerParenStart; - this.yieldPos = 0; - this.awaitPos = 0; - while (this.type !== types.parenR) { - first ? first = false : this$1.expect(types.comma); - if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) { - lastIsComma = true; - break - } else if (this$1.type === types.ellipsis) { - spreadStart = this$1.start; - exprList.push(this$1.parseParenItem(this$1.parseRestBinding())); - if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } - break - } else { - if (this$1.type === types.parenL && !innerParenStart) { - innerParenStart = this$1.start; - } - exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem)); - } - } - var innerEndPos = this.start, innerEndLoc = this.startLoc; - this.expect(types.parenR); - - if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { - this.checkPatternErrors(refDestructuringErrors, false); - this.checkYieldAwaitInDefaultParams(); - if (innerParenStart) { this.unexpected(innerParenStart); } - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - return this.parseParenArrowList(startPos, startLoc, exprList) - } - - if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } - if (spreadStart) { this.unexpected(spreadStart); } - this.checkExpressionErrors(refDestructuringErrors, true); - this.yieldPos = oldYieldPos || this.yieldPos; - this.awaitPos = oldAwaitPos || this.awaitPos; - - if (exprList.length > 1) { - val = this.startNodeAt(innerStartPos, innerStartLoc); - val.expressions = exprList; - this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); - } else { - val = exprList[0]; - } - } else { - val = this.parseParenExpression(); - } - - if (this.options.preserveParens) { - var par = this.startNodeAt(startPos, startLoc); - par.expression = val; - return this.finishNode(par, "ParenthesizedExpression") - } else { - return val - } -}; - -pp$3.parseParenItem = function(item) { - return item -}; - -pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) -}; - -// New's precedence is slightly tricky. It must allow its argument to -// be a `[]` or dot subscript expression, but not a call — at least, -// not without wrapping it in parentheses. Thus, it uses the noCalls -// argument to parseSubscripts to prevent it from consuming the -// argument list. - -var empty$1 = []; - -pp$3.parseNew = function() { - var node = this.startNode(); - var meta = this.parseIdent(true); - if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { - node.meta = meta; - node.property = this.parseIdent(true); - if (node.property.name !== "target") - { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); } - if (!this.inFunction) - { this.raiseRecoverable(node.start, "new.target can only be used in functions"); } - return this.finishNode(node, "MetaProperty") - } - var startPos = this.start, startLoc = this.startLoc; - node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); - if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } - else { node.arguments = empty$1; } - return this.finishNode(node, "NewExpression") -}; - -// Parse template expression. - -pp$3.parseTemplateElement = function(ref) { - var isTagged = ref.isTagged; - - var elem = this.startNode(); - if (this.type === types.invalidTemplate) { - if (!isTagged) { - this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); - } - elem.value = { - raw: this.value, - cooked: null - }; - } else { - elem.value = { - raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), - cooked: this.value - }; - } - this.next(); - elem.tail = this.type === types.backQuote; - return this.finishNode(elem, "TemplateElement") -}; - -pp$3.parseTemplate = function(ref) { - var this$1 = this; - if ( ref === void 0 ) { ref = {}; } - var isTagged = ref.isTagged; if ( isTagged === void 0 ) { isTagged = false; } - - var node = this.startNode(); - this.next(); - node.expressions = []; - var curElt = this.parseTemplateElement({isTagged: isTagged}); - node.quasis = [curElt]; - while (!curElt.tail) { - this$1.expect(types.dollarBraceL); - node.expressions.push(this$1.parseExpression()); - this$1.expect(types.braceR); - node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged})); - } - this.next(); - return this.finishNode(node, "TemplateLiteral") -}; - -// Parse an object literal or binding pattern. - -pp$3.isAsyncProp = function(prop) { - return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && - (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword) && - !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) -}; - -pp$3.parseObj = function(isPattern, refDestructuringErrors) { - var this$1 = this; - - var node = this.startNode(), first = true, propHash = {}; - node.properties = []; - this.next(); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var prop = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0), startPos = (void 0), startLoc = (void 0); - if (this$1.options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - if (isPattern || refDestructuringErrors) { - startPos = this$1.start; - startLoc = this$1.startLoc; - } - if (!isPattern) - { isGenerator = this$1.eat(types.star); } - } - this$1.parsePropertyName(prop); - if (!isPattern && this$1.options.ecmaVersion >= 8 && !isGenerator && this$1.isAsyncProp(prop)) { - isAsync = true; - this$1.parsePropertyName(prop, refDestructuringErrors); - } else { - isAsync = false; - } - this$1.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors); - this$1.checkPropClash(prop, propHash); - node.properties.push(this$1.finishNode(prop, "Property")); - } - return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") -}; - -pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors) { - if ((isGenerator || isAsync) && this.type === types.colon) - { this.unexpected(); } - - if (this.eat(types.colon)) { - prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); - prop.kind = "init"; - } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) { - if (isPattern) { this.unexpected(); } - prop.kind = "init"; - prop.method = true; - prop.value = this.parseMethod(isGenerator, isAsync); - } else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && - (prop.key.name === "get" || prop.key.name === "set") && - (this.type != types.comma && this.type != types.braceR)) { - if (isGenerator || isAsync || isPattern) { this.unexpected(); } - prop.kind = prop.key.name; - this.parsePropertyName(prop); - prop.value = this.parseMethod(false); - var paramCount = prop.kind === "get" ? 0 : 1; - if (prop.value.params.length !== paramCount) { - var start = prop.value.start; - if (prop.kind === "get") - { this.raiseRecoverable(start, "getter should have no params"); } - else - { this.raiseRecoverable(start, "setter should have exactly one param"); } - } else { - if (prop.kind === "set" && prop.value.params[0].type === "RestElement") - { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } - } - } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { - this.checkUnreserved(prop.key); - prop.kind = "init"; - if (isPattern) { - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else if (this.type === types.eq && refDestructuringErrors) { - if (refDestructuringErrors.shorthandAssign < 0) - { refDestructuringErrors.shorthandAssign = this.start; } - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else { - prop.value = prop.key; - } - prop.shorthand = true; - } else { this.unexpected(); } -}; - -pp$3.parsePropertyName = function(prop) { - if (this.options.ecmaVersion >= 6) { - if (this.eat(types.bracketL)) { - prop.computed = true; - prop.key = this.parseMaybeAssign(); - this.expect(types.bracketR); - return prop.key - } else { - prop.computed = false; - } - } - return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true) -}; - -// Initialize empty function node. - -pp$3.initFunction = function(node) { - node.id = null; - if (this.options.ecmaVersion >= 6) { - node.generator = false; - node.expression = false; - } - if (this.options.ecmaVersion >= 8) - { node.async = false; } -}; - -// Parse object or class method. - -pp$3.parseMethod = function(isGenerator, isAsync) { - var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; - - this.initFunction(node); - if (this.options.ecmaVersion >= 6) - { node.generator = isGenerator; } - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - - this.inGenerator = node.generator; - this.inAsync = node.async; - this.yieldPos = 0; - this.awaitPos = 0; - this.inFunction = true; - this.enterFunctionScope(); - - this.expect(types.parenL); - node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); - this.checkYieldAwaitInDefaultParams(); - this.parseFunctionBody(node, false); - - this.inGenerator = oldInGen; - this.inAsync = oldInAsync; - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - this.inFunction = oldInFunc; - return this.finishNode(node, "FunctionExpression") -}; - -// Parse arrow function expression with given parameters. - -pp$3.parseArrowExpression = function(node, params, isAsync) { - var oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; - - this.enterFunctionScope(); - this.initFunction(node); - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - - this.inGenerator = false; - this.inAsync = node.async; - this.yieldPos = 0; - this.awaitPos = 0; - this.inFunction = true; - - node.params = this.toAssignableList(params, true); - this.parseFunctionBody(node, true); - - this.inGenerator = oldInGen; - this.inAsync = oldInAsync; - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - this.inFunction = oldInFunc; - return this.finishNode(node, "ArrowFunctionExpression") -}; - -// Parse function body and check parameters. - -pp$3.parseFunctionBody = function(node, isArrowFunction) { - var isExpression = isArrowFunction && this.type !== types.braceL; - var oldStrict = this.strict, useStrict = false; - - if (isExpression) { - node.body = this.parseMaybeAssign(); - node.expression = true; - this.checkParams(node, false); - } else { - var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); - if (!oldStrict || nonSimple) { - useStrict = this.strictDirective(this.end); - // If this is a strict mode function, verify that argument names - // are not repeated, and it does not try to bind the words `eval` - // or `arguments`. - if (useStrict && nonSimple) - { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } - } - // Start a new scope with regard to labels and the `inFunction` - // flag (restore them to their old value afterwards). - var oldLabels = this.labels; - this.labels = []; - if (useStrict) { this.strict = true; } - - // Add the params to varDeclaredNames to ensure that an error is thrown - // if a let/const declaration in the function clashes with one of the params. - this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)); - node.body = this.parseBlock(false); - node.expression = false; - this.labels = oldLabels; - } - this.exitFunctionScope(); - - if (this.strict && node.id) { - // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' - this.checkLVal(node.id, "none"); - } - this.strict = oldStrict; -}; - -pp$3.isSimpleParamList = function(params) { - for (var i = 0, list = params; i < list.length; i += 1) - { - var param = list[i]; - - if (param.type !== "Identifier") { return false - } } - return true -}; - -// Checks function params for various disallowed patterns such as using "eval" -// or "arguments" and duplicate parameters. - -pp$3.checkParams = function(node, allowDuplicates) { - var this$1 = this; - - var nameHash = {}; - for (var i = 0, list = node.params; i < list.length; i += 1) - { - var param = list[i]; - - this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash); - } -}; - -// Parses a comma-separated list of expressions, and returns them as -// an array. `close` is the token type that ends the list, and -// `allowEmpty` can be turned on to allow subsequent commas with -// nothing in between them to be parsed as `null` (which is needed -// for array literals). - -pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { - var this$1 = this; - - var elts = [], first = true; - while (!this.eat(close)) { - if (!first) { - this$1.expect(types.comma); - if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } - } else { first = false; } - - var elt = (void 0); - if (allowEmpty && this$1.type === types.comma) - { elt = null; } - else if (this$1.type === types.ellipsis) { - elt = this$1.parseSpread(refDestructuringErrors); - if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0) - { refDestructuringErrors.trailingComma = this$1.start; } - } else { - elt = this$1.parseMaybeAssign(false, refDestructuringErrors); - } - elts.push(elt); - } - return elts -}; - -// Parse the next token as an identifier. If `liberal` is true (used -// when parsing properties), it will also convert keywords into -// identifiers. - -pp$3.checkUnreserved = function(ref) { - var start = ref.start; - var end = ref.end; - var name = ref.name; - - if (this.inGenerator && name === "yield") - { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); } - if (this.inAsync && name === "await") - { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); } - if (this.isKeyword(name)) - { this.raise(start, ("Unexpected keyword '" + name + "'")); } - if (this.options.ecmaVersion < 6 && - this.input.slice(start, end).indexOf("\\") != -1) { return } - var re = this.strict ? this.reservedWordsStrict : this.reservedWords; - if (re.test(name)) - { this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); } -}; - -pp$3.parseIdent = function(liberal, isBinding) { - var node = this.startNode(); - if (liberal && this.options.allowReserved == "never") { liberal = false; } - if (this.type === types.name) { - node.name = this.value; - } else if (this.type.keyword) { - node.name = this.type.keyword; - } else { - this.unexpected(); - } - this.next(); - this.finishNode(node, "Identifier"); - if (!liberal) { this.checkUnreserved(node); } - return node -}; - -// Parses yield expression inside generator. - -pp$3.parseYield = function() { - if (!this.yieldPos) { this.yieldPos = this.start; } - - var node = this.startNode(); - this.next(); - if (this.type == types.semi || this.canInsertSemicolon() || (this.type != types.star && !this.type.startsExpr)) { - node.delegate = false; - node.argument = null; - } else { - node.delegate = this.eat(types.star); - node.argument = this.parseMaybeAssign(); - } - return this.finishNode(node, "YieldExpression") -}; - -pp$3.parseAwait = function() { - if (!this.awaitPos) { this.awaitPos = this.start; } - - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeUnary(null, true); - return this.finishNode(node, "AwaitExpression") -}; - -var pp$4 = Parser.prototype; - -// This function is used to raise exceptions on parse errors. It -// takes an offset integer (into the current `input`) to indicate -// the location of the error, attaches the position to the end -// of the error message, and then raises a `SyntaxError` with that -// message. - -pp$4.raise = function(pos, message) { - var loc = getLineInfo(this.input, pos); - message += " (" + loc.line + ":" + loc.column + ")"; - var err = new SyntaxError(message); - err.pos = pos; err.loc = loc; err.raisedAt = this.pos; - throw err -}; - -pp$4.raiseRecoverable = pp$4.raise; - -pp$4.curPosition = function() { - if (this.options.locations) { - return new Position(this.curLine, this.pos - this.lineStart) - } -}; - -var pp$5 = Parser.prototype; - -// Object.assign polyfill -var assign$1 = Object.assign || function(target) { - var sources = [], len = arguments.length - 1; - while ( len-- > 0 ) { sources[ len ] = arguments[ len + 1 ]; } - - for (var i = 0, list = sources; i < list.length; i += 1) { - var source = list[i]; - - for (var key in source) { - if (has(source, key)) { - target[key] = source[key]; - } - } - } - return target -}; - -// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. - -pp$5.enterFunctionScope = function() { - // var: a hash of var-declared names in the current lexical scope - // lexical: a hash of lexically-declared names in the current lexical scope - // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) - // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) - this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}); -}; - -pp$5.exitFunctionScope = function() { - this.scopeStack.pop(); -}; - -pp$5.enterLexicalScope = function() { - var parentScope = this.scopeStack[this.scopeStack.length - 1]; - var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}}; - - this.scopeStack.push(childScope); - assign$1(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical); -}; - -pp$5.exitLexicalScope = function() { - var childScope = this.scopeStack.pop(); - var parentScope = this.scopeStack[this.scopeStack.length - 1]; - - assign$1(parentScope.childVar, childScope.var, childScope.childVar); -}; - -/** - * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` - * in the current lexical scope or any of the parent lexical scopes in this function. - */ -pp$5.canDeclareVarName = function(name) { - var currentScope = this.scopeStack[this.scopeStack.length - 1]; - - return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) -}; - -/** - * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` - * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in - * any child lexical scopes in this function. - */ -pp$5.canDeclareLexicalName = function(name) { - var currentScope = this.scopeStack[this.scopeStack.length - 1]; - - return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) -}; - -pp$5.declareVarName = function(name) { - this.scopeStack[this.scopeStack.length - 1].var[name] = true; -}; - -pp$5.declareLexicalName = function(name) { - this.scopeStack[this.scopeStack.length - 1].lexical[name] = true; -}; - -var Node = function Node(parser, pos, loc) { - this.type = ""; - this.start = pos; - this.end = 0; - if (parser.options.locations) - { this.loc = new SourceLocation(parser, loc); } - if (parser.options.directSourceFile) - { this.sourceFile = parser.options.directSourceFile; } - if (parser.options.ranges) - { this.range = [pos, 0]; } -}; - -// Start an AST node, attaching a start offset. - -var pp$6 = Parser.prototype; - -pp$6.startNode = function() { - return new Node(this, this.start, this.startLoc) -}; - -pp$6.startNodeAt = function(pos, loc) { - return new Node(this, pos, loc) -}; - -// Finish an AST node, adding `type` and `end` properties. - -function finishNodeAt(node, type, pos, loc) { - node.type = type; - node.end = pos; - if (this.options.locations) - { node.loc.end = loc; } - if (this.options.ranges) - { node.range[1] = pos; } - return node -} - -pp$6.finishNode = function(node, type) { - return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) -}; - -// Finish node at given position - -pp$6.finishNodeAt = function(node, type, pos, loc) { - return finishNodeAt.call(this, node, type, pos, loc) -}; - -// The algorithm used to determine whether a regexp can appear at a -// given point in the program is loosely based on sweet.js' approach. -// See https://github.com/mozilla/sweet.js/wiki/design - -var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { - this.token = token; - this.isExpr = !!isExpr; - this.preserveSpace = !!preserveSpace; - this.override = override; - this.generator = !!generator; -}; - -var types$1 = { - b_stat: new TokContext("{", false), - b_expr: new TokContext("{", true), - b_tmpl: new TokContext("${", false), - p_stat: new TokContext("(", false), - p_expr: new TokContext("(", true), - q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), - f_stat: new TokContext("function", false), - f_expr: new TokContext("function", true), - f_expr_gen: new TokContext("function", true, false, null, true), - f_gen: new TokContext("function", false, false, null, true) -}; - -var pp$7 = Parser.prototype; - -pp$7.initialContext = function() { - return [types$1.b_stat] -}; - -pp$7.braceIsBlock = function(prevType) { - var parent = this.curContext(); - if (parent === types$1.f_expr || parent === types$1.f_stat) - { return true } - if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) - { return !parent.isExpr } - - // The check for `tt.name && exprAllowed` detects whether we are - // after a `yield` or `of` construct. See the `updateContext` for - // `tt.name`. - if (prevType === types._return || prevType == types.name && this.exprAllowed) - { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } - if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType == types.arrow) - { return true } - if (prevType == types.braceL) - { return parent === types$1.b_stat } - if (prevType == types._var || prevType == types.name) - { return false } - return !this.exprAllowed -}; - -pp$7.inGeneratorContext = function() { - var this$1 = this; - - for (var i = this.context.length - 1; i >= 1; i--) { - var context = this$1.context[i]; - if (context.token === "function") - { return context.generator } - } - return false -}; - -pp$7.updateContext = function(prevType) { - var update, type = this.type; - if (type.keyword && prevType == types.dot) - { this.exprAllowed = false; } - else if (update = type.updateContext) - { update.call(this, prevType); } - else - { this.exprAllowed = type.beforeExpr; } -}; - -// Token-specific context update code - -types.parenR.updateContext = types.braceR.updateContext = function() { - if (this.context.length == 1) { - this.exprAllowed = true; - return - } - var out = this.context.pop(); - if (out === types$1.b_stat && this.curContext().token === "function") { - out = this.context.pop(); - } - this.exprAllowed = !out.isExpr; -}; - -types.braceL.updateContext = function(prevType) { - this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); - this.exprAllowed = true; -}; - -types.dollarBraceL.updateContext = function() { - this.context.push(types$1.b_tmpl); - this.exprAllowed = true; -}; - -types.parenL.updateContext = function(prevType) { - var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; - this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); - this.exprAllowed = true; -}; - -types.incDec.updateContext = function() { - // tokExprAllowed stays unchanged -}; - -types._function.updateContext = types._class.updateContext = function(prevType) { - if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && - !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) - { this.context.push(types$1.f_expr); } - else - { this.context.push(types$1.f_stat); } - this.exprAllowed = false; -}; - -types.backQuote.updateContext = function() { - if (this.curContext() === types$1.q_tmpl) - { this.context.pop(); } - else - { this.context.push(types$1.q_tmpl); } - this.exprAllowed = false; -}; - -types.star.updateContext = function(prevType) { - if (prevType == types._function) { - var index = this.context.length - 1; - if (this.context[index] === types$1.f_expr) - { this.context[index] = types$1.f_expr_gen; } - else - { this.context[index] = types$1.f_gen; } - } - this.exprAllowed = true; -}; - -types.name.updateContext = function(prevType) { - var allowed = false; - if (this.options.ecmaVersion >= 6) { - if (this.value == "of" && !this.exprAllowed || - this.value == "yield" && this.inGeneratorContext()) - { allowed = true; } - } - this.exprAllowed = allowed; -}; - -// Object type used to represent tokens. Note that normally, tokens -// simply exist as properties on the parser object. This is only -// used for the onToken callback and the external tokenizer. - -var Token = function Token(p) { - this.type = p.type; - this.value = p.value; - this.start = p.start; - this.end = p.end; - if (p.options.locations) - { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } - if (p.options.ranges) - { this.range = [p.start, p.end]; } -}; - -// ## Tokenizer - -var pp$8 = Parser.prototype; - -// Are we running under Rhino? -var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]"; - -// Move to the next token - -pp$8.next = function() { - if (this.options.onToken) - { this.options.onToken(new Token(this)); } - - this.lastTokEnd = this.end; - this.lastTokStart = this.start; - this.lastTokEndLoc = this.endLoc; - this.lastTokStartLoc = this.startLoc; - this.nextToken(); -}; - -pp$8.getToken = function() { - this.next(); - return new Token(this) -}; - -// If we're in an ES6 environment, make parsers iterable -if (typeof Symbol !== "undefined") - { pp$8[Symbol.iterator] = function() { - var this$1 = this; - - return { - next: function () { - var token = this$1.getToken(); - return { - done: token.type === types.eof, - value: token - } - } - } - }; } - -// Toggle strict mode. Re-reads the next number or string to please -// pedantic tests (`"use strict"; 010;` should fail). - -pp$8.curContext = function() { - return this.context[this.context.length - 1] -}; - -// Read a single token, updating the parser object's token-related -// properties. - -pp$8.nextToken = function() { - var curContext = this.curContext(); - if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } - - this.start = this.pos; - if (this.options.locations) { this.startLoc = this.curPosition(); } - if (this.pos >= this.input.length) { return this.finishToken(types.eof) } - - if (curContext.override) { return curContext.override(this) } - else { this.readToken(this.fullCharCodeAtPos()); } -}; - -pp$8.readToken = function(code) { - // Identifier or keyword. '\uXXXX' sequences are allowed in - // identifiers, so '\' also dispatches to that. - if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) - { return this.readWord() } - - return this.getTokenFromCode(code) -}; - -pp$8.fullCharCodeAtPos = function() { - var code = this.input.charCodeAt(this.pos); - if (code <= 0xd7ff || code >= 0xe000) { return code } - var next = this.input.charCodeAt(this.pos + 1); - return (code << 10) + next - 0x35fdc00 -}; - -pp$8.skipBlockComment = function() { - var this$1 = this; - - var startLoc = this.options.onComment && this.curPosition(); - var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); - if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } - this.pos = end + 2; - if (this.options.locations) { - lineBreakG.lastIndex = start; - var match; - while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { - ++this$1.curLine; - this$1.lineStart = match.index + match[0].length; - } - } - if (this.options.onComment) - { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, - startLoc, this.curPosition()); } -}; - -pp$8.skipLineComment = function(startSkip) { - var this$1 = this; - - var start = this.pos; - var startLoc = this.options.onComment && this.curPosition(); - var ch = this.input.charCodeAt(this.pos += startSkip); - while (this.pos < this.input.length && !isNewLine(ch)) { - ch = this$1.input.charCodeAt(++this$1.pos); - } - if (this.options.onComment) - { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, - startLoc, this.curPosition()); } -}; - -// Called at the start of the parse and after every token. Skips -// whitespace and comments, and. - -pp$8.skipSpace = function() { - var this$1 = this; - - loop: while (this.pos < this.input.length) { - var ch = this$1.input.charCodeAt(this$1.pos); - switch (ch) { - case 32: case 160: // ' ' - ++this$1.pos; - break - case 13: - if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { - ++this$1.pos; - } - case 10: case 8232: case 8233: - ++this$1.pos; - if (this$1.options.locations) { - ++this$1.curLine; - this$1.lineStart = this$1.pos; - } - break - case 47: // '/' - switch (this$1.input.charCodeAt(this$1.pos + 1)) { - case 42: // '*' - this$1.skipBlockComment(); - break - case 47: - this$1.skipLineComment(2); - break - default: - break loop - } - break - default: - if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++this$1.pos; - } else { - break loop - } - } - } -}; - -// Called at the end of every token. Sets `end`, `val`, and -// maintains `context` and `exprAllowed`, and skips the space after -// the token, so that the next one's `start` will point at the -// right position. - -pp$8.finishToken = function(type, val) { - this.end = this.pos; - if (this.options.locations) { this.endLoc = this.curPosition(); } - var prevType = this.type; - this.type = type; - this.value = val; - - this.updateContext(prevType); -}; - -// ### Token reading - -// This is the function that is called to fetch the next token. It -// is somewhat obscure, because it works in character codes rather -// than characters, and because operator parsing has been inlined -// into it. -// -// All in the name of speed. -// -pp$8.readToken_dot = function() { - var next = this.input.charCodeAt(this.pos + 1); - if (next >= 48 && next <= 57) { return this.readNumber(true) } - var next2 = this.input.charCodeAt(this.pos + 2); - if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' - this.pos += 3; - return this.finishToken(types.ellipsis) - } else { - ++this.pos; - return this.finishToken(types.dot) - } -}; - -pp$8.readToken_slash = function() { // '/' - var next = this.input.charCodeAt(this.pos + 1); - if (this.exprAllowed) { ++this.pos; return this.readRegexp() } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.slash, 1) -}; - -pp$8.readToken_mult_modulo_exp = function(code) { // '%*' - var next = this.input.charCodeAt(this.pos + 1); - var size = 1; - var tokentype = code === 42 ? types.star : types.modulo; - - // exponentiation operator ** and **= - if (this.options.ecmaVersion >= 7 && next === 42) { - ++size; - tokentype = types.starstar; - next = this.input.charCodeAt(this.pos + 2); - } - - if (next === 61) { return this.finishOp(types.assign, size + 1) } - return this.finishOp(tokentype, size) -}; - -pp$8.readToken_pipe_amp = function(code) { // '|&' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) -}; - -pp$8.readToken_caret = function() { // '^' - var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.bitwiseXOR, 1) -}; - -pp$8.readToken_plus_min = function(code) { // '+-' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) { - if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 && - (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { - // A `-->` line comment - this.skipLineComment(3); - this.skipSpace(); - return this.nextToken() - } - return this.finishOp(types.incDec, 2) - } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.plusMin, 1) -}; - -pp$8.readToken_lt_gt = function(code) { // '<>' - var next = this.input.charCodeAt(this.pos + 1); - var size = 1; - if (next === code) { - size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; - if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } - return this.finishOp(types.bitShift, size) - } - if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 && - this.input.charCodeAt(this.pos + 3) == 45) { - // ` - diff --git a/test/ut/spec/animation/ElementAnimation.test.ts b/test/ut/spec/animation/ElementAnimation.test.ts index 39548c48e..26b528124 100644 --- a/test/ut/spec/animation/ElementAnimation.test.ts +++ b/test/ut/spec/animation/ElementAnimation.test.ts @@ -2,6 +2,34 @@ import {Polyline, Rect, init} from '../zrender'; import Animation from '../../../../src/animation/Animation'; describe('ElementAnimation', function () { + + it('Undefined value should not be animated.', function () { + const polyline = new Polyline(); + polyline.animateTo({ + shape: { + foo: 2 + } as any + }, { + setToFinal: true + }); + + expect(polyline.animators.length).toEqual(0); + }); + + + it('Equal value should not be animated.', function () { + const polyline = new Polyline(); + polyline.x = 100; + polyline.animateTo({ + x: 100 + }, { + setToFinal: true + }); + + expect(polyline.animators.length).toEqual(0); + }); + + it('Should be final state when setToFinal', function () { const polyline = new Polyline(); polyline.animateTo({ @@ -56,7 +84,7 @@ describe('ElementAnimation', function () { duration: 100, done: () => { animation.stop(); - resolve(); + resolve(undefined); } }); for (let i = 0; i < rect.animators.length; i++) { diff --git a/test/ut/spec/core/platform.test.ts b/test/ut/spec/core/platform.test.ts new file mode 100644 index 000000000..5f307fe88 --- /dev/null +++ b/test/ut/spec/core/platform.test.ts @@ -0,0 +1,36 @@ +import * as platform from '../../../../src/core/platform'; + +describe('platform', function() { + + it('Default font should be correct', function () { + expect(platform.DEFAULT_FONT_SIZE).toBe(12); + expect(platform.DEFAULT_FONT_FAMILY).toBe('sans-serif'); + expect(platform.DEFAULT_FONT).toBe('12px sans-serif'); + }); + + it('setPlatformAPI can override methods', function () { + function createCanvas() { + return { + width: 1 + }as HTMLCanvasElement; + } + function measureText() { + return { width: 16.5 }; + } + + const oldCreateCanvas = platform.platformApi.createCanvas; + const oldMeasureText = platform.platformApi.measureText; + platform.setPlatformAPI({ + createCanvas, + measureText + }); + expect(platform.platformApi.createCanvas().width).toBe(1); + expect(platform.platformApi.measureText('a', '12px sans-serif').width).toBe(16.5); + + // Restore + platform.setPlatformAPI({ + createCanvas: oldCreateCanvas, + measureText: oldMeasureText + }); + }) +}); \ No newline at end of file