├── .prettierignore ├── .prettierrc.toml ├── recipes ├── Window#fetch.json ├── Window#Storage.json ├── Document#cookie.json ├── Window#localStorage.json ├── XMLHttpRequest.json ├── Navigator#vendor.json ├── Window#sessionStorage.json ├── Navigator#platform.json ├── Window#XMLHttpRequest.json ├── Navigator#appVersion.json ├── Navigator#doNotTrack.json ├── Navigator#productSub.json ├── Navigator#userAgent.json ├── Window#XMLHttpRequestUpload.json └── Window#XMLHttpRequestEventTarget.json ├── mocks ├── fetch.js ├── navigator.js ├── navigatorId.js ├── cookies.js ├── webStorage.js └── xmlHttpRequest.js ├── config.example.json ├── bundle.js ├── README.md ├── package.json ├── report.js ├── .gitignore ├── record.js ├── config.js ├── reportTemplate.handlebars ├── ingest.js ├── cli.js ├── rewrite.js └── pnpm-lock.yaml /.prettierignore: -------------------------------------------------------------------------------- 1 | addthis_widget.js 2 | addthis_widget_pretty.js 3 | test.js 4 | test_rewritten.js 5 | data 6 | -------------------------------------------------------------------------------- /.prettierrc.toml: -------------------------------------------------------------------------------- 1 | printWidth = 99 2 | tabWidth = 2 3 | singleQuote = true 4 | spaceBeforeFunctionParen = true 5 | arrowParens = 'avoid' 6 | -------------------------------------------------------------------------------- /recipes/Window#fetch.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["window"], 3 | "sourceProperty": "fetch", 4 | "destinationMock": "fetch" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Window#Storage.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["window"], 3 | "sourceProperty": "Storage", 4 | "destinationMock": "webStorage" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Document#cookie.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["Document", "prototype"], 3 | "sourceProperty": "cookie", 4 | "destinationMock": "cookies" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Window#localStorage.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["window"], 3 | "sourceProperty": "localStorage", 4 | "destinationMock": "webStorage" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/XMLHttpRequest.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["window"], 3 | "sourceProperty": "XMLHttpRequest", 4 | "destinationMock": "xmlHttpRequest" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Navigator#vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["Navigator", "prototype"], 3 | "sourceProperty": "vendor", 4 | "destinationMock": "navigator" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Window#sessionStorage.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["window"], 3 | "sourceProperty": "sessionStorage", 4 | "destinationMock": "webStorage" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Navigator#platform.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["Navigator", "prototype"], 3 | "sourceProperty": "platform", 4 | "destinationMock": "navigatorId" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Window#XMLHttpRequest.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["window"], 3 | "sourceProperty": "XMLHttpRequest", 4 | "destinationMock": "xmlHttpRequest" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Navigator#appVersion.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["Navigator", "prototype"], 3 | "sourceProperty": "appVersion", 4 | "destinationMock": "navigatorId" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Navigator#doNotTrack.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["Navigator", "prototype"], 3 | "sourceProperty": "doNotTrack", 4 | "destinationMock": "navigator" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Navigator#productSub.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["Navigator", "prototype"], 3 | "sourceProperty": "productSub", 4 | "destinationMock": "navigator" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Navigator#userAgent.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["Navigator", "prototype"], 3 | "sourceProperty": "userAgent", 4 | "destinationMock": "navigatorId" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Window#XMLHttpRequestUpload.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["window"], 3 | "sourceProperty": "XMLHttpRequestUpload", 4 | "destinationMock": "xmlHttpRequest" 5 | } 6 | -------------------------------------------------------------------------------- /recipes/Window#XMLHttpRequestEventTarget.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceObject": ["window"], 3 | "sourceProperty": "XMLHttpRequestEventTarget", 4 | "destinationMock": "xmlHttpRequest" 5 | } 6 | -------------------------------------------------------------------------------- /mocks/fetch.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | // Fetch API 4 | // 5 | 6 | 'use strict'; 7 | 8 | const fetch = async (resource, init = null) => { 9 | throw new TypeError('Failed to fetch'); 10 | }; 11 | 12 | exports.fetch = { 13 | configurable: true, 14 | enumerable: true, 15 | value: fetch, 16 | writable: true, 17 | }; 18 | -------------------------------------------------------------------------------- /config.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": { 3 | "foo": { 4 | "patterns": ["||example.com/foo.js"], 5 | "policy": { 6 | "include": [ 7 | "Document#cookie" 8 | ], 9 | "exclude": [ 10 | "Navigator#userAgent" 11 | ] 12 | } 13 | } 14 | }, 15 | "graphs": ["data/graphs/**/*.graphml"], 16 | "code": "data/code", 17 | "trace": "data/trace.json", 18 | "report": "data/report.html", 19 | "bundle": { 20 | "rules": "data/rules.txt", 21 | "resources": "data/resources.json" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bundle.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | 'use strict'; 4 | 5 | const bundle = resources => { 6 | return { 7 | rules: resources.flatMap(({ name, patterns }) => 8 | patterns.map(pattern => `${pattern}$script,important,redirect=${name}`) 9 | ), 10 | resources: resources.map(({ name, src }) => ({ 11 | name, 12 | aliases: [], 13 | kind: { 14 | mime: 'application/javascript', 15 | }, 16 | content: Buffer.from(src, 'utf8').toString('base64'), 17 | })), 18 | }; 19 | }; 20 | 21 | module.exports = bundle; 22 | -------------------------------------------------------------------------------- /mocks/navigator.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | // Navigator API 4 | // 5 | 6 | 'use strict'; 7 | 8 | exports.doNotTrack = { 9 | configurable: true, 10 | enumerable: true, 11 | get () { 12 | return '1'; 13 | }, 14 | }; 15 | 16 | exports.productSub = { 17 | configurable: true, 18 | enumerable: true, 19 | get () { 20 | return 20030107; 21 | }, 22 | }; 23 | 24 | exports.vendor = { 25 | configurable: true, 26 | enumerable: true, 27 | get () { 28 | return ''; 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /mocks/navigatorId.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | // NavigatorID API 4 | // 5 | 6 | 'use strict'; 7 | 8 | exports.appVersion = { 9 | configurable: true, 10 | enumerable: true, 11 | get () { 12 | return '5.0'; 13 | }, 14 | }; 15 | 16 | exports.platform = { 17 | configurable: true, 18 | enumerable: true, 19 | get () { 20 | return ''; 21 | }, 22 | }; 23 | 24 | exports.userAgent = { 25 | configurable: true, 26 | enumerable: true, 27 | get () { 28 | return 'Mozilla/5.0'; 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SugarCoat 2 | 3 | ## Development 4 | 5 | [pnpm](https://pnpm.js.org/) is recommended for managing a JavaScript development environment for 6 | SugarCoat. 7 | 8 | To initialize an isolated JavaScript development environment: 9 | 10 | ``` 11 | pnpm install 12 | ``` 13 | 14 | ### Code Formatting 15 | 16 | Code formatting for JavaScript is handled by [prettierx](https://github.com/brodybits/prettierx), 17 | with a few [options](.prettierrc.toml) tweaked. 18 | 19 | To check that the code is correctly formatted: 20 | 21 | ``` 22 | pnpm run check 23 | ``` 24 | 25 | To auto-format the code: 26 | 27 | ``` 28 | pnpm run fmt 29 | ``` 30 | -------------------------------------------------------------------------------- /mocks/cookies.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | 'use strict'; 4 | 5 | // Document.cookie API 6 | // 7 | 8 | const cookieJar = {}; 9 | 10 | exports.cookie = { 11 | enumerable: true, 12 | configurable: true, 13 | get () { 14 | return Object.entries(cookieJar) 15 | .map(([key, value]) => (value == null ? key : `${key}=${value}`)) 16 | .join('; '); 17 | }, 18 | set (value) { 19 | const pair = value.split(';')[0]; 20 | const parts = pair.split('='); 21 | const cookieKey = parts.shift().trim(); 22 | const cookieValue = parts.length > 0 ? parts.join('=').trim() : null; 23 | cookieJar[cookieKey] = cookieValue; 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sugarcoat", 3 | "version": "0.0.0", 4 | "description": "", 5 | "author": "Michael Smith (https://spinda.net)", 6 | "license": "MPL-2.0", 7 | "homepage": "https://github.com/spinda/sugarcoat#readme", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/spinda/sugarcoat.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/spinda/sugarcoat/issues" 14 | }, 15 | "keywords": [], 16 | "bin": { 17 | "sugarcoat": "cli.js" 18 | }, 19 | "scripts": { 20 | "cli": "node cli.js", 21 | "record": "node record.js", 22 | "check": "prettierx --check \"*.js\" \"**/*.js\"", 23 | "fmt": "prettierx --write \"*.js\" \"**/*.js\"" 24 | }, 25 | "dependencies": { 26 | "ajv": "^6.12.4", 27 | "am": "^1.0.2", 28 | "await-sleep": "^0.0.1", 29 | "better-ajv-errors": "^0.6.7", 30 | "commander": "^6.0.0", 31 | "crypto-random-string": "^3.2.0", 32 | "escodegen": "^1.14.3", 33 | "esprima": "^4.0.1", 34 | "fast-glob": "^3.2.4", 35 | "fs-extra": "^9.0.1", 36 | "graphology": "^0.17.1", 37 | "graphology-graphml": "^0.2.0", 38 | "handlebars": "^4.7.6", 39 | "iterare": "^1.2.1", 40 | "jsonlint": "^1.6.3", 41 | "line-column": "^1.0.2", 42 | "lodash.groupby": "^4.6.0", 43 | "lodash.sortby": "^4.7.0", 44 | "puppeteer-core": "^1.19.0", 45 | "sanitize-filename": "^1.6.3", 46 | "tmp-promise": "^3.0.2", 47 | "verror": "^1.10.0" 48 | }, 49 | "devDependencies": { 50 | "prettierx": "^0.14.0" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /mocks/webStorage.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | // Web Storage API 4 | // 5 | 6 | 'use strict'; 7 | 8 | let isSealed = false; 9 | 10 | class Storage { 11 | constructor () { 12 | if (isSealed) { 13 | throw new TypeError('Illegal constructor'); 14 | } 15 | } 16 | 17 | get length () { 18 | return Object.keys(this).length; 19 | } 20 | 21 | key (index) { 22 | const keys = Object.keys(this); 23 | if (index < 0 || index >= keys.length) { 24 | return null; 25 | } 26 | return keys[index]; 27 | } 28 | 29 | getItem (key) { 30 | return Object.prototype.hasOwnProperty.call(this, key) ? this[key] : null; 31 | } 32 | 33 | setItem (key, value) { 34 | this[key] = String(value); 35 | } 36 | 37 | removeItem (key) { 38 | delete this[key]; 39 | } 40 | 41 | clear () { 42 | const keys = Object.keys(this); 43 | for (const key of keys) { 44 | delete this[key]; 45 | } 46 | } 47 | } 48 | 49 | exports.Storage = { 50 | configurable: true, 51 | enumerable: true, 52 | value: Storage, 53 | writable: true, 54 | }; 55 | 56 | const localStorage = new Storage(); 57 | 58 | exports.localStorage = { 59 | configurable: true, 60 | enumerable: true, 61 | get () { 62 | return localStorage; 63 | }, 64 | }; 65 | 66 | const sessionStorage = new Storage(); 67 | 68 | exports.sessionStorage = { 69 | configurable: true, 70 | enumerable: true, 71 | get () { 72 | return sessionStorage; 73 | }, 74 | }; 75 | 76 | isSealed = true; 77 | -------------------------------------------------------------------------------- /report.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | 'use strict'; 4 | 5 | const path = require('path'); 6 | 7 | const fs = require('fs-extra'); 8 | const Handlebars = require('handlebars'); 9 | const { iterate } = require('iterare'); 10 | const lineColumn = require('line-column'); 11 | const groupBy = require('lodash.groupby'); 12 | const sortBy = require('lodash.sortby'); 13 | const { VError } = require('verror'); 14 | 15 | const contextLength = 24; 16 | 17 | const report = (reportTemplate, targets) => 18 | reportTemplate({ 19 | targets: iterate(targets).map(({ name, src, trace }) => { 20 | const srcIndex = lineColumn(src); 21 | return { 22 | name, 23 | bindings: sortBy(Object.entries(groupBy(trace, 'binding')), 0).map(([name, accesses]) => ({ 24 | name, 25 | accesses: accesses.map(bindingAccess => ({ 26 | accessPosition: srcIndex.fromIndex(bindingAccess.position), 27 | accessPrefix: src.substring( 28 | Math.max(0, bindingAccess.position - 1 - contextLength), 29 | bindingAccess.position - 1 30 | ), 31 | accessSuffix: src.substring( 32 | bindingAccess.position - 1, 33 | Math.min(src.length, bindingAccess.position - 1 + contextLength) 34 | ), 35 | })), 36 | })), 37 | }; 38 | }), 39 | }); 40 | module.exports = report; 41 | 42 | const loadReportTemplate = async reportTemplate => 43 | Handlebars.compile( 44 | await fs.readFile(path.join(__dirname, 'reportTemplate.handlebars'), { encoding: 'utf8' }) 45 | ); 46 | report.loadReportTemplate = loadReportTemplate; 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## SugarCoat 2 | 3 | data 4 | config.json 5 | 6 | ## JavaScript 7 | 8 | # Logs 9 | logs 10 | *.log 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | lerna-debug.log* 15 | 16 | # Diagnostic reports (https://nodejs.org/api/report.html) 17 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 18 | 19 | # Runtime data 20 | pids 21 | *.pid 22 | *.seed 23 | *.pid.lock 24 | 25 | # Directory for instrumented libs generated by jscoverage/JSCover 26 | lib-cov 27 | 28 | # Coverage directory used by tools like istanbul 29 | coverage 30 | *.lcov 31 | 32 | # nyc test coverage 33 | .nyc_output 34 | 35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 36 | .grunt 37 | 38 | # Bower dependency directory (https://bower.io/) 39 | bower_components 40 | 41 | # node-waf configuration 42 | .lock-wscript 43 | 44 | # Compiled binary addons (https://nodejs.org/api/addons.html) 45 | build/Release 46 | 47 | # Dependency directories 48 | node_modules/ 49 | jspm_packages/ 50 | 51 | # TypeScript v1 declaration files 52 | typings/ 53 | 54 | # TypeScript cache 55 | *.tsbuildinfo 56 | 57 | # Optional npm cache directory 58 | .npm 59 | 60 | # Optional eslint cache 61 | .eslintcache 62 | 63 | # Optional REPL history 64 | .node_repl_history 65 | 66 | # Output of 'npm pack' 67 | *.tgz 68 | 69 | # Yarn Integrity file 70 | .yarn-integrity 71 | 72 | # dotenv environment variables file 73 | .env 74 | .env.test 75 | 76 | # parcel-bundler cache (https://parceljs.org/) 77 | .cache 78 | 79 | # next.js build output 80 | .next 81 | 82 | # nuxt.js build output 83 | .nuxt 84 | 85 | # vuepress build output 86 | .vuepress/dist 87 | 88 | # Serverless directories 89 | .serverless/ 90 | 91 | # FuseBox cache 92 | .fusebox/ 93 | 94 | # DynamoDB Local files 95 | .dynamodb/ 96 | -------------------------------------------------------------------------------- /record.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | 'use strict'; 4 | 5 | const crypto = require('crypto'); 6 | const path = require('path'); 7 | 8 | const am = require('am'); 9 | const sleep = require('await-sleep'); 10 | const { program } = require('commander'); 11 | const fs = require('fs-extra'); 12 | const puppeteer = require('puppeteer-core'); 13 | const tmp = require('tmp-promise'); 14 | 15 | tmp.setGracefulCleanup(); 16 | 17 | program 18 | .version(require('./package.json').version) 19 | .requiredOption('-b, --browser ', 'browser executable path') 20 | .requiredOption('-o, --output ', 'Page Graph output directory') 21 | .option('-p, --profile ', 'browser profile directory', null) 22 | .option('-v, --verbose', 'enable verbose browser logging', false) 23 | .parse(require('process').argv); 24 | 25 | const { 26 | browser: browserExePath, 27 | output: outputDirPath, 28 | profile: profileDirPath, 29 | verbose: enableBrowserLogging, 30 | } = program; 31 | 32 | const computeHash = data => crypto.createHash('sha256').update(data).digest('hex'); 33 | 34 | const attachToTarget = async target => { 35 | const client = await target.createCDPSession(); 36 | client.on('Page.finalPageGraph', async event => { 37 | const graphFileName = `frame-${event.frameId.toLowerCase()}-${computeHash( 38 | event.data 39 | ).substring(0, 32)}.graphml`; 40 | const graphFilePath = path.join(outputDirPath, graphFileName); 41 | await fs.writeFile(graphFilePath, event.data); 42 | console.log(`Saved: ${graphFilePath}`); 43 | }); 44 | }; 45 | 46 | am(async () => { 47 | await fs.ensureDir(outputDirPath); 48 | 49 | const profileDir = profileDirPath 50 | ? { path: profileDirPath, cleanup () {} } 51 | : await tmp.dir({ 52 | unsafeCleanup: true, 53 | }); 54 | 55 | const browser = await puppeteer.launch({ 56 | executablePath: browserExePath, 57 | userDataDir: profileDir.path, 58 | userDataDir: '/home/spinda/.config/BraveSoftware/Brave-Browser-Development', 59 | args: [ 60 | ...(enableBrowserLogging ? ['--enable-logging', '--v=0'] : []), 61 | '--disable-brave-update', 62 | ...(enableBrowserLogging ? ['--enable-logging=stderr'] : []), 63 | ], 64 | ignoreDefaultArgs: [ 65 | '--disable-sync', 66 | '--enable-features=NetworkService,NetworkServiceInProcess', 67 | // ^ breaks Brave Shields 68 | '--disable-extensions', 69 | ], 70 | dumpio: enableBrowserLogging, 71 | headless: false, 72 | }); 73 | 74 | browser.on('targetcreated', async target => { 75 | if (target.type() === 'page') { 76 | await attachToTarget(target); 77 | } 78 | }); 79 | 80 | for (const page of await browser.pages()) { 81 | attachToTarget(page.target()); 82 | } 83 | 84 | browser.on('disconnected', async () => { 85 | profileDir.cleanup(); 86 | }); 87 | }); 88 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | 'use strict'; 4 | 5 | const Ajv = require('ajv'); 6 | const betterAjvErrors = require('better-ajv-errors'); 7 | const fs = require('fs-extra'); 8 | const jsonlint = require('jsonlint'); 9 | 10 | const configAjv = new Ajv({ jsonPointers: true }); 11 | configAjv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json')); 12 | 13 | const configSchema = { 14 | type: 'object', 15 | properties: { 16 | targets: { 17 | type: 'object', 18 | additionalProperties: { 19 | type: 'object', 20 | properties: { 21 | patterns: { 22 | type: 'array', 23 | items: { 24 | type: 'string', 25 | }, 26 | }, 27 | policy: { 28 | type: 'object', 29 | properties: { 30 | include: { 31 | type: 'array', 32 | items: { 33 | type: 'string', 34 | }, 35 | }, 36 | exclude: { 37 | type: 'array', 38 | items: { 39 | type: 'string', 40 | }, 41 | }, 42 | }, 43 | additionalProperties: false, 44 | }, 45 | }, 46 | additionalProperties: false, 47 | }, 48 | }, 49 | graphs: { 50 | type: 'array', 51 | items: { 52 | type: 'string', 53 | }, 54 | }, 55 | code: { 56 | type: 'string', 57 | }, 58 | trace: { 59 | type: 'string', 60 | }, 61 | report: { 62 | type: 'string', 63 | }, 64 | bundle: { 65 | type: 'object', 66 | properties: { 67 | rules: { 68 | type: 'string', 69 | }, 70 | resources: { 71 | type: 'string', 72 | }, 73 | }, 74 | required: ['rules', 'resources'], 75 | additionalProperties: false, 76 | }, 77 | }, 78 | additionalProperties: false, 79 | }; 80 | exports.configSchema = configSchema; 81 | 82 | const validateConfigImpl = configAjv.compile(configSchema); 83 | const validateConfig = config => { 84 | if (!validateConfigImpl(config)) { 85 | throw new TypeError( 86 | betterAjvErrors(configSchema, config, validateConfigImpl.errors, { indent: 2 }) 87 | ); 88 | } 89 | }; 90 | exports.validateConfig = validateConfig; 91 | 92 | const parseConfig = configSrc => { 93 | const config = jsonlint.parse(configSrc); 94 | validateConfig(config); 95 | return config; 96 | }; 97 | exports.parseConfig = parseConfig; 98 | 99 | const parseConfigFile = async configFilePath => { 100 | const configSrc = await fs.readFile(configFilePath, { encoding: 'utf8' }); 101 | return parseConfig(configSrc); 102 | }; 103 | exports.parseConfigFile = parseConfigFile; 104 | -------------------------------------------------------------------------------- /reportTemplate.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SugarCoat Report 6 | 99 | 100 | 101 |

SugarCoat Report

102 | {{#each targets}} 103 |
104 |
{{name}}
105 |
106 | {{#if bindings.[0]}} 107 |
    108 | {{#each bindings}} 109 |
  • 110 | {{name}} 111 | Accessed {{accesses.length}} 112 | time{{#if accesses.[2]}}s{{/if}}. 113 | 114 | 115 | {{#each accesses}} 116 | 117 | 118 | 121 | 122 | {{/each}} 123 | 124 |
    {{accessPosition.line}}:{{accessPosition.col}} 119 | …{{accessPrefix}}{{accessSuffix}}… 120 |
    125 |
  • 126 | {{/each}} 127 |
128 | {{else}} 129 |
(No accesses recorded.)
130 | {{/if}} 131 | {{/each}} 132 | 133 | 134 | -------------------------------------------------------------------------------- /ingest.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | 'use strict'; 4 | 5 | const { iterate } = require('iterare'); 6 | const lineColumn = require('line-column'); 7 | const sortBy = require('lodash.sortby'); 8 | const { VError } = require('verror'); 9 | 10 | const ingest = (graphs, targets) => { 11 | const entriesMapBySrc = new Map(); 12 | const registerEntryBySrc = (src, entry) => { 13 | const entries = entriesMapBySrc.get(src); 14 | if (entries) { 15 | entries.push(entry); 16 | } else { 17 | entriesMapBySrc.set(src, [entry]); 18 | } 19 | }; 20 | 21 | const traces = iterate(targets) 22 | .map(target => { 23 | const trace = new Map(); 24 | registerEntryBySrc(target.src, { trace }); 25 | 26 | if (target.alts) { 27 | const origSrcIndex = lineColumn(target.src); 28 | for (const alt of target.alts) { 29 | registerEntryBySrc(alt.src, { 30 | trace, 31 | srcMap: alt.srcMap, 32 | srcIndex: lineColumn(alt.src), 33 | origSrcIndex, 34 | }); 35 | } 36 | } 37 | 38 | return trace; 39 | }) 40 | .toArray(); 41 | 42 | for (const graph of graphs) { 43 | const entriesMapByNodeKey = new Map(); 44 | 45 | for (const [scriptNodeKey, scriptNodeAttrs] of graph.nodeEntries()) { 46 | if (scriptNodeAttrs['node type'] !== 'script') { 47 | continue; 48 | } 49 | 50 | const scriptSrc = scriptNodeAttrs['source']; 51 | if (scriptSrc == null) { 52 | continue; 53 | } 54 | 55 | const entries = entriesMapBySrc.get(scriptSrc); 56 | if (!entries) { 57 | continue; 58 | } 59 | 60 | entriesMapByNodeKey.set(scriptNodeKey, entries); 61 | } 62 | 63 | for (const [bindingNodeKey, bindingNodeAttrs] of graph.nodeEntries()) { 64 | if (bindingNodeAttrs['node type'] !== 'binding') { 65 | continue; 66 | } 67 | 68 | const binding = bindingNodeAttrs['binding']; 69 | 70 | for (const [ 71 | bindingEdgeKey, 72 | bindingEdgeAttrs, 73 | bindingEventNodeKey, 74 | , 75 | bindingEventNodeAttrs, 76 | ] of graph.inEdgeEntries(bindingNodeKey)) { 77 | if (bindingEdgeAttrs['edge type'] !== 'binding') { 78 | continue; 79 | } 80 | 81 | for (const [ 82 | bindingEventEdgeKey, 83 | bindingEventEdgeAttrs, 84 | scriptNodeKey, 85 | , 86 | scriptNodeAttrs, 87 | ] of graph.inEdgeEntries(bindingEventNodeKey)) { 88 | const entries = entriesMapByNodeKey.get(scriptNodeKey); 89 | if (!entries) { 90 | continue; 91 | } 92 | 93 | const rawPosition = bindingEventEdgeAttrs['script position']; 94 | for (const entry of entries) { 95 | let position = rawPosition; 96 | if (entry.srcMap) { 97 | position = entry.srcIndex.fromIndex(position); 98 | position = srcMap.originalPositionFor({ 99 | line: position.line, 100 | column: position.col - 1, 101 | }); 102 | if (!position.source) { 103 | // Ignore accesses from within generated code. 104 | continue; 105 | } 106 | position = entry.origSrcIndex.toIndex(position.line, position.column + 1); 107 | } 108 | 109 | const bindingSet = entry.trace.get(position); 110 | if (bindingSet) { 111 | bindingSet.add(binding); 112 | } else { 113 | entry.trace.set(position, new Set([binding])); 114 | } 115 | } 116 | 117 | break; 118 | } 119 | } 120 | } 121 | } 122 | 123 | return traces.map(trace => 124 | sortBy( 125 | iterate(trace) 126 | .map(([position, bindingSet]) => 127 | iterate(bindingSet).map(binding => ({ binding, position })) 128 | ) 129 | .flatten() 130 | .toArray(), 131 | ['position', 'binding'] 132 | ) 133 | ); 134 | }; 135 | 136 | module.exports = ingest; 137 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | 'use strict'; 4 | 5 | const crypto = require('crypto'); 6 | const path = require('path'); 7 | 8 | const am = require('am'); 9 | const { program } = require('commander'); 10 | const glob = require('fast-glob'); 11 | const fs = require('fs-extra'); 12 | const graphml = require('graphology-graphml'); 13 | const { iterate, zip } = require('iterare'); 14 | const { MultiDirectedGraph } = require('graphology'); 15 | const sanitizeFileName = require('sanitize-filename'); 16 | const { VError } = require('verror'); 17 | 18 | const { parseConfigFile } = require('./config'); 19 | 20 | program 21 | .version(require('./package.json').version) 22 | .requiredOption('-c, --config ', 'config JSON file path') 23 | .option('-i, --ingest', 'ingest Page Graph data and produce a trace of API accesses') 24 | .option('-R, --report', 'generated report of recorded API access sites') 25 | .option('-r, --rewrite', 'produce rewritten script files') 26 | .option('-b, --bundle', 'bundle rewrites into adblock data') 27 | .parse(require('process').argv); 28 | 29 | const { 30 | config: configFilePath, 31 | ingest: shouldIngest, 32 | report: shouldReport, 33 | rewrite: shouldRewrite, 34 | bundle: shouldBundle, 35 | } = program; 36 | 37 | const requiredConfigKeys = new Set(); 38 | if (shouldIngest) { 39 | requiredConfigKeys.add('graphs'); 40 | requiredConfigKeys.add('code'); 41 | requiredConfigKeys.add('trace'); 42 | } 43 | if (shouldReport) { 44 | requiredConfigKeys.add('trace'); 45 | requiredConfigKeys.add('report'); 46 | } 47 | if (shouldRewrite) { 48 | requiredConfigKeys.add('code'); 49 | requiredConfigKeys.add('trace'); 50 | } 51 | if (shouldBundle) { 52 | requiredConfigKeys.add('code'); 53 | requiredConfigKeys.add('bundle'); 54 | } 55 | 56 | const compilePolicy = policy => { 57 | if (policy) { 58 | if (policy.include) { 59 | const includeSet = new Set(policy.include); 60 | if (policy.exclude) { 61 | for (const binding of policy.exclude) { 62 | includeSet.delete(binding); 63 | } 64 | } 65 | return binding => includeSet.has(binding); 66 | } 67 | 68 | if (policy.exclude) { 69 | const excludeSet = new Set(policy.exclude); 70 | return binding => excludeSet.has(binding); 71 | } 72 | } 73 | 74 | return null; 75 | }; 76 | 77 | am(async () => { 78 | let config; 79 | try { 80 | config = await parseConfigFile(configFilePath); 81 | } catch (err) { 82 | throw new VError(err, `Failed to load config JSON file ${JSON.stringify(configFilePath)}`); 83 | } 84 | 85 | const missingConfigKeys = iterate(requiredConfigKeys) 86 | .filter(key => !config[key]) 87 | .toArray(); 88 | if (missingConfigKeys.length > 0) { 89 | throw new Error( 90 | `Can't perform the requested operation(s) without the following config key(s): ${missingConfigKeys.join( 91 | ', ' 92 | )}` 93 | ); 94 | } 95 | 96 | const { 97 | graphs: graphFileGlobs, 98 | code: codeDirPath, 99 | trace: traceFilePath, 100 | report: reportFilePath, 101 | bundle: bundleConfig, 102 | } = config; 103 | 104 | const targets = config.targets 105 | ? Object.entries(config.targets).map(([name, data]) => ({ name, ...data })) 106 | : []; 107 | if (shouldIngest || shouldRewrite) { 108 | await Promise.all( 109 | targets.map(async target => { 110 | const origSrcFilePath = path.join(codeDirPath, `${target.name}.js`); 111 | 112 | let origSrc; 113 | try { 114 | origSrc = await fs.readFile(origSrcFilePath, { encoding: 'utf8' }); 115 | } catch (err) { 116 | throw new VError( 117 | err, 118 | `Failed to read target source file ${JSON.stringify(origSrcFilePath)}` 119 | ); 120 | } 121 | 122 | target.src = origSrc; 123 | target.srcHash = crypto.createHash('sha256').update(origSrc).digest('hex'); 124 | }) 125 | ); 126 | } 127 | 128 | if (shouldIngest) { 129 | const graphFilePaths = await glob(graphFileGlobs); 130 | const graphs = await Promise.all( 131 | graphFilePaths.map(async graphFilePath => { 132 | try { 133 | const graphSrc = await fs.readFile(graphFilePath, { encoding: 'utf8' }); 134 | return graphml.parse(MultiDirectedGraph, graphSrc); 135 | } catch (err) { 136 | throw new VError(err, `Failed to load Page Graph file ${JSON.stringify(graphFilePath)}`); 137 | } 138 | }) 139 | ); 140 | 141 | const tracesObj = Object.fromEntries( 142 | zip(targets, require('./ingest')(graphs, targets)).map(([target, trace]) => { 143 | target.trace = trace; 144 | return [target.name, { srcHash: target.srcHash, trace }]; 145 | }) 146 | ); 147 | 148 | try { 149 | await fs.writeFile(traceFilePath, JSON.stringify(tracesObj, null, 2), { encoding: 'utf8' }); 150 | } catch (err) { 151 | throw new VError(err, `Failed to write trace file ${JSON.stringify(traceFilePath)}`); 152 | } 153 | } else if (shouldReport || shouldRewrite) { 154 | let tracesObj; 155 | try { 156 | tracesObj = JSON.parse(await fs.readFile(traceFilePath, { encoding: 'utf8' })); 157 | } catch (err) { 158 | throw new VError(err, `Failed to load trace JSON file ${JSON.stringify(traceFilePath)}`); 159 | } 160 | 161 | for (const target of targets) { 162 | if (!Object.prototype.hasOwnProperty.call(tracesObj, target.name)) { 163 | throw new Error( 164 | `Trace file is missing an entry for target ${JSON.stringify(target.name)}` 165 | ); 166 | } 167 | const { srcHash, trace } = tracesObj[target.name]; 168 | if (target.srcHash !== srcHash) { 169 | throw new Error( 170 | `SHA-256 source hash for target ${JSON.stringify(target.name)} (${ 171 | target.srcHash 172 | }) doesn't match hash recorded in trace file (${srcHash})` 173 | ); 174 | } 175 | target.trace = trace; 176 | } 177 | } 178 | 179 | if (shouldReport) { 180 | const report = require('./report'); 181 | const reportTemplate = await report.loadReportTemplate(); 182 | const reportSrc = report(reportTemplate, targets); 183 | 184 | try { 185 | await fs.writeFile(reportFilePath, reportSrc, { encoding: 'utf8' }); 186 | } catch (err) { 187 | throw new VError(err, `Failed to write report file ${JSON.stringify(reportFilePath)}`); 188 | } 189 | } 190 | 191 | let resources; 192 | if (shouldBundle) { 193 | if (shouldRewrite) { 194 | resources = []; 195 | } else { 196 | } 197 | } 198 | 199 | if (shouldRewrite) { 200 | const rewrite = require('./rewrite'); 201 | 202 | let mocksMap; 203 | try { 204 | mocksMap = await rewrite.loadMocks(); 205 | } catch (err) { 206 | throw new VError(err, 'Failed to load mocks library'); 207 | } 208 | 209 | let recipesMap; 210 | try { 211 | recipesMap = await rewrite.loadRecipes(mocksMap); 212 | } catch (err) { 213 | throw new VError(err, 'Failed to load recipes library'); 214 | } 215 | 216 | await Promise.all( 217 | targets.flatMap(target => { 218 | const rewriteData = rewrite( 219 | mocksMap, 220 | recipesMap, 221 | target.name, 222 | target.src, 223 | target.trace, 224 | compilePolicy(target.policy) 225 | ); 226 | if (!rewriteData) { 227 | return []; 228 | } 229 | 230 | target.rewriteSrc = rewriteData.src; 231 | 232 | const rewriteSrcFilePath = path.join(codeDirPath, `${target.name}.js.0`); 233 | const rewriteSrcMapFilePath = `${rewriteSrcFilePath}.map`; 234 | return [ 235 | (async () => { 236 | try { 237 | await fs.writeFile(rewriteSrcFilePath, rewriteData.src, { encoding: 'utf8' }); 238 | } catch (err) { 239 | throw new VError( 240 | err, 241 | `Failed to write rewrite source file ${JSON.stringify(rewriteSrcFilePath)}` 242 | ); 243 | } 244 | })(), 245 | (async () => { 246 | try { 247 | await fs.writeFile(rewriteSrcMapFilePath, rewriteData.srcMap, { encoding: 'utf8' }); 248 | } catch (err) { 249 | throw new VError( 250 | err, 251 | `Failed to write rewrite source map file ${JSON.stringify(rewriteSrcMapFilePath)}` 252 | ); 253 | } 254 | })(), 255 | ]; 256 | }) 257 | ); 258 | } else if (shouldBundle) { 259 | await Promise.all( 260 | targets.map(async target => { 261 | const rewriteSrcFilePath = path.join(codeDirPath, `${target.name}.js.0`); 262 | if (!(await fs.pathExists(rewriteSrcFilePath))) { 263 | return; 264 | } 265 | 266 | let rewriteSrc; 267 | try { 268 | rewriteSrc = await fs.readFile(rewritesSrcFilePath, { encoding: 'utf8' }); 269 | } catch (err) { 270 | throw new VError( 271 | err, 272 | `Failed to read rewrite source file ${JSON.stringify(rewriteSrcFilePath)}` 273 | ); 274 | } 275 | target.rewriteSrc = rewriteSrc; 276 | }) 277 | ); 278 | } 279 | 280 | if (shouldBundle) { 281 | const { rules: rulesFilePath, resources: resourcesFilePath } = bundleConfig; 282 | 283 | const bundle = await require('./bundle')( 284 | targets.map(target => ({ 285 | name: `sugarcoat-${target.name}`, 286 | src: target.src, 287 | patterns: target.patterns, 288 | })) 289 | ); 290 | 291 | await Promise.all([ 292 | (async () => { 293 | try { 294 | await fs.writeFile(rulesFilePath, bundle.rules.join('\n'), { encoding: 'utf8' }); 295 | } catch (err) { 296 | throw new VError(err, `Failed to write rules file ${JSON.stringify(rulesFilePath)}`); 297 | } 298 | })(), 299 | (async () => { 300 | try { 301 | await fs.writeFile(resourcesFilePath, JSON.stringify(bundle.resources, null, 2), { 302 | encoding: 'utf8', 303 | }); 304 | } catch (err) { 305 | throw new VError( 306 | err, 307 | `Failed to write resources file ${JSON.stringify(resourcesFilePath)}` 308 | ); 309 | } 310 | })(), 311 | ]); 312 | } 313 | }); 314 | -------------------------------------------------------------------------------- /mocks/xmlHttpRequest.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | // XMLHttpRequest API 4 | // 5 | 6 | 'use strict'; 7 | 8 | const xhrUnsent = 0; 9 | const xhrOpened = 1; 10 | const xhrHeadersReceived = 2; 11 | const xhrLoading = 3; 12 | const xhrDone = 4; 13 | 14 | const xhrDeferredHandleSymbol = Symbol('deferredHandle'); 15 | 16 | const xhrOnLoadStartSymbol = Symbol('onloadstart'); 17 | const xhrOnProgressSymbol = Symbol('onprogress'); 18 | const xhrOnAbortSymbol = Symbol('onabort'); 19 | const xhrOnErrorSymbol = Symbol('onerror'); 20 | const xhrOnLoadSymbol = Symbol('onload'); 21 | const xhrOnTimeoutSymbol = Symbol('ontimeout'); 22 | const xhrOnLoadEndSymbol = Symbol('onloadend'); 23 | 24 | const xhrOnReadyStateChangeSymbol = Symbol('onreadystatechange'); 25 | const xhrReadyStateSymbol = Symbol('readyState'); 26 | const xhrTimeoutSymbol = Symbol('timeout'); 27 | const xhrWithCredentialsSymbol = Symbol('withCredentials'); 28 | const xhrUploadSymbol = Symbol('upload'); 29 | const xhrResponseTypeSymbol = Symbol('responseType'); 30 | 31 | const defineEvent = (obj, symbol) => { 32 | const type = symbol.description.substring(2); 33 | 34 | Object.defineProperty(obj, symbol, { 35 | configurable: false, 36 | enumerable: false, 37 | value: null, 38 | writable: true, 39 | }); 40 | 41 | obj.addEventListener(type, function (event) { 42 | const handler = this[symbol]; 43 | if (handler) { 44 | handler.call(this, event); 45 | } 46 | }); 47 | }; 48 | 49 | const changeReadyState = (xhr, readyState) => { 50 | xhr[xhrReadyStateSymbol] = readyState; 51 | xhr.dispatchEvent(new Event('readystatechange')); 52 | }; 53 | 54 | let isSealed = true; 55 | 56 | class XMLHttpRequestEventTarget extends EventTarget { 57 | constructor () { 58 | super(); 59 | 60 | if (!(this instanceof XMLHttpRequest) && !(this instanceof XMLHttpRequestUpload)) { 61 | throw new TypeError('Illegal constructor'); 62 | } 63 | 64 | defineEvent(this, xhrOnLoadStartSymbol); 65 | defineEvent(this, xhrOnProgressSymbol); 66 | defineEvent(this, xhrOnAbortSymbol); 67 | defineEvent(this, xhrOnErrorSymbol); 68 | defineEvent(this, xhrOnLoadSymbol); 69 | defineEvent(this, xhrOnTimeoutSymbol); 70 | defineEvent(this, xhrOnLoadEndSymbol); 71 | } 72 | 73 | get onloadstart () { 74 | return this[xhrOnLoadStartSymbol]; 75 | } 76 | 77 | set onloadstart (value) { 78 | this[xhrOnLoadStartSymbol] = value; 79 | } 80 | 81 | get onprogress () { 82 | return this[xhrOnProgressSymbol]; 83 | } 84 | 85 | set onprogress (value) { 86 | this[xhrOnProgressSymbol] = value; 87 | } 88 | 89 | get onabort () { 90 | return this[xhrOnAbortSymbol]; 91 | } 92 | 93 | set onabort (value) { 94 | this[xhrOnAbortSymbol] = value; 95 | } 96 | 97 | get onerror () { 98 | return this[xhrOnErrorSymbol]; 99 | } 100 | 101 | set onerror (value) { 102 | this[xhrOnErrorSymbol] = value; 103 | } 104 | 105 | get ontimeout () { 106 | return this[xhrOnTimeoutSymbol]; 107 | } 108 | 109 | set ontimeout (value) { 110 | this[xhrOnTimeoutSymbol] = value; 111 | } 112 | 113 | get onloadend () { 114 | return this[xhrOnLoadEndSymbol]; 115 | } 116 | 117 | set onloadend (value) { 118 | this[xhrOnLoadEndSymbol] = value; 119 | } 120 | } 121 | 122 | exports.XMLHttpRequestEventTarget = { 123 | configurable: true, 124 | enumerable: true, 125 | value: XMLHttpRequestEventTarget, 126 | writable: true, 127 | }; 128 | 129 | class XMLHttpRequestUpload extends XMLHttpRequestEventTarget { 130 | constructor () { 131 | if (isSealed) { 132 | throw new TypeError('Illegal constructor'); 133 | } 134 | 135 | super(); 136 | } 137 | } 138 | 139 | exports.XMLHttpRequestUpload = { 140 | configurable: true, 141 | enumerable: true, 142 | value: XMLHttpRequestUpload, 143 | writable: true, 144 | }; 145 | 146 | class XMLHttpRequest extends XMLHttpRequestEventTarget { 147 | constructor () { 148 | super(); 149 | 150 | isSealed = false; 151 | const xhrUpload = new XMLHttpRequestUpload(); 152 | isSealed = true; 153 | 154 | Object.defineProperty(this, xhrDeferredHandleSymbol, { 155 | configurable: false, 156 | enumerable: false, 157 | value: null, 158 | writable: true, 159 | }); 160 | 161 | defineEvent(this, xhrOnReadyStateChangeSymbol); 162 | 163 | Object.defineProperty(this, xhrReadyStateSymbol, { 164 | configurable: false, 165 | enumerable: false, 166 | value: xhrUnsent, 167 | writable: true, 168 | }); 169 | 170 | Object.defineProperty(this, xhrTimeoutSymbol, { 171 | configurable: false, 172 | enumerable: false, 173 | value: 0, 174 | writable: true, 175 | }); 176 | 177 | Object.defineProperty(this, xhrWithCredentialsSymbol, { 178 | configurable: false, 179 | enumerable: false, 180 | value: false, 181 | writable: true, 182 | }); 183 | 184 | Object.defineProperty(this, xhrUploadSymbol, { 185 | configurable: false, 186 | enumerable: false, 187 | value: xhrUpload, 188 | writable: false, 189 | }); 190 | 191 | Object.defineProperty(this, xhrResponseTypeSymbol, { 192 | configurable: false, 193 | enumerable: false, 194 | value: '', 195 | writable: true, 196 | }); 197 | } 198 | 199 | get onreadystatechange () { 200 | return this[xhrOnReadyStateChangeSymbol]; 201 | } 202 | 203 | set onreadystatechange (value) { 204 | this[xhrOnReadyStateChangeSymbol] = value; 205 | } 206 | 207 | get readyState () { 208 | return this[xhrReadyStateSymbol]; 209 | } 210 | 211 | open (method, url) { 212 | switch (this[xhrReadyStateSymbol]) { 213 | case xhrUnsent: 214 | case xhrDone: { 215 | changeReadyState(this, xhrOpened); 216 | break; 217 | } 218 | } 219 | } 220 | 221 | setRequestHeader (name, value) {} 222 | 223 | setTrustToken (trustToken) {} 224 | 225 | get timeout () { 226 | return this[xhrTimeoutSymbol]; 227 | } 228 | 229 | set timeout (value) { 230 | this[xhrTimeoutSymbol] = value; 231 | } 232 | 233 | get withCredentials () { 234 | return this[xhrWithCredentialsSymbol]; 235 | } 236 | 237 | set withCredentials (value) { 238 | switch (this[xhrReadyStateSymbol]) { 239 | case xhrUnsent: 240 | case xhrOpened: { 241 | break; 242 | } 243 | default: { 244 | throw new DOMException( 245 | "Failed to set the 'withCredentials' property on 'XMLHttpRequest': The value may only be set if the object's state is UNSENT or OPENED." 246 | ); 247 | } 248 | } 249 | 250 | this[xhrWithCredentialsSymbol] = !!value; 251 | } 252 | 253 | get upload () { 254 | return this[xhrUploadSymbol]; 255 | } 256 | 257 | send () { 258 | if (this[xhrReadyStateSymbol] === xhrOpened && this[xhrDeferredHandleSymbol] === null) { 259 | this[xhrDeferredHandleSymbol] = setTimeout(() => { 260 | this[xhrDeferredHandleSymbol] = null; 261 | changeReadyState(this, xhrDone); 262 | this.dispatchEvent(new ProgressEvent('error')); 263 | this.dispatchEvent(new ProgressEvent('loadend')); 264 | }, 0); 265 | } else { 266 | throw new DOMException( 267 | "Failed to execute 'send' on 'XMLHttpRequest': The object's state must be OPENED." 268 | ); 269 | } 270 | } 271 | 272 | abort () { 273 | if (this[xhrReadyStateSymbol] === xhrOpened && this[xhrDeferredHandleSymbol] !== null) { 274 | clearTimeout(this[xhrDeferredHandleSymbol]); 275 | this[xhrDeferredHandleSymbol] = null; 276 | 277 | changeReadyState(this, xhrUnsent); 278 | this.dispatchEvent(new ProgressEvent('abort')); 279 | this.dispatchEvent(new ProgressEvent('loadend')); 280 | } 281 | } 282 | 283 | get responseURL () { 284 | return ''; 285 | } 286 | 287 | get status () { 288 | return 0; 289 | } 290 | 291 | get statusText () { 292 | return ''; 293 | } 294 | 295 | getResponseHeader (name) { 296 | return null; 297 | } 298 | 299 | overrideMimeType (mime) {} 300 | 301 | get responseType () { 302 | return this[xhrResponseTypeSymbol]; 303 | } 304 | 305 | set responseType (value) { 306 | switch (this[xhrReadyStateSymbol]) { 307 | case xhrDone: { 308 | throw new DOMException( 309 | "Failed to set the 'responseType' property on 'XMLHttpRequest': The response type cannot be set if the object's state is LOADING or DONE." 310 | ); 311 | } 312 | } 313 | 314 | switch (value) { 315 | case '': 316 | case 'arraybuffer': 317 | case 'blob': 318 | case 'document': 319 | case 'json': 320 | case 'text': { 321 | this[xhrResponseTypeSymbol] = value; 322 | break; 323 | } 324 | } 325 | } 326 | 327 | get response () { 328 | const responseType = this[xhrResponseTypeSymbol]; 329 | return responseType === '' || responseType === 'text' ? '' : null; 330 | } 331 | 332 | get responseText () { 333 | const responseType = this[xhrResponseTypeSymbol]; 334 | if (responseType === '' || responseType === 'text') { 335 | return ''; 336 | } else { 337 | throw new DOMException( 338 | "Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'arraybuffer')." 339 | ); 340 | } 341 | } 342 | 343 | get responseXML () { 344 | return null; 345 | } 346 | } 347 | 348 | Object.defineProperty(XMLHttpRequest, 'UNSENT', { 349 | configurable: false, 350 | enumerable: true, 351 | value: xhrUnsent, 352 | }); 353 | 354 | Object.defineProperty(XMLHttpRequest, 'OPENED', { 355 | configurable: false, 356 | enumerable: true, 357 | value: xhrOpened, 358 | }); 359 | 360 | Object.defineProperty(XMLHttpRequest, 'HEADERS_RECEIVED', { 361 | configurable: false, 362 | enumerable: true, 363 | value: xhrHeadersReceived, 364 | }); 365 | 366 | Object.defineProperty(XMLHttpRequest, 'LOADING', { 367 | configurable: false, 368 | enumerable: true, 369 | value: xhrLoading, 370 | }); 371 | 372 | Object.defineProperty(XMLHttpRequest, 'DONE', { 373 | configurable: false, 374 | enumerable: true, 375 | value: xhrDone, 376 | }); 377 | 378 | exports.XMLHttpRequest = { 379 | configurable: true, 380 | enumerable: true, 381 | value: XMLHttpRequest, 382 | writable: true, 383 | }; 384 | -------------------------------------------------------------------------------- /rewrite.js: -------------------------------------------------------------------------------- 1 | // vim: set tw=99 ts=2 sw=2 et: 2 | 3 | 'use strict'; 4 | 5 | const path = require('path'); 6 | 7 | const cryptoRandomString = require('crypto-random-string'); 8 | const escodegen = require('escodegen'); 9 | const esprima = require('esprima'); 10 | const fs = require('fs-extra'); 11 | const { iterate } = require('iterare'); 12 | 13 | const generateRandomVariableName = prefix => 14 | `$___${prefix}_${cryptoRandomString({ length: 16, type: 'hex' })}`; 15 | 16 | const isNodeLike = value => Object.prototype.hasOwnProperty.call(value, 'type'); 17 | 18 | const objectConstructorExpression = { 19 | type: 'MemberExpression', 20 | computed: false, 21 | object: { 22 | type: 'ObjectExpression', 23 | properties: [], 24 | }, 25 | property: { 26 | type: 'Identifier', 27 | name: 'constructor', 28 | }, 29 | }; 30 | 31 | const rewriteNode = (accesses, node, preludeStatements = null) => { 32 | let bodyStatements = null; 33 | 34 | switch (node.type) { 35 | case 'Program': { 36 | bodyStatements = node.body; 37 | break; 38 | } 39 | case 'ArrowFunctionExpression': 40 | case 'FunctionDeclaration': 41 | case 'FunctionExpression': { 42 | if (node.type === 'ArrowFunctionExpression' && node.expression) { 43 | node.body = { 44 | type: 'BlockStatement', 45 | body: [ 46 | { 47 | type: 'ReturnStatement', 48 | argument: node.body, 49 | }, 50 | ], 51 | }; 52 | node.expression = false; 53 | } 54 | 55 | bodyStatements = node.body.body; 56 | 57 | for (const param of node.params) { 58 | if (param.type === 'AssignmentPattern') { 59 | param.right = { 60 | type: 'CallExpression', 61 | callee: { 62 | type: 'ArrowFunctionExpression', 63 | params: [], 64 | body: param.right, 65 | expression: true, 66 | range: param.right.range, 67 | }, 68 | arguments: [], 69 | }; 70 | 71 | rewriteNode(accesses, param.right); 72 | } 73 | } 74 | 75 | break; 76 | } 77 | } 78 | 79 | if (bodyStatements) { 80 | const [start, end] = node.range; 81 | 82 | let indexOfFirstAccessInRange = null; 83 | let numAccessesInRange = 0; 84 | for (let accessIndex = 0; accessIndex < accesses.length; ++accessIndex) { 85 | const access = accesses[accessIndex]; 86 | 87 | if (access.position >= end) { 88 | break; 89 | } 90 | 91 | if (indexOfFirstAccessInRange == null) { 92 | if (access.position < start) { 93 | continue; 94 | } 95 | indexOfFirstAccessInRange = accessIndex; 96 | } 97 | 98 | ++numAccessesInRange; 99 | } 100 | 101 | accesses = 102 | indexOfFirstAccessInRange == null 103 | ? [] 104 | : accesses.splice(indexOfFirstAccessInRange, numAccessesInRange); 105 | } 106 | 107 | traverseObjectAndRewriteNodes(accesses, node); 108 | 109 | if (bodyStatements) { 110 | if (bodyStatements.length > 0 && accesses.length > 0) { 111 | const recipes = Array.from(new Set(accesses.map(access => access.recipe))); 112 | injectRewriteWrapper(recipes, bodyStatements, preludeStatements); 113 | } else if (preludeStatements) { 114 | const innerStatements = [...bodyStatements]; 115 | const outerStatements = [ 116 | { 117 | type: 'BlockStatement', 118 | body: [...preludeStatements, iifeDelegate(innerStatements, true)], 119 | }, 120 | ]; 121 | hoistVariables(outerStatements, innerStatements); 122 | bodyStatements.splice(0, bodyStatements.length, ...outerStatements); 123 | } 124 | } 125 | }; 126 | 127 | const traverseObjectAndRewriteNodes = (accesses, thing) => { 128 | for (const value of Object.values(thing)) { 129 | traverseAndRewriteNodes(accesses, value); 130 | } 131 | }; 132 | 133 | const traverseAndRewriteNodes = (accesses, thing) => { 134 | if (!thing || typeof thing !== 'object') { 135 | return; 136 | } 137 | 138 | if (Array.isArray(thing)) { 139 | for (const item of thing) { 140 | traverseAndRewriteNodes(accesses, item); 141 | } 142 | } else if (isNodeLike(thing)) { 143 | rewriteNode(accesses, thing); 144 | } else { 145 | traverseObjectAndRewriteNodes(accesses, thing); 146 | } 147 | }; 148 | 149 | const injectRewriteWrapper = (recipes, bodyStatements, preludeStatements = null) => { 150 | const isTopLevel = !!preludeStatements; 151 | 152 | const oldDescriptorVariableNames = recipes.map(() => generateRandomVariableName('old')); 153 | 154 | const oldDescriptorVariableDeclarators = recipes.map((recipe, recipeIndex) => ({ 155 | type: 'VariableDeclarator', 156 | id: { 157 | type: 'Identifier', 158 | name: oldDescriptorVariableNames[recipeIndex], 159 | }, 160 | init: { 161 | type: 'CallExpression', 162 | callee: { 163 | type: 'MemberExpression', 164 | computed: false, 165 | object: objectConstructorExpression, 166 | property: { 167 | type: 'Identifier', 168 | name: 'getOwnPropertyDescriptor', 169 | }, 170 | }, 171 | arguments: [ 172 | recipe.sourceObject, 173 | { 174 | type: 'Literal', 175 | value: recipe.sourceProperty, 176 | }, 177 | ], 178 | }, 179 | })); 180 | 181 | const applyRecipeStatements = recipes.map((recipe, recipeIndex) => ({ 182 | type: 'IfStatement', 183 | test: { 184 | type: 'Identifier', 185 | name: oldDescriptorVariableNames[recipeIndex], 186 | }, 187 | consequent: { 188 | type: 'ExpressionStatement', 189 | expression: recipe.destination 190 | ? { 191 | type: 'CallExpression', 192 | callee: { 193 | type: 'MemberExpression', 194 | computed: false, 195 | object: objectConstructorExpression, 196 | property: { 197 | type: 'Identifier', 198 | name: 'defineProperty', 199 | }, 200 | }, 201 | arguments: [ 202 | recipe.sourceObject, 203 | { 204 | type: 'Literal', 205 | value: recipe.sourceProperty, 206 | }, 207 | recipe.destination, 208 | ], 209 | } 210 | : { 211 | type: 'UnaryExpression', 212 | operator: 'delete', 213 | prefix: true, 214 | argument: { 215 | type: 'MemberExpression', 216 | computed: false, 217 | object: recipe.sourceObject, 218 | property: { type: 'Identifier', name: recipe.sourceProperty }, 219 | }, 220 | }, 221 | }, 222 | })); 223 | 224 | const undoRecipeStatements = recipes.map((recipe, recipeIndex) => { 225 | const oldDescriptorVariableName = oldDescriptorVariableNames[recipeIndex]; 226 | return { 227 | type: 'IfStatement', 228 | test: { 229 | type: 'Identifier', 230 | name: oldDescriptorVariableName, 231 | }, 232 | consequent: { 233 | type: 'ExpressionStatement', 234 | expression: { 235 | type: 'CallExpression', 236 | callee: { 237 | type: 'MemberExpression', 238 | computed: false, 239 | object: objectConstructorExpression, 240 | property: { 241 | type: 'Identifier', 242 | name: 'defineProperty', 243 | }, 244 | }, 245 | arguments: [ 246 | recipe.sourceObject, 247 | { 248 | type: 'Literal', 249 | value: recipe.sourceProperty, 250 | }, 251 | { 252 | type: 'Identifier', 253 | name: oldDescriptorVariableName, 254 | }, 255 | ], 256 | }, 257 | }, 258 | }; 259 | }); 260 | 261 | const innerStatements = [...bodyStatements]; 262 | 263 | let outerStatements = [ 264 | ...(preludeStatements || []), 265 | { 266 | type: 'VariableDeclaration', 267 | kind: 'const', 268 | declarations: oldDescriptorVariableDeclarators, 269 | }, 270 | { 271 | type: 'TryStatement', 272 | block: { 273 | type: 'BlockStatement', 274 | body: [...applyRecipeStatements, iifeDelegate(innerStatements, isTopLevel)], 275 | }, 276 | handler: null, 277 | finalizer: { 278 | type: 'BlockStatement', 279 | body: undoRecipeStatements, 280 | }, 281 | }, 282 | ]; 283 | 284 | if (isTopLevel) { 285 | outerStatements = [ 286 | { 287 | type: 'BlockStatement', 288 | body: outerStatements, 289 | }, 290 | ]; 291 | 292 | hoistVariables(outerStatements, innerStatements); 293 | } 294 | 295 | bodyStatements.splice(0, bodyStatements.length, ...outerStatements); 296 | }; 297 | 298 | const iifeDelegate = (bodyStatements, isTopLevel = false) => { 299 | const functionExpression = { 300 | type: 'FunctionExpression', 301 | params: [], 302 | body: { 303 | type: 'BlockStatement', 304 | body: bodyStatements, 305 | }, 306 | }; 307 | 308 | return isTopLevel 309 | ? { 310 | type: 'CallExpression', 311 | callee: functionExpression, 312 | arguments: [], 313 | } 314 | : { 315 | type: 'ReturnStatement', 316 | argument: { 317 | type: 'CallExpression', 318 | callee: { 319 | type: 'MemberExpression', 320 | computed: false, 321 | object: functionExpression, 322 | property: { 323 | type: 'Identifier', 324 | name: 'apply', 325 | }, 326 | }, 327 | arguments: [ 328 | { 329 | type: 'ThisExpression', 330 | }, 331 | { 332 | type: 'Identifier', 333 | name: 'arguments', 334 | }, 335 | ], 336 | }, 337 | }; 338 | }; 339 | 340 | const hoistVariables = (outerStatements, innerStatements) => { 341 | const hoistedOldStyleVariableDeclarators = []; 342 | const hoistedNewStyleVariableDeclarators = []; 343 | const hoistStatementsAndIndices = []; 344 | const functionDeclarationHoistStatements = []; 345 | 346 | for (let index = 0; index < innerStatements.length; ++index) { 347 | const statement = innerStatements[index]; 348 | 349 | let declarations = null; 350 | let hoistedVariableDeclarators = null; 351 | let isFunctionDeclaration = false; 352 | switch (statement.type) { 353 | case 'VariableDeclaration': { 354 | declarations = statement.declarations; 355 | hoistedVariableDeclarators = 356 | statement.kind === 'var' 357 | ? hoistedOldStyleVariableDeclarators 358 | : hoistedNewStyleVariableDeclarators; 359 | break; 360 | } 361 | case 'FunctionDeclaration': { 362 | declarations = [statement]; 363 | hoistedVariableDeclarators = hoistedOldStyleVariableDeclarators; 364 | isFunctionDeclaration = true; 365 | break; 366 | } 367 | default: { 368 | continue; 369 | } 370 | } 371 | 372 | for (const declarator of declarations) { 373 | const replacements = replaceDeclaredVariableNames(declarator.id); 374 | 375 | for (const replacement of replacements) { 376 | hoistedVariableDeclarators.push({ 377 | type: 'VariableDeclarator', 378 | id: { 379 | type: 'Identifier', 380 | name: replacement.oldName, 381 | }, 382 | }); 383 | 384 | const hoistStatement = { 385 | type: 'ExpressionStatement', 386 | expression: { 387 | type: 'AssignmentExpression', 388 | operator: '=', 389 | left: { 390 | type: 'Identifier', 391 | name: replacement.oldName, 392 | }, 393 | right: { 394 | type: 'Identifier', 395 | name: replacement.newName, 396 | }, 397 | }, 398 | }; 399 | 400 | if (isFunctionDeclaration) { 401 | functionDeclarationHoistStatements.push(hoistStatement, { 402 | type: 'ExpressionStatement', 403 | expression: { 404 | type: 'CallExpression', 405 | callee: { 406 | type: 'MemberExpression', 407 | computed: false, 408 | object: objectConstructorExpression, 409 | property: { 410 | type: 'Identifier', 411 | name: 'defineProperty', 412 | }, 413 | }, 414 | arguments: [ 415 | { 416 | type: 'Identifier', 417 | name: replacement.oldName, 418 | }, 419 | { 420 | type: 'Literal', 421 | value: 'name', 422 | }, 423 | { 424 | type: 'ObjectExpression', 425 | properties: [ 426 | { 427 | type: 'Property', 428 | key: { 429 | type: 'Identifier', 430 | name: 'configurable', 431 | }, 432 | computed: false, 433 | value: { 434 | type: 'Literal', 435 | value: true, 436 | }, 437 | kind: 'init', 438 | }, 439 | { 440 | type: 'Property', 441 | key: { 442 | type: 'Identifier', 443 | name: 'enumerable', 444 | }, 445 | computed: false, 446 | value: { 447 | type: 'Literal', 448 | value: false, 449 | }, 450 | kind: 'init', 451 | }, 452 | { 453 | type: 'Property', 454 | key: { 455 | type: 'Identifier', 456 | name: 'value', 457 | }, 458 | computed: false, 459 | value: { 460 | type: 'Literal', 461 | value: replacement.oldName, 462 | }, 463 | kind: 'init', 464 | }, 465 | { 466 | type: 'Property', 467 | key: { 468 | type: 'Identifier', 469 | name: 'writable', 470 | }, 471 | computed: false, 472 | value: { 473 | type: 'Literal', 474 | value: false, 475 | }, 476 | kind: 'init', 477 | }, 478 | ], 479 | }, 480 | ], 481 | }, 482 | }); 483 | } else { 484 | hoistStatementsAndIndices.push({ 485 | statement: hoistStatement, 486 | index, 487 | }); 488 | } 489 | } 490 | } 491 | } 492 | 493 | if (hoistedNewStyleVariableDeclarators.length > 0) { 494 | outerStatements.unshift({ 495 | type: 'VariableDeclaration', 496 | kind: 'let', 497 | declarations: hoistedNewStyleVariableDeclarators, 498 | }); 499 | } 500 | 501 | if (hoistedOldStyleVariableDeclarators.length > 0) { 502 | outerStatements.unshift({ 503 | type: 'VariableDeclaration', 504 | kind: 'var', 505 | declarations: hoistedOldStyleVariableDeclarators, 506 | }); 507 | } 508 | 509 | for (let index = 0; index < hoistStatementsAndIndices.length; ++index) { 510 | const entry = hoistStatementsAndIndices[index]; 511 | innerStatements.splice(index + entry.index + 1, 0, entry.statement); 512 | } 513 | 514 | innerStatements.unshift(...functionDeclarationHoistStatements); 515 | }; 516 | 517 | const replaceDeclaredVariableNames = node => { 518 | if (node == null) { 519 | return []; 520 | } 521 | 522 | switch (node.type) { 523 | case 'ArrayPattern': { 524 | return node.elements.flatMap(item => replaceDeclaredVariableNames(item)); 525 | } 526 | case 'AssignmentPattern': { 527 | return replaceDeclaredVariableNames(node.left); 528 | } 529 | case 'Identifier': { 530 | const oldName = node.name; 531 | const newName = (node.name = generateRandomVariableName('var')); 532 | return [{ oldName, newName }]; 533 | } 534 | case 'ObjectPattern': { 535 | return node.properties.flatMap(property => { 536 | if (property.value == null) { 537 | const oldName = property.key; 538 | const newName = (property.key = generateRandomVariableName('var')); 539 | return [{ oldName, newName }]; 540 | } else { 541 | return extractDeclaredVariableNames(property.value); 542 | } 543 | }); 544 | } 545 | case 'RestElement': { 546 | return extractDeclaredVariableNames(node.argument); 547 | } 548 | default: { 549 | throw new RangeError(`Unexpected node type: ${node.type}`); 550 | } 551 | } 552 | }; 553 | 554 | const readDirToMap = async (dirPath, ext, f) => { 555 | const fileNames = await fs.readdir(dirPath); 556 | return new Map( 557 | ( 558 | await Promise.all( 559 | fileNames.map(fileName => { 560 | if (path.extname(fileName) !== ext) { 561 | return null; 562 | } 563 | const name = path.basename(fileName, ext); 564 | const filePath = path.join(dirPath, fileName); 565 | return (async () => [name, f(await fs.readFile(filePath, { encoding: 'utf8' }))])(); 566 | }) 567 | ) 568 | ).filter(entry => entry) 569 | ); 570 | }; 571 | 572 | const rewrite = (mocksMap, recipesMap, scriptName, scriptSrc, trace, policy = null) => { 573 | const script = esprima.parseScript(scriptSrc, { loc: true, range: true, source: scriptName }); 574 | 575 | const accesses = trace 576 | .map(entry => { 577 | if (policy && !policy(entry.binding)) { 578 | return null; 579 | } 580 | const recipe = recipesMap.get(entry.binding); 581 | if (recipe) { 582 | return { 583 | position: entry.position, 584 | recipe: recipesMap.get(entry.binding), 585 | }; 586 | } else { 587 | return null; 588 | } 589 | }) 590 | .filter(access => access); 591 | 592 | if (accesses.length < 1) { 593 | return null; 594 | } 595 | 596 | const usedRecipes = new Set(accesses.map(access => access.recipe)); 597 | const usedMocks = new Set( 598 | iterate(usedRecipes) 599 | .map(recipe => recipe.destinationMock) 600 | .filter(mock => mock) 601 | ); 602 | const mockInitializationStatements = iterate(usedMocks) 603 | .map(mock => mock.initializationStatements) 604 | .flatten() 605 | .toArray(); 606 | 607 | rewriteNode(accesses, script, mockInitializationStatements); 608 | 609 | const { code: rewriteSrc, map: rewriteSrcMap } = escodegen.generate(script, { 610 | /* 611 | format: { 612 | compact: true, 613 | }, 614 | */ 615 | sourceMap: true, 616 | sourceMapWithCode: true, 617 | }); 618 | return { src: rewriteSrc, srcMap: rewriteSrcMap.toString() }; 619 | }; 620 | module.exports = rewrite; 621 | 622 | const mocksDirPath = path.join(__dirname, 'mocks'); 623 | const loadMocks = async () => { 624 | const mocksMap = await readDirToMap(mocksDirPath, '.js', src => ({ src })); 625 | for (const mock of mocksMap.values()) { 626 | const mockBody = esprima.parseScript(mock.src).body; 627 | delete mock.src; 628 | 629 | mock.variableName = generateRandomVariableName('mock'); 630 | mock.initializationStatements = [ 631 | { 632 | type: 'VariableDeclaration', 633 | declarations: [ 634 | { 635 | type: 'VariableDeclarator', 636 | id: { 637 | type: 'Identifier', 638 | name: mock.variableName, 639 | }, 640 | init: { 641 | type: 'ObjectExpression', 642 | properties: [], 643 | }, 644 | }, 645 | ], 646 | kind: 'const', 647 | }, 648 | { 649 | type: 'ExpressionStatement', 650 | expression: { 651 | type: 'CallExpression', 652 | callee: { 653 | type: 'ArrowFunctionExpression', 654 | params: [ 655 | { 656 | type: 'Identifier', 657 | name: 'exports', 658 | }, 659 | ], 660 | body: { 661 | type: 'BlockStatement', 662 | body: mockBody, 663 | }, 664 | }, 665 | arguments: [ 666 | { 667 | type: 'Identifier', 668 | name: mock.variableName, 669 | }, 670 | ], 671 | }, 672 | }, 673 | ]; 674 | } 675 | return mocksMap; 676 | }; 677 | rewrite.loadMocks = loadMocks; 678 | 679 | const recipesDirPath = path.join(__dirname, 'recipes'); 680 | const loadRecipes = async mocksMap => { 681 | const recipesMap = await readDirToMap(recipesDirPath, '.json', src => JSON.parse(src)); 682 | for (const recipe of recipesMap.values()) { 683 | recipe.sourceObject = recipe.sourceObject.reduce( 684 | (accumulator, currentValue) => 685 | accumulator 686 | ? { 687 | type: 'MemberExpression', 688 | computed: false, 689 | object: accumulator, 690 | property: { type: 'Identifier', name: currentValue }, 691 | } 692 | : { type: 'Identifier', name: currentValue }, 693 | null 694 | ); 695 | 696 | if (recipe.destinationMock) { 697 | recipe.destinationMock = mocksMap.get(recipe.destinationMock); 698 | 699 | recipe.destination = { 700 | type: 'MemberExpression', 701 | object: { 702 | type: 'Identifier', 703 | name: recipe.destinationMock.variableName, 704 | }, 705 | property: { 706 | type: 'Identifier', 707 | name: recipe.destinationProperty || recipe.sourceProperty, 708 | }, 709 | }; 710 | } else { 711 | recipe.destination = null; 712 | } 713 | } 714 | return recipesMap; 715 | }; 716 | rewrite.loadRecipes = loadRecipes; 717 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | ajv: 6.12.4 3 | am: 1.0.2 4 | await-sleep: 0.0.1 5 | better-ajv-errors: 0.6.7_ajv@6.12.4 6 | commander: 6.0.0 7 | crypto-random-string: 3.2.0 8 | escodegen: 1.14.3 9 | esprima: 4.0.1 10 | fast-glob: 3.2.4 11 | fs-extra: 9.0.1 12 | graphology: 0.17.1 13 | graphology-graphml: 0.2.0 14 | handlebars: 4.7.6 15 | iterare: 1.2.1 16 | jsonlint: 1.6.3 17 | line-column: 1.0.2 18 | lodash.groupby: 4.6.0 19 | lodash.sortby: 4.7.0 20 | puppeteer-core: 1.20.0 21 | sanitize-filename: 1.6.3 22 | tmp-promise: 3.0.2 23 | verror: 1.10.0 24 | devDependencies: 25 | prettierx: 0.14.0 26 | lockfileVersion: 5.1 27 | packages: 28 | /@angular/compiler/9.0.5: 29 | dev: true 30 | peerDependencies: 31 | tslib: ^1.10.0 32 | resolution: 33 | integrity: sha512-TeyhRGefTOtA9N3udMrvheafoXcz/dvTTdZLcieeZQxm1SSeaQDUQ/rUH6QTOiHVNMtjOCrZ9J5rk1A4mPYuag== 34 | /@babel/code-frame/7.10.4: 35 | dependencies: 36 | '@babel/highlight': 7.10.4 37 | resolution: 38 | integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== 39 | /@babel/helper-validator-identifier/7.10.4: 40 | resolution: 41 | integrity: sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== 42 | /@babel/highlight/7.10.4: 43 | dependencies: 44 | '@babel/helper-validator-identifier': 7.10.4 45 | chalk: 2.4.2 46 | js-tokens: 4.0.0 47 | resolution: 48 | integrity: sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== 49 | /@babel/parser/7.11.3: 50 | dev: true 51 | engines: 52 | node: '>=6.0.0' 53 | hasBin: true 54 | resolution: 55 | integrity: sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== 56 | /@babel/runtime/7.11.2: 57 | dependencies: 58 | regenerator-runtime: 0.13.7 59 | dev: false 60 | resolution: 61 | integrity: sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== 62 | /@glimmer/env/0.1.7: 63 | dev: true 64 | resolution: 65 | integrity: sha1-/S0rVakCnGs3psk16MiHGucN+gc= 66 | /@glimmer/interfaces/0.56.1: 67 | dependencies: 68 | '@simple-dom/interface': 1.4.0 69 | dev: true 70 | resolution: 71 | integrity: sha512-+0KvSd7c9QmkEeCFHaBDub1DBeTONw+x6MZUcb/MlA3FfNis2aFs7kHVkjkdzp0Ust54Wn448dgWZFW27EuVJA== 72 | /@glimmer/syntax/0.56.1: 73 | dependencies: 74 | '@glimmer/interfaces': 0.56.1 75 | '@glimmer/util': 0.56.1 76 | handlebars: 4.7.6 77 | simple-html-tokenizer: 0.5.9 78 | dev: true 79 | resolution: 80 | integrity: sha512-4TdtIQVFo9UfIVzXnXpMuzsA4mX06oF9NER8FmIPjBosNiQsYB7P8sABSG+2rtWgsh6CkFXkwvxZ++BB+alwOw== 81 | /@glimmer/util/0.56.1: 82 | dependencies: 83 | '@glimmer/env': 0.1.7 84 | '@glimmer/interfaces': 0.56.1 85 | '@simple-dom/interface': 1.4.0 86 | dev: true 87 | resolution: 88 | integrity: sha512-g7R5hMtZ2BLF+AsYhSE1xoh0gOJALof4/JL6zovYvqrsKTLYGK1Qe3RKXSt8dPav8Ac0LXt+cOd6jHPGSrEs+A== 89 | /@iarna/toml/2.2.5: 90 | dev: true 91 | resolution: 92 | integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== 93 | /@nodelib/fs.scandir/2.1.3: 94 | dependencies: 95 | '@nodelib/fs.stat': 2.0.3 96 | run-parallel: 1.1.9 97 | engines: 98 | node: '>= 8' 99 | resolution: 100 | integrity: sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== 101 | /@nodelib/fs.stat/2.0.3: 102 | engines: 103 | node: '>= 8' 104 | resolution: 105 | integrity: sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== 106 | /@nodelib/fs.walk/1.2.4: 107 | dependencies: 108 | '@nodelib/fs.scandir': 2.1.3 109 | fastq: 1.8.0 110 | engines: 111 | node: '>= 8' 112 | resolution: 113 | integrity: sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== 114 | /@simple-dom/interface/1.4.0: 115 | dev: true 116 | resolution: 117 | integrity: sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA== 118 | /@types/color-name/1.1.1: 119 | dev: true 120 | resolution: 121 | integrity: sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== 122 | /@types/parse-json/4.0.0: 123 | dev: true 124 | resolution: 125 | integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== 126 | /@types/unist/2.0.3: 127 | dev: true 128 | resolution: 129 | integrity: sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== 130 | /@typescript-eslint/typescript-estree/2.34.0: 131 | dependencies: 132 | debug: 4.1.1 133 | eslint-visitor-keys: 1.3.0 134 | glob: 7.1.6 135 | is-glob: 4.0.1 136 | lodash: 4.17.19 137 | semver: 7.3.2 138 | tsutils: 3.17.1 139 | dev: true 140 | engines: 141 | node: ^8.10.0 || ^10.13.0 || >=11.10.1 142 | peerDependencies: 143 | typescript: '*' 144 | peerDependenciesMeta: 145 | typescript: 146 | optional: true 147 | resolution: 148 | integrity: sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg== 149 | /JSV/4.0.2: 150 | dev: false 151 | resolution: 152 | integrity: sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c= 153 | /agent-base/4.3.0: 154 | dependencies: 155 | es6-promisify: 5.0.0 156 | dev: false 157 | engines: 158 | node: '>= 4.0.0' 159 | resolution: 160 | integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== 161 | /ajv/6.12.4: 162 | dependencies: 163 | fast-deep-equal: 3.1.3 164 | fast-json-stable-stringify: 2.1.0 165 | json-schema-traverse: 0.4.1 166 | uri-js: 4.2.2 167 | dev: false 168 | resolution: 169 | integrity: sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== 170 | /am/1.0.2: 171 | dev: false 172 | resolution: 173 | integrity: sha512-RHkQUXmpazNBEqjZyCJNcKMRrlHI76Sx5Eba7VwccgAxJQULM05yqNny17zjRBgP+OjOQ0yW8PLZQ1gXSHQowg== 174 | /angular-estree-parser/1.3.1_@angular+compiler@9.0.5: 175 | dependencies: 176 | '@angular/compiler': 9.0.5 177 | lines-and-columns: 1.1.6 178 | tslib: 1.13.0 179 | dev: true 180 | engines: 181 | node: '>= 6' 182 | peerDependencies: 183 | '@angular/compiler': '>= 6.0.0 < 9.0.6' 184 | resolution: 185 | integrity: sha512-jvlnNk4aoEmA6EKK12OnsOkCSdsWleBsYB+aWyH8kpfTB6Li1kxWVbHKVldH9zDCwVVi1hXfqPi/gbSv49tkbQ== 186 | /angular-html-parser/1.7.0: 187 | dependencies: 188 | tslib: 1.13.0 189 | dev: true 190 | engines: 191 | node: '>= 6' 192 | resolution: 193 | integrity: sha512-/yjeqDQXGblZuFMI6vpDgiIDuv816QpIqa/mCotc0I4R0F5t5sfX1ntZ8VsBVQOUYRjPw8ggYlPZto76gHtf7Q== 194 | /ansi-regex/5.0.0: 195 | dev: true 196 | engines: 197 | node: '>=8' 198 | resolution: 199 | integrity: sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 200 | /ansi-styles/1.0.0: 201 | dev: false 202 | engines: 203 | node: '>=0.8.0' 204 | resolution: 205 | integrity: sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg= 206 | /ansi-styles/3.2.1: 207 | dependencies: 208 | color-convert: 1.9.3 209 | engines: 210 | node: '>=4' 211 | resolution: 212 | integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 213 | /ansi-styles/4.2.1: 214 | dependencies: 215 | '@types/color-name': 1.1.1 216 | color-convert: 2.0.1 217 | dev: true 218 | engines: 219 | node: '>=8' 220 | resolution: 221 | integrity: sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== 222 | /array-union/2.1.0: 223 | dev: true 224 | engines: 225 | node: '>=8' 226 | resolution: 227 | integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== 228 | /assert-plus/1.0.0: 229 | dev: false 230 | engines: 231 | node: '>=0.8' 232 | resolution: 233 | integrity: sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= 234 | /async-limiter/1.0.1: 235 | dev: false 236 | resolution: 237 | integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== 238 | /at-least-node/1.0.0: 239 | dev: false 240 | engines: 241 | node: '>= 4.0.0' 242 | resolution: 243 | integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== 244 | /await-sleep/0.0.1: 245 | dev: false 246 | resolution: 247 | integrity: sha512-H3X3eAxwGpeNIk/yvFOs8g7500Q1YvzrxjSC9TNgLGtjrMFxPwhDdcT34QNs2iGWpZ+5WKkMJdjDoYs+Sw+TaA== 248 | /bail/1.0.5: 249 | dev: true 250 | resolution: 251 | integrity: sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== 252 | /balanced-match/1.0.0: 253 | resolution: 254 | integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 255 | /better-ajv-errors/0.6.7_ajv@6.12.4: 256 | dependencies: 257 | '@babel/code-frame': 7.10.4 258 | '@babel/runtime': 7.11.2 259 | ajv: 6.12.4 260 | chalk: 2.4.2 261 | core-js: 3.6.5 262 | json-to-ast: 2.1.0 263 | jsonpointer: 4.1.0 264 | leven: 3.1.0 265 | dev: false 266 | peerDependencies: 267 | ajv: 4.11.8 - 6 268 | resolution: 269 | integrity: sha512-PYgt/sCzR4aGpyNy5+ViSQ77ognMnWq7745zM+/flYO4/Yisdtp9wDQW2IKCyVYPUxQt3E/b5GBSwfhd1LPdlg== 270 | /brace-expansion/1.1.11: 271 | dependencies: 272 | balanced-match: 1.0.0 273 | concat-map: 0.0.1 274 | resolution: 275 | integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 276 | /braces/3.0.2: 277 | dependencies: 278 | fill-range: 7.0.1 279 | engines: 280 | node: '>=8' 281 | resolution: 282 | integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 283 | /buffer-crc32/0.2.13: 284 | dev: false 285 | resolution: 286 | integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= 287 | /buffer-from/1.1.1: 288 | dev: false 289 | resolution: 290 | integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 291 | /callsites/3.1.0: 292 | dev: true 293 | engines: 294 | node: '>=6' 295 | resolution: 296 | integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 297 | /camelcase/6.0.0: 298 | dev: true 299 | engines: 300 | node: '>=10' 301 | resolution: 302 | integrity: sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== 303 | /chalk/0.4.0: 304 | dependencies: 305 | ansi-styles: 1.0.0 306 | has-color: 0.1.7 307 | strip-ansi: 0.1.1 308 | dev: false 309 | engines: 310 | node: '>=0.8.0' 311 | resolution: 312 | integrity: sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8= 313 | /chalk/2.4.2: 314 | dependencies: 315 | ansi-styles: 3.2.1 316 | escape-string-regexp: 1.0.5 317 | supports-color: 5.5.0 318 | engines: 319 | node: '>=4' 320 | resolution: 321 | integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 322 | /chalk/4.1.0: 323 | dependencies: 324 | ansi-styles: 4.2.1 325 | supports-color: 7.1.0 326 | dev: true 327 | engines: 328 | node: '>=10' 329 | resolution: 330 | integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== 331 | /character-entities-legacy/1.1.4: 332 | dev: true 333 | resolution: 334 | integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== 335 | /character-entities/1.2.4: 336 | dev: true 337 | resolution: 338 | integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== 339 | /character-reference-invalid/1.1.4: 340 | dev: true 341 | resolution: 342 | integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== 343 | /ci-info/2.0.0: 344 | dev: true 345 | resolution: 346 | integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== 347 | /cjk-regex/2.0.0: 348 | dependencies: 349 | regexp-util: 1.2.2 350 | unicode-regex: 2.0.0 351 | dev: true 352 | engines: 353 | node: '>= 4' 354 | resolution: 355 | integrity: sha512-E4gFi2f3jC0zFVHpaAcupW+gv9OejZ2aV3DP/LlSO0dDcZJAXw7W0ivn+vN17edN/PhU4HCgs1bfx7lPK7FpdA== 356 | /code-error-fragment/0.0.230: 357 | dev: false 358 | engines: 359 | node: '>= 4' 360 | resolution: 361 | integrity: sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw== 362 | /collapse-white-space/1.0.6: 363 | dev: true 364 | resolution: 365 | integrity: sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== 366 | /color-convert/1.9.3: 367 | dependencies: 368 | color-name: 1.1.3 369 | resolution: 370 | integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 371 | /color-convert/2.0.1: 372 | dependencies: 373 | color-name: 1.1.4 374 | dev: true 375 | engines: 376 | node: '>=7.0.0' 377 | resolution: 378 | integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 379 | /color-name/1.1.3: 380 | resolution: 381 | integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 382 | /color-name/1.1.4: 383 | dev: true 384 | resolution: 385 | integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 386 | /commander/2.20.3: 387 | dev: true 388 | resolution: 389 | integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 390 | /commander/6.0.0: 391 | dev: false 392 | engines: 393 | node: '>= 6' 394 | resolution: 395 | integrity: sha512-s7EA+hDtTYNhuXkTlhqew4txMZVdszBmKWSPEMxGr8ru8JXR7bLUFIAtPhcSuFdJQ0ILMxnJi8GkQL0yvDy/YA== 396 | /concat-map/0.0.1: 397 | resolution: 398 | integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 399 | /concat-stream/1.6.2: 400 | dependencies: 401 | buffer-from: 1.1.1 402 | inherits: 2.0.4 403 | readable-stream: 2.3.7 404 | typedarray: 0.0.6 405 | dev: false 406 | engines: 407 | '0': node >= 0.8 408 | resolution: 409 | integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== 410 | /core-js/3.6.5: 411 | dev: false 412 | requiresBuild: true 413 | resolution: 414 | integrity: sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== 415 | /core-util-is/1.0.2: 416 | dev: false 417 | resolution: 418 | integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 419 | /cosmiconfig/7.0.0: 420 | dependencies: 421 | '@types/parse-json': 4.0.0 422 | import-fresh: 3.2.1 423 | parse-json: 5.0.1 424 | path-type: 4.0.0 425 | yaml: 1.10.0 426 | dev: true 427 | engines: 428 | node: '>=10' 429 | resolution: 430 | integrity: sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA== 431 | /crypto-random-string/3.2.0: 432 | dependencies: 433 | type-fest: 0.8.1 434 | dev: false 435 | engines: 436 | node: '>=8' 437 | resolution: 438 | integrity: sha512-8vPu5bsKaq2uKRy3OL7h1Oo7RayAWB8sYexLKAqvCXVib8SxgbmoF1IN4QMKjBv8uI8mp5gPPMbiRah25GMrVQ== 439 | /dashify/2.0.0: 440 | dev: true 441 | engines: 442 | node: '>=4' 443 | resolution: 444 | integrity: sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A== 445 | /debug/2.6.9: 446 | dependencies: 447 | ms: 2.0.0 448 | dev: false 449 | resolution: 450 | integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 451 | /debug/3.2.6: 452 | dependencies: 453 | ms: 2.1.2 454 | dev: false 455 | resolution: 456 | integrity: sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== 457 | /debug/4.1.1: 458 | dependencies: 459 | ms: 2.1.2 460 | resolution: 461 | integrity: sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== 462 | /dedent/0.7.0: 463 | dev: true 464 | resolution: 465 | integrity: sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= 466 | /deep-is/0.1.3: 467 | dev: false 468 | resolution: 469 | integrity: sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= 470 | /detect-newline/3.1.0: 471 | dev: true 472 | engines: 473 | node: '>=8' 474 | resolution: 475 | integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== 476 | /diff/4.0.2: 477 | dev: true 478 | engines: 479 | node: '>=0.3.1' 480 | resolution: 481 | integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 482 | /dir-glob/3.0.1: 483 | dependencies: 484 | path-type: 4.0.0 485 | dev: true 486 | engines: 487 | node: '>=8' 488 | resolution: 489 | integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== 490 | /editorconfig-to-prettier/0.1.1: 491 | dev: true 492 | resolution: 493 | integrity: sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ== 494 | /editorconfig/0.15.3: 495 | dependencies: 496 | commander: 2.20.3 497 | lru-cache: 4.1.5 498 | semver: 5.7.1 499 | sigmund: 1.0.1 500 | dev: true 501 | hasBin: true 502 | resolution: 503 | integrity: sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== 504 | /emoji-regex/8.0.0: 505 | dev: true 506 | resolution: 507 | integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 508 | /error-ex/1.3.2: 509 | dependencies: 510 | is-arrayish: 0.2.1 511 | dev: true 512 | resolution: 513 | integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 514 | /es6-promise/4.2.8: 515 | dev: false 516 | resolution: 517 | integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== 518 | /es6-promisify/5.0.0: 519 | dependencies: 520 | es6-promise: 4.2.8 521 | dev: false 522 | resolution: 523 | integrity: sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= 524 | /escape-string-regexp/1.0.5: 525 | engines: 526 | node: '>=0.8.0' 527 | resolution: 528 | integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 529 | /escape-string-regexp/4.0.0: 530 | dev: true 531 | engines: 532 | node: '>=10' 533 | resolution: 534 | integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 535 | /escodegen/1.14.3: 536 | dependencies: 537 | esprima: 4.0.1 538 | estraverse: 4.3.0 539 | esutils: 2.0.3 540 | optionator: 0.8.3 541 | dev: false 542 | engines: 543 | node: '>=4.0' 544 | hasBin: true 545 | optionalDependencies: 546 | source-map: 0.6.1 547 | resolution: 548 | integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== 549 | /eslint-visitor-keys/1.3.0: 550 | dev: true 551 | engines: 552 | node: '>=4' 553 | resolution: 554 | integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== 555 | /esprima/4.0.1: 556 | dev: false 557 | engines: 558 | node: '>=4' 559 | hasBin: true 560 | resolution: 561 | integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 562 | /estraverse/4.3.0: 563 | dev: false 564 | engines: 565 | node: '>=4.0' 566 | resolution: 567 | integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 568 | /esutils/2.0.3: 569 | engines: 570 | node: '>=0.10.0' 571 | resolution: 572 | integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 573 | /events/3.2.0: 574 | dev: false 575 | engines: 576 | node: '>=0.8.x' 577 | resolution: 578 | integrity: sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== 579 | /extend/3.0.2: 580 | dev: true 581 | resolution: 582 | integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 583 | /extract-zip/1.7.0: 584 | dependencies: 585 | concat-stream: 1.6.2 586 | debug: 2.6.9 587 | mkdirp: 0.5.5 588 | yauzl: 2.10.0 589 | dev: false 590 | hasBin: true 591 | resolution: 592 | integrity: sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== 593 | /extsprintf/1.4.0: 594 | dev: false 595 | engines: 596 | '0': node >=0.6.0 597 | resolution: 598 | integrity: sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= 599 | /fast-deep-equal/3.1.3: 600 | dev: false 601 | resolution: 602 | integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 603 | /fast-glob/3.2.4: 604 | dependencies: 605 | '@nodelib/fs.stat': 2.0.3 606 | '@nodelib/fs.walk': 1.2.4 607 | glob-parent: 5.1.1 608 | merge2: 1.4.1 609 | micromatch: 4.0.2 610 | picomatch: 2.2.2 611 | engines: 612 | node: '>=8' 613 | resolution: 614 | integrity: sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== 615 | /fast-json-stable-stringify/2.1.0: 616 | dev: false 617 | resolution: 618 | integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 619 | /fast-levenshtein/2.0.6: 620 | dev: false 621 | resolution: 622 | integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 623 | /fastq/1.8.0: 624 | dependencies: 625 | reusify: 1.0.4 626 | resolution: 627 | integrity: sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== 628 | /fd-slicer/1.1.0: 629 | dependencies: 630 | pend: 1.2.0 631 | dev: false 632 | resolution: 633 | integrity: sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= 634 | /fill-range/7.0.1: 635 | dependencies: 636 | to-regex-range: 5.0.1 637 | engines: 638 | node: '>=8' 639 | resolution: 640 | integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 641 | /find-parent-dir/0.3.0: 642 | dev: true 643 | resolution: 644 | integrity: sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ= 645 | /find-project-root/1.1.1: 646 | dev: true 647 | hasBin: true 648 | resolution: 649 | integrity: sha1-0kJyei2QRyXfVxTyPf3N7doLbvg= 650 | /flatten/1.0.3: 651 | dev: true 652 | resolution: 653 | integrity: sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== 654 | /fs-extra/9.0.1: 655 | dependencies: 656 | at-least-node: 1.0.0 657 | graceful-fs: 4.2.4 658 | jsonfile: 6.0.1 659 | universalify: 1.0.0 660 | dev: false 661 | engines: 662 | node: '>=10' 663 | resolution: 664 | integrity: sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== 665 | /fs.realpath/1.0.0: 666 | resolution: 667 | integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 668 | /get-stream/6.0.0: 669 | dev: true 670 | engines: 671 | node: '>=10' 672 | resolution: 673 | integrity: sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg== 674 | /glob-parent/5.1.1: 675 | dependencies: 676 | is-glob: 4.0.1 677 | engines: 678 | node: '>= 6' 679 | resolution: 680 | integrity: sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== 681 | /glob/7.1.6: 682 | dependencies: 683 | fs.realpath: 1.0.0 684 | inflight: 1.0.6 685 | inherits: 2.0.4 686 | minimatch: 3.0.4 687 | once: 1.4.0 688 | path-is-absolute: 1.0.1 689 | resolution: 690 | integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 691 | /globby/11.0.1: 692 | dependencies: 693 | array-union: 2.1.0 694 | dir-glob: 3.0.1 695 | fast-glob: 3.2.4 696 | ignore: 5.1.8 697 | merge2: 1.4.1 698 | slash: 3.0.0 699 | dev: true 700 | engines: 701 | node: '>=10' 702 | resolution: 703 | integrity: sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== 704 | /graceful-fs/4.2.4: 705 | dev: false 706 | resolution: 707 | integrity: sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== 708 | /grapheme-splitter/1.0.4: 709 | dev: false 710 | resolution: 711 | integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== 712 | /graphology-graphml/0.2.0: 713 | dependencies: 714 | graphology-utils: 1.7.0 715 | xml-writer: 1.7.0 716 | xmldom: 0.2.1 717 | dev: false 718 | resolution: 719 | integrity: sha512-sa/sosn6gHnQiQ7Ij+J4cQBmC/qYIcQfY9yxlpzm6eefS6tZFOfZNdYKLkV3J0wf7e4KMek4vH5vDPiqnSuJsQ== 720 | /graphology-types/0.15.5: 721 | dev: false 722 | resolution: 723 | integrity: sha512-2NONgcQ0KmzMoiLAOkk4AkyhrQsA4dfJKyGOMYUfz2sNBAR/VK3oPcalCg3ID7zDd4XSqE3rMtEt+G3KcUaLew== 724 | /graphology-types/0.16.0: 725 | dev: false 726 | resolution: 727 | integrity: sha512-iBGyPuMHlmHdXaB0cu/vllkPJ3myf063ZICY90zDxYQrJYZ3Dm4h2+dLM3Kof+CVJzM4HGg96ZFZ8HS6C7LgCQ== 728 | /graphology-utils/1.7.0: 729 | dependencies: 730 | graphology-types: 0.15.5 731 | dev: false 732 | resolution: 733 | integrity: sha512-g94E5O1FTws4E81AVKnCmxinDN1KRO7Zpysqd/j7Xjy2Qjs7DOnB3XHZUaS/Yk6D74LorBp7NJY5685IEkAh6g== 734 | /graphology/0.17.1: 735 | dependencies: 736 | events: 3.2.0 737 | graphology-types: 0.16.0 738 | obliterator: 1.6.1 739 | dev: false 740 | resolution: 741 | integrity: sha512-3cUHg0OzCnLMK+R1sL678afUjtsoQcyq8XU0MmotlpsTqMjq5YrbWBcoXSth3kexRk+ynTiGw6t+ph49zvpQ+g== 742 | /graphql/15.3.0: 743 | dev: true 744 | engines: 745 | node: '>= 10.x' 746 | resolution: 747 | integrity: sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w== 748 | /handlebars/4.7.6: 749 | dependencies: 750 | minimist: 1.2.5 751 | neo-async: 2.6.2 752 | source-map: 0.6.1 753 | wordwrap: 1.0.0 754 | engines: 755 | node: '>=0.4.7' 756 | hasBin: true 757 | optionalDependencies: 758 | uglify-js: 3.10.3 759 | resolution: 760 | integrity: sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== 761 | /has-color/0.1.7: 762 | dev: false 763 | engines: 764 | node: '>=0.10.0' 765 | resolution: 766 | integrity: sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8= 767 | /has-flag/3.0.0: 768 | engines: 769 | node: '>=4' 770 | resolution: 771 | integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 772 | /has-flag/4.0.0: 773 | dev: true 774 | engines: 775 | node: '>=8' 776 | resolution: 777 | integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 778 | /html-element-attributes/2.2.1: 779 | dev: true 780 | resolution: 781 | integrity: sha512-gGTgCeQu+g1OFExZKWQ1LwbFXxLJ6cGdCGj64ByEaxatr/EPVc23D6Gxngb37ao+SNInP/sGu8FXxRsSxMm7aQ== 782 | /html-styles/1.0.0: 783 | dev: true 784 | resolution: 785 | integrity: sha1-oYBh/WUfmca3XEXI4FSaO8PgGnU= 786 | /html-tag-names/1.1.5: 787 | dev: true 788 | resolution: 789 | integrity: sha512-aI5tKwNTBzOZApHIynaAwecLBv8TlZTEy/P4Sj2SzzAhBrGuI8yGZ0UIXVPQzOHGS+to2mjb04iy6VWt/8+d8A== 790 | /https-proxy-agent/2.2.4: 791 | dependencies: 792 | agent-base: 4.3.0 793 | debug: 3.2.6 794 | dev: false 795 | engines: 796 | node: '>= 4.5.0' 797 | resolution: 798 | integrity: sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== 799 | /ignore/4.0.6: 800 | dev: true 801 | engines: 802 | node: '>= 4' 803 | resolution: 804 | integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== 805 | /ignore/5.1.8: 806 | dev: true 807 | engines: 808 | node: '>= 4' 809 | resolution: 810 | integrity: sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== 811 | /import-fresh/3.2.1: 812 | dependencies: 813 | parent-module: 1.0.1 814 | resolve-from: 4.0.0 815 | dev: true 816 | engines: 817 | node: '>=6' 818 | resolution: 819 | integrity: sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== 820 | /indexes-of/1.0.1: 821 | dev: true 822 | resolution: 823 | integrity: sha1-8w9xbI4r00bHtn0985FVZqfAVgc= 824 | /inflight/1.0.6: 825 | dependencies: 826 | once: 1.4.0 827 | wrappy: 1.0.2 828 | resolution: 829 | integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 830 | /inherits/2.0.4: 831 | resolution: 832 | integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 833 | /is-alphabetical/1.0.4: 834 | dev: true 835 | resolution: 836 | integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== 837 | /is-alphanumerical/1.0.4: 838 | dependencies: 839 | is-alphabetical: 1.0.4 840 | is-decimal: 1.0.4 841 | dev: true 842 | resolution: 843 | integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== 844 | /is-arrayish/0.2.1: 845 | dev: true 846 | resolution: 847 | integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 848 | /is-buffer/2.0.4: 849 | dev: true 850 | engines: 851 | node: '>=4' 852 | resolution: 853 | integrity: sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== 854 | /is-decimal/1.0.4: 855 | dev: true 856 | resolution: 857 | integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== 858 | /is-extglob/2.1.1: 859 | engines: 860 | node: '>=0.10.0' 861 | resolution: 862 | integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 863 | /is-fullwidth-code-point/3.0.0: 864 | dev: true 865 | engines: 866 | node: '>=8' 867 | resolution: 868 | integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 869 | /is-glob/4.0.1: 870 | dependencies: 871 | is-extglob: 2.1.1 872 | engines: 873 | node: '>=0.10.0' 874 | resolution: 875 | integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 876 | /is-hexadecimal/1.0.4: 877 | dev: true 878 | resolution: 879 | integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== 880 | /is-number/7.0.0: 881 | engines: 882 | node: '>=0.12.0' 883 | resolution: 884 | integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 885 | /is-plain-obj/2.1.0: 886 | dev: true 887 | engines: 888 | node: '>=8' 889 | resolution: 890 | integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 891 | /is-whitespace-character/1.0.4: 892 | dev: true 893 | resolution: 894 | integrity: sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== 895 | /is-word-character/1.0.4: 896 | dev: true 897 | resolution: 898 | integrity: sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== 899 | /isarray/1.0.0: 900 | dev: false 901 | resolution: 902 | integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 903 | /isobject/2.1.0: 904 | dependencies: 905 | isarray: 1.0.0 906 | dev: false 907 | engines: 908 | node: '>=0.10.0' 909 | resolution: 910 | integrity: sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= 911 | /iterare/1.2.1: 912 | dev: false 913 | engines: 914 | node: '>=6' 915 | resolution: 916 | integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q== 917 | /jest-docblock/26.0.0: 918 | dependencies: 919 | detect-newline: 3.1.0 920 | dev: true 921 | engines: 922 | node: '>= 10.14.2' 923 | resolution: 924 | integrity: sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== 925 | /js-tokens/4.0.0: 926 | resolution: 927 | integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 928 | /json-parse-better-errors/1.0.2: 929 | dev: true 930 | resolution: 931 | integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 932 | /json-schema-traverse/0.4.1: 933 | dev: false 934 | resolution: 935 | integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 936 | /json-stable-stringify/1.0.1: 937 | dependencies: 938 | jsonify: 0.0.0 939 | dev: true 940 | resolution: 941 | integrity: sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= 942 | /json-to-ast/2.1.0: 943 | dependencies: 944 | code-error-fragment: 0.0.230 945 | grapheme-splitter: 1.0.4 946 | dev: false 947 | engines: 948 | node: '>= 4' 949 | resolution: 950 | integrity: sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ== 951 | /jsonfile/6.0.1: 952 | dependencies: 953 | universalify: 1.0.0 954 | dev: false 955 | optionalDependencies: 956 | graceful-fs: 4.2.4 957 | resolution: 958 | integrity: sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== 959 | /jsonify/0.0.0: 960 | dev: true 961 | resolution: 962 | integrity: sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= 963 | /jsonlint/1.6.3: 964 | dependencies: 965 | JSV: 4.0.2 966 | nomnom: 1.8.1 967 | dev: false 968 | engines: 969 | node: '>= 0.6' 970 | hasBin: true 971 | resolution: 972 | integrity: sha512-jMVTMzP+7gU/IyC6hvKyWpUU8tmTkK5b3BPNuMI9U8Sit+YAWLlZwB6Y6YrdCxfg2kNz05p3XY3Bmm4m26Nv3A== 973 | /jsonpointer/4.1.0: 974 | dev: false 975 | engines: 976 | node: '>=0.10.0' 977 | resolution: 978 | integrity: sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg== 979 | /leven/2.1.0: 980 | dev: true 981 | engines: 982 | node: '>=0.10.0' 983 | resolution: 984 | integrity: sha1-wuep93IJTe6dNCAq6KzORoeHVYA= 985 | /leven/3.1.0: 986 | engines: 987 | node: '>=6' 988 | resolution: 989 | integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== 990 | /levn/0.3.0: 991 | dependencies: 992 | prelude-ls: 1.1.2 993 | type-check: 0.3.2 994 | dev: false 995 | engines: 996 | node: '>= 0.8.0' 997 | resolution: 998 | integrity: sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= 999 | /line-column/1.0.2: 1000 | dependencies: 1001 | isarray: 1.0.0 1002 | isobject: 2.1.0 1003 | dev: false 1004 | resolution: 1005 | integrity: sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= 1006 | /lines-and-columns/1.1.6: 1007 | dev: true 1008 | resolution: 1009 | integrity: sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= 1010 | /linguist-languages/7.10.0: 1011 | dev: true 1012 | resolution: 1013 | integrity: sha512-Uqt94P4iAznscZtccnNE1IBi105U+fmQKEUlDJv54JDdFZDInomkepEIRpZLOQcPyGdcNu3JO9Tvo5wpQVbfKw== 1014 | /lodash.groupby/4.6.0: 1015 | dev: false 1016 | resolution: 1017 | integrity: sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E= 1018 | /lodash.sortby/4.7.0: 1019 | dev: false 1020 | resolution: 1021 | integrity: sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= 1022 | /lodash/4.17.19: 1023 | dev: true 1024 | resolution: 1025 | integrity: sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== 1026 | /lru-cache/4.1.5: 1027 | dependencies: 1028 | pseudomap: 1.0.2 1029 | yallist: 2.1.2 1030 | dev: true 1031 | resolution: 1032 | integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== 1033 | /map-age-cleaner/0.1.3: 1034 | dependencies: 1035 | p-defer: 1.0.0 1036 | dev: true 1037 | engines: 1038 | node: '>=6' 1039 | resolution: 1040 | integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== 1041 | /markdown-escapes/1.0.4: 1042 | dev: true 1043 | resolution: 1044 | integrity: sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== 1045 | /mem/6.1.0: 1046 | dependencies: 1047 | map-age-cleaner: 0.1.3 1048 | mimic-fn: 3.1.0 1049 | dev: true 1050 | engines: 1051 | node: '>=8' 1052 | resolution: 1053 | integrity: sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg== 1054 | /merge2/1.4.1: 1055 | engines: 1056 | node: '>= 8' 1057 | resolution: 1058 | integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== 1059 | /micromatch/4.0.2: 1060 | dependencies: 1061 | braces: 3.0.2 1062 | picomatch: 2.2.2 1063 | engines: 1064 | node: '>=8' 1065 | resolution: 1066 | integrity: sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== 1067 | /mime/2.4.6: 1068 | dev: false 1069 | engines: 1070 | node: '>=4.0.0' 1071 | hasBin: true 1072 | resolution: 1073 | integrity: sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== 1074 | /mimic-fn/3.1.0: 1075 | dev: true 1076 | engines: 1077 | node: '>=8' 1078 | resolution: 1079 | integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== 1080 | /minimatch/3.0.4: 1081 | dependencies: 1082 | brace-expansion: 1.1.11 1083 | resolution: 1084 | integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 1085 | /minimist/1.2.5: 1086 | resolution: 1087 | integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 1088 | /mkdirp/0.5.5: 1089 | dependencies: 1090 | minimist: 1.2.5 1091 | dev: false 1092 | hasBin: true 1093 | resolution: 1094 | integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 1095 | /ms/2.0.0: 1096 | dev: false 1097 | resolution: 1098 | integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 1099 | /ms/2.1.2: 1100 | resolution: 1101 | integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1102 | /n-readlines/1.0.0: 1103 | dev: true 1104 | engines: 1105 | node: '>=6.x.x' 1106 | resolution: 1107 | integrity: sha512-ISDqGcspVu6U3VKqtJZG1uR55SmNNF9uK0EMq1IvNVVZOui6MW6VR0+pIZhqz85ORAGp+4zW+5fJ/SE7bwEibA== 1108 | /neo-async/2.6.2: 1109 | resolution: 1110 | integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== 1111 | /nomnom/1.8.1: 1112 | dependencies: 1113 | chalk: 0.4.0 1114 | underscore: 1.6.0 1115 | deprecated: Package no longer supported. Contact support@npmjs.com for more info. 1116 | dev: false 1117 | resolution: 1118 | integrity: sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc= 1119 | /obliterator/1.6.1: 1120 | dev: false 1121 | resolution: 1122 | integrity: sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig== 1123 | /once/1.4.0: 1124 | dependencies: 1125 | wrappy: 1.0.2 1126 | resolution: 1127 | integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 1128 | /optionator/0.8.3: 1129 | dependencies: 1130 | deep-is: 0.1.3 1131 | fast-levenshtein: 2.0.6 1132 | levn: 0.3.0 1133 | prelude-ls: 1.1.2 1134 | type-check: 0.3.2 1135 | word-wrap: 1.2.3 1136 | dev: false 1137 | engines: 1138 | node: '>= 0.8.0' 1139 | resolution: 1140 | integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== 1141 | /p-defer/1.0.0: 1142 | dev: true 1143 | engines: 1144 | node: '>=4' 1145 | resolution: 1146 | integrity: sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= 1147 | /parent-module/1.0.1: 1148 | dependencies: 1149 | callsites: 3.1.0 1150 | dev: true 1151 | engines: 1152 | node: '>=6' 1153 | resolution: 1154 | integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1155 | /parse-entities/1.2.2: 1156 | dependencies: 1157 | character-entities: 1.2.4 1158 | character-entities-legacy: 1.1.4 1159 | character-reference-invalid: 1.1.4 1160 | is-alphanumerical: 1.0.4 1161 | is-decimal: 1.0.4 1162 | is-hexadecimal: 1.0.4 1163 | dev: true 1164 | resolution: 1165 | integrity: sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg== 1166 | /parse-json/5.0.1: 1167 | dependencies: 1168 | '@babel/code-frame': 7.10.4 1169 | error-ex: 1.3.2 1170 | json-parse-better-errors: 1.0.2 1171 | lines-and-columns: 1.1.6 1172 | dev: true 1173 | engines: 1174 | node: '>=8' 1175 | resolution: 1176 | integrity: sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ== 1177 | /path-is-absolute/1.0.1: 1178 | engines: 1179 | node: '>=0.10.0' 1180 | resolution: 1181 | integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1182 | /path-parse/1.0.6: 1183 | dev: true 1184 | resolution: 1185 | integrity: sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 1186 | /path-type/4.0.0: 1187 | dev: true 1188 | engines: 1189 | node: '>=8' 1190 | resolution: 1191 | integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 1192 | /pend/1.2.0: 1193 | dev: false 1194 | resolution: 1195 | integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA= 1196 | /picomatch/2.2.2: 1197 | engines: 1198 | node: '>=8.6' 1199 | resolution: 1200 | integrity: sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== 1201 | /please-upgrade-node/3.2.0: 1202 | dependencies: 1203 | semver-compare: 1.0.0 1204 | dev: true 1205 | resolution: 1206 | integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== 1207 | /postcss-less/3.1.4: 1208 | dependencies: 1209 | postcss: 7.0.32 1210 | dev: true 1211 | engines: 1212 | node: '>=6.14.4' 1213 | resolution: 1214 | integrity: sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA== 1215 | /postcss-media-query-parser/0.2.3: 1216 | dev: true 1217 | resolution: 1218 | integrity: sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= 1219 | /postcss-scss/2.1.1: 1220 | dependencies: 1221 | postcss: 7.0.32 1222 | dev: true 1223 | engines: 1224 | node: '>=6.0.0' 1225 | resolution: 1226 | integrity: sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA== 1227 | /postcss-selector-parser/2.2.3: 1228 | dependencies: 1229 | flatten: 1.0.3 1230 | indexes-of: 1.0.1 1231 | uniq: 1.0.1 1232 | dev: true 1233 | resolution: 1234 | integrity: sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A= 1235 | /postcss-values-parser/2.0.1: 1236 | dependencies: 1237 | flatten: 1.0.3 1238 | indexes-of: 1.0.1 1239 | uniq: 1.0.1 1240 | dev: true 1241 | engines: 1242 | node: '>=6.14.4' 1243 | resolution: 1244 | integrity: sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== 1245 | /postcss/7.0.32: 1246 | dependencies: 1247 | chalk: 2.4.2 1248 | source-map: 0.6.1 1249 | supports-color: 6.1.0 1250 | dev: true 1251 | engines: 1252 | node: '>=6.0.0' 1253 | resolution: 1254 | integrity: sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== 1255 | /prelude-ls/1.1.2: 1256 | dev: false 1257 | engines: 1258 | node: '>= 0.8.0' 1259 | resolution: 1260 | integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= 1261 | /prettierx/0.14.0: 1262 | dependencies: 1263 | '@angular/compiler': 9.0.5 1264 | '@babel/code-frame': 7.10.4 1265 | '@babel/parser': 7.11.3 1266 | '@glimmer/syntax': 0.56.1 1267 | '@iarna/toml': 2.2.5 1268 | '@typescript-eslint/typescript-estree': 2.34.0 1269 | angular-estree-parser: 1.3.1_@angular+compiler@9.0.5 1270 | angular-html-parser: 1.7.0 1271 | camelcase: 6.0.0 1272 | chalk: 4.1.0 1273 | ci-info: 2.0.0 1274 | cjk-regex: 2.0.0 1275 | cosmiconfig: 7.0.0 1276 | dashify: 2.0.0 1277 | dedent: 0.7.0 1278 | diff: 4.0.2 1279 | editorconfig: 0.15.3 1280 | editorconfig-to-prettier: 0.1.1 1281 | escape-string-regexp: 4.0.0 1282 | esutils: 2.0.3 1283 | fast-glob: 3.2.4 1284 | find-parent-dir: 0.3.0 1285 | find-project-root: 1.1.1 1286 | get-stream: 6.0.0 1287 | globby: 11.0.1 1288 | graphql: 15.3.0 1289 | html-element-attributes: 2.2.1 1290 | html-styles: 1.0.0 1291 | html-tag-names: 1.1.5 1292 | ignore: 4.0.6 1293 | jest-docblock: 26.0.0 1294 | json-stable-stringify: 1.0.1 1295 | leven: 3.1.0 1296 | lines-and-columns: 1.1.6 1297 | linguist-languages: 7.10.0 1298 | lodash: 4.17.19 1299 | mem: 6.1.0 1300 | minimatch: 3.0.4 1301 | minimist: 1.2.5 1302 | n-readlines: 1.0.0 1303 | please-upgrade-node: 3.2.0 1304 | postcss-less: 3.1.4 1305 | postcss-media-query-parser: 0.2.3 1306 | postcss-scss: 2.1.1 1307 | postcss-selector-parser: 2.2.3 1308 | postcss-values-parser: 2.0.1 1309 | regexp-util: 1.2.2 1310 | remark-math: 1.0.6_remark-parse@5.0.0 1311 | remark-parse: 5.0.0 1312 | resolve: 1.17.0 1313 | semver: 7.3.2 1314 | srcset: 3.0.0 1315 | string-width: 4.2.0 1316 | unicode-regex: 3.0.0 1317 | unified: 9.1.0 1318 | vnopts: 1.0.2 1319 | yaml-unist-parser: 1.3.0 1320 | dev: true 1321 | engines: 1322 | node: '>=10.13.0' 1323 | hasBin: true 1324 | peerDependencies: 1325 | flow-parser: '*' 1326 | typescript: '*' 1327 | peerDependenciesMeta: 1328 | flow-parser: 1329 | optional: true 1330 | typescript: 1331 | optional: true 1332 | resolution: 1333 | integrity: sha512-+EEYBROT3kpYcBgTcMvSlisWdtGFPuUeIDw0XYMd2qZ25btZ8FRhA+IWPnxqYpqY+yEjRchSOhQwMj4BhJGEdQ== 1334 | /process-nextick-args/2.0.1: 1335 | dev: false 1336 | resolution: 1337 | integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 1338 | /progress/2.0.3: 1339 | dev: false 1340 | engines: 1341 | node: '>=0.4.0' 1342 | resolution: 1343 | integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== 1344 | /proxy-from-env/1.1.0: 1345 | dev: false 1346 | resolution: 1347 | integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== 1348 | /pseudomap/1.0.2: 1349 | dev: true 1350 | resolution: 1351 | integrity: sha1-8FKijacOYYkX7wqKw0wa5aaChrM= 1352 | /punycode/2.1.1: 1353 | dev: false 1354 | engines: 1355 | node: '>=6' 1356 | resolution: 1357 | integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 1358 | /puppeteer-core/1.20.0: 1359 | dependencies: 1360 | debug: 4.1.1 1361 | extract-zip: 1.7.0 1362 | https-proxy-agent: 2.2.4 1363 | mime: 2.4.6 1364 | progress: 2.0.3 1365 | proxy-from-env: 1.1.0 1366 | rimraf: 2.7.1 1367 | ws: 6.2.1 1368 | dev: false 1369 | engines: 1370 | node: '>=6.4.0' 1371 | requiresBuild: true 1372 | resolution: 1373 | integrity: sha512-akoSCMDVv6BFd/4+dtW6mVgdaRQhy/cmkGzXcx9HAXZqnY9zXYbsfoXMiMpwt3+53U9zFGSjgvsi0mDKNJLfqg== 1374 | /readable-stream/2.3.7: 1375 | dependencies: 1376 | core-util-is: 1.0.2 1377 | inherits: 2.0.4 1378 | isarray: 1.0.0 1379 | process-nextick-args: 2.0.1 1380 | safe-buffer: 5.1.2 1381 | string_decoder: 1.1.1 1382 | util-deprecate: 1.0.2 1383 | dev: false 1384 | resolution: 1385 | integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 1386 | /regenerator-runtime/0.13.7: 1387 | dev: false 1388 | resolution: 1389 | integrity: sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== 1390 | /regexp-util/1.2.2: 1391 | dependencies: 1392 | tslib: 1.13.0 1393 | dev: true 1394 | engines: 1395 | node: '>= 4' 1396 | resolution: 1397 | integrity: sha512-5/rl2UD18oAlLQEIuKBeiSIOp1hb5wCXcakl5yvHxlY1wyWI4D5cUKKzCibBeu741PA9JKvZhMqbkDQqPusX3w== 1398 | /remark-math/1.0.6_remark-parse@5.0.0: 1399 | dependencies: 1400 | remark-parse: 5.0.0 1401 | trim-trailing-lines: 1.1.3 1402 | dev: true 1403 | peerDependencies: 1404 | remark-parse: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 1405 | resolution: 1406 | integrity: sha512-I43wU/QOQpXvVFXKjA4FHp5xptK65+5F6yolm8+69/JV0EqSOB64wURUZ3JK50JtnTL8FvwLiH2PZ+fvsBxviA== 1407 | /remark-parse/5.0.0: 1408 | dependencies: 1409 | collapse-white-space: 1.0.6 1410 | is-alphabetical: 1.0.4 1411 | is-decimal: 1.0.4 1412 | is-whitespace-character: 1.0.4 1413 | is-word-character: 1.0.4 1414 | markdown-escapes: 1.0.4 1415 | parse-entities: 1.2.2 1416 | repeat-string: 1.6.1 1417 | state-toggle: 1.0.3 1418 | trim: 0.0.1 1419 | trim-trailing-lines: 1.1.3 1420 | unherit: 1.1.3 1421 | unist-util-remove-position: 1.1.4 1422 | vfile-location: 2.0.6 1423 | xtend: 4.0.2 1424 | dev: true 1425 | resolution: 1426 | integrity: sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA== 1427 | /repeat-string/1.6.1: 1428 | dev: true 1429 | engines: 1430 | node: '>=0.10' 1431 | resolution: 1432 | integrity: sha1-jcrkcOHIirwtYA//Sndihtp15jc= 1433 | /replace-ext/1.0.0: 1434 | dev: true 1435 | engines: 1436 | node: '>= 0.10' 1437 | resolution: 1438 | integrity: sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= 1439 | /resolve-from/4.0.0: 1440 | dev: true 1441 | engines: 1442 | node: '>=4' 1443 | resolution: 1444 | integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1445 | /resolve/1.17.0: 1446 | dependencies: 1447 | path-parse: 1.0.6 1448 | dev: true 1449 | resolution: 1450 | integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== 1451 | /reusify/1.0.4: 1452 | engines: 1453 | iojs: '>=1.0.0' 1454 | node: '>=0.10.0' 1455 | resolution: 1456 | integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 1457 | /rimraf/2.7.1: 1458 | dependencies: 1459 | glob: 7.1.6 1460 | dev: false 1461 | hasBin: true 1462 | resolution: 1463 | integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== 1464 | /rimraf/3.0.2: 1465 | dependencies: 1466 | glob: 7.1.6 1467 | dev: false 1468 | hasBin: true 1469 | resolution: 1470 | integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1471 | /run-parallel/1.1.9: 1472 | resolution: 1473 | integrity: sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== 1474 | /safe-buffer/5.1.2: 1475 | dev: false 1476 | resolution: 1477 | integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 1478 | /sanitize-filename/1.6.3: 1479 | dependencies: 1480 | truncate-utf8-bytes: 1.0.2 1481 | dev: false 1482 | resolution: 1483 | integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== 1484 | /semver-compare/1.0.0: 1485 | dev: true 1486 | resolution: 1487 | integrity: sha1-De4hahyUGrN+nvsXiPavxf9VN/w= 1488 | /semver/5.7.1: 1489 | dev: true 1490 | hasBin: true 1491 | resolution: 1492 | integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 1493 | /semver/7.3.2: 1494 | dev: true 1495 | engines: 1496 | node: '>=10' 1497 | hasBin: true 1498 | resolution: 1499 | integrity: sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== 1500 | /sigmund/1.0.1: 1501 | dev: true 1502 | resolution: 1503 | integrity: sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= 1504 | /simple-html-tokenizer/0.5.9: 1505 | dev: true 1506 | resolution: 1507 | integrity: sha512-w/3FEDN94r4JQ9WoYrIr8RqDIPZdyNkdpbK9glFady1CAEyD97XWCv8HFetQO21w81e7h7Nh59iYTyG1mUJftg== 1508 | /slash/3.0.0: 1509 | dev: true 1510 | engines: 1511 | node: '>=8' 1512 | resolution: 1513 | integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== 1514 | /source-map/0.6.1: 1515 | engines: 1516 | node: '>=0.10.0' 1517 | resolution: 1518 | integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1519 | /srcset/3.0.0: 1520 | dev: true 1521 | engines: 1522 | node: '>=10' 1523 | resolution: 1524 | integrity: sha512-D59vF08Qzu/C4GAOXVgMTLfgryt5fyWo93FZyhEWANo0PokFz/iWdDe13mX3O5TRf6l8vMTqckAfR4zPiaH0yQ== 1525 | /state-toggle/1.0.3: 1526 | dev: true 1527 | resolution: 1528 | integrity: sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== 1529 | /string-width/4.2.0: 1530 | dependencies: 1531 | emoji-regex: 8.0.0 1532 | is-fullwidth-code-point: 3.0.0 1533 | strip-ansi: 6.0.0 1534 | dev: true 1535 | engines: 1536 | node: '>=8' 1537 | resolution: 1538 | integrity: sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== 1539 | /string_decoder/1.1.1: 1540 | dependencies: 1541 | safe-buffer: 5.1.2 1542 | dev: false 1543 | resolution: 1544 | integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 1545 | /strip-ansi/0.1.1: 1546 | dev: false 1547 | engines: 1548 | node: '>=0.8.0' 1549 | hasBin: true 1550 | resolution: 1551 | integrity: sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE= 1552 | /strip-ansi/6.0.0: 1553 | dependencies: 1554 | ansi-regex: 5.0.0 1555 | dev: true 1556 | engines: 1557 | node: '>=8' 1558 | resolution: 1559 | integrity: sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== 1560 | /supports-color/5.5.0: 1561 | dependencies: 1562 | has-flag: 3.0.0 1563 | engines: 1564 | node: '>=4' 1565 | resolution: 1566 | integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1567 | /supports-color/6.1.0: 1568 | dependencies: 1569 | has-flag: 3.0.0 1570 | dev: true 1571 | engines: 1572 | node: '>=6' 1573 | resolution: 1574 | integrity: sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== 1575 | /supports-color/7.1.0: 1576 | dependencies: 1577 | has-flag: 4.0.0 1578 | dev: true 1579 | engines: 1580 | node: '>=8' 1581 | resolution: 1582 | integrity: sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== 1583 | /tmp-promise/3.0.2: 1584 | dependencies: 1585 | tmp: 0.2.1 1586 | dev: false 1587 | resolution: 1588 | integrity: sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA== 1589 | /tmp/0.2.1: 1590 | dependencies: 1591 | rimraf: 3.0.2 1592 | dev: false 1593 | engines: 1594 | node: '>=8.17.0' 1595 | resolution: 1596 | integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== 1597 | /to-regex-range/5.0.1: 1598 | dependencies: 1599 | is-number: 7.0.0 1600 | engines: 1601 | node: '>=8.0' 1602 | resolution: 1603 | integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1604 | /trim-trailing-lines/1.1.3: 1605 | dev: true 1606 | resolution: 1607 | integrity: sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA== 1608 | /trim/0.0.1: 1609 | dev: true 1610 | resolution: 1611 | integrity: sha1-WFhUf2spB1fulczMZm+1AITEYN0= 1612 | /trough/1.0.5: 1613 | dev: true 1614 | resolution: 1615 | integrity: sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== 1616 | /truncate-utf8-bytes/1.0.2: 1617 | dependencies: 1618 | utf8-byte-length: 1.0.4 1619 | dev: false 1620 | resolution: 1621 | integrity: sha1-QFkjkJWS1W94pYGENLC3hInKXys= 1622 | /tslib/1.13.0: 1623 | dev: true 1624 | resolution: 1625 | integrity: sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== 1626 | /tsutils/3.17.1: 1627 | dependencies: 1628 | tslib: 1.13.0 1629 | dev: true 1630 | engines: 1631 | node: '>= 6' 1632 | peerDependencies: 1633 | typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' 1634 | resolution: 1635 | integrity: sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== 1636 | /type-check/0.3.2: 1637 | dependencies: 1638 | prelude-ls: 1.1.2 1639 | dev: false 1640 | engines: 1641 | node: '>= 0.8.0' 1642 | resolution: 1643 | integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= 1644 | /type-fest/0.8.1: 1645 | dev: false 1646 | engines: 1647 | node: '>=8' 1648 | resolution: 1649 | integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== 1650 | /typedarray/0.0.6: 1651 | dev: false 1652 | resolution: 1653 | integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= 1654 | /uglify-js/3.10.3: 1655 | engines: 1656 | node: '>=0.8.0' 1657 | hasBin: true 1658 | optional: true 1659 | resolution: 1660 | integrity: sha512-Lh00i69Uf6G74mvYpHCI9KVVXLcHW/xu79YTvH7Mkc9zyKUeSPz0owW0dguj0Scavns3ZOh3wY63J0Zb97Za2g== 1661 | /underscore/1.6.0: 1662 | dev: false 1663 | resolution: 1664 | integrity: sha1-izixDKze9jM3uLJOT/htRa6lKag= 1665 | /unherit/1.1.3: 1666 | dependencies: 1667 | inherits: 2.0.4 1668 | xtend: 4.0.2 1669 | dev: true 1670 | resolution: 1671 | integrity: sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== 1672 | /unicode-regex/2.0.0: 1673 | dependencies: 1674 | regexp-util: 1.2.2 1675 | dev: true 1676 | engines: 1677 | node: '>= 4' 1678 | resolution: 1679 | integrity: sha512-5nbEG2YU7loyTvPABaKb+8B0u8L7vWCsVmCSsiaO249ZdMKlvrXlxR2ex4TUVAdzv/Cne/TdoXSSaJArGXaleQ== 1680 | /unicode-regex/3.0.0: 1681 | dependencies: 1682 | regexp-util: 1.2.2 1683 | dev: true 1684 | engines: 1685 | node: '>= 4' 1686 | resolution: 1687 | integrity: sha512-WiDJdORsqgxkZrjC8WsIP573130HNn7KsB0IDnUccW2BG2b19QQNloNhVe6DKk3Aef0UcoIHhNVj7IkkcYWrNw== 1688 | /unified/9.1.0: 1689 | dependencies: 1690 | bail: 1.0.5 1691 | extend: 3.0.2 1692 | is-buffer: 2.0.4 1693 | is-plain-obj: 2.1.0 1694 | trough: 1.0.5 1695 | vfile: 4.2.0 1696 | dev: true 1697 | resolution: 1698 | integrity: sha512-VXOv7Ic6twsKGJDeZQ2wwPqXs2hM0KNu5Hkg9WgAZbSD1pxhZ7p8swqg583nw1Je2fhwHy6U8aEjiI79x1gvag== 1699 | /uniq/1.0.1: 1700 | dev: true 1701 | resolution: 1702 | integrity: sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= 1703 | /unist-util-is/3.0.0: 1704 | dev: true 1705 | resolution: 1706 | integrity: sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== 1707 | /unist-util-remove-position/1.1.4: 1708 | dependencies: 1709 | unist-util-visit: 1.4.1 1710 | dev: true 1711 | resolution: 1712 | integrity: sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A== 1713 | /unist-util-stringify-position/2.0.3: 1714 | dependencies: 1715 | '@types/unist': 2.0.3 1716 | dev: true 1717 | resolution: 1718 | integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== 1719 | /unist-util-visit-parents/2.1.2: 1720 | dependencies: 1721 | unist-util-is: 3.0.0 1722 | dev: true 1723 | resolution: 1724 | integrity: sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== 1725 | /unist-util-visit/1.4.1: 1726 | dependencies: 1727 | unist-util-visit-parents: 2.1.2 1728 | dev: true 1729 | resolution: 1730 | integrity: sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== 1731 | /universalify/1.0.0: 1732 | dev: false 1733 | engines: 1734 | node: '>= 10.0.0' 1735 | resolution: 1736 | integrity: sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== 1737 | /uri-js/4.2.2: 1738 | dependencies: 1739 | punycode: 2.1.1 1740 | dev: false 1741 | resolution: 1742 | integrity: sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== 1743 | /utf8-byte-length/1.0.4: 1744 | dev: false 1745 | resolution: 1746 | integrity: sha1-9F8VDExm7uloGGUFq5P8u4rWv2E= 1747 | /util-deprecate/1.0.2: 1748 | dev: false 1749 | resolution: 1750 | integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 1751 | /verror/1.10.0: 1752 | dependencies: 1753 | assert-plus: 1.0.0 1754 | core-util-is: 1.0.2 1755 | extsprintf: 1.4.0 1756 | dev: false 1757 | engines: 1758 | '0': node >=0.6.0 1759 | resolution: 1760 | integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= 1761 | /vfile-location/2.0.6: 1762 | dev: true 1763 | resolution: 1764 | integrity: sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== 1765 | /vfile-message/2.0.4: 1766 | dependencies: 1767 | '@types/unist': 2.0.3 1768 | unist-util-stringify-position: 2.0.3 1769 | dev: true 1770 | resolution: 1771 | integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== 1772 | /vfile/4.2.0: 1773 | dependencies: 1774 | '@types/unist': 2.0.3 1775 | is-buffer: 2.0.4 1776 | replace-ext: 1.0.0 1777 | unist-util-stringify-position: 2.0.3 1778 | vfile-message: 2.0.4 1779 | dev: true 1780 | resolution: 1781 | integrity: sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw== 1782 | /vnopts/1.0.2: 1783 | dependencies: 1784 | chalk: 2.4.2 1785 | leven: 2.1.0 1786 | tslib: 1.13.0 1787 | dev: true 1788 | engines: 1789 | node: '>= 6' 1790 | resolution: 1791 | integrity: sha512-d2rr2EFhAGHnTlURu49G7GWmiJV80HbAnkYdD9IFAtfhmxC+kSWEaZ6ZF064DJFTv9lQZQV1vuLTntyQpoanGQ== 1792 | /word-wrap/1.2.3: 1793 | dev: false 1794 | engines: 1795 | node: '>=0.10.0' 1796 | resolution: 1797 | integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== 1798 | /wordwrap/1.0.0: 1799 | resolution: 1800 | integrity: sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= 1801 | /wrappy/1.0.2: 1802 | resolution: 1803 | integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1804 | /ws/6.2.1: 1805 | dependencies: 1806 | async-limiter: 1.0.1 1807 | dev: false 1808 | resolution: 1809 | integrity: sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== 1810 | /xml-writer/1.7.0: 1811 | dev: false 1812 | engines: 1813 | node: '>=0.4.0' 1814 | resolution: 1815 | integrity: sha1-t28dWRwWomNOvbcDx729D9aBkGU= 1816 | /xmldom/0.2.1: 1817 | dev: false 1818 | engines: 1819 | node: '>=0.1' 1820 | resolution: 1821 | integrity: sha512-kXXiYvmblIgEemGeB75y97FyaZavx6SQhGppLw5TKWAD2Wd0KAly0g23eVLh17YcpxZpnFym1Qk/eaRjy1APPg== 1822 | /xtend/4.0.2: 1823 | dev: true 1824 | engines: 1825 | node: '>=0.4' 1826 | resolution: 1827 | integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 1828 | /yallist/2.1.2: 1829 | dev: true 1830 | resolution: 1831 | integrity: sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= 1832 | /yaml-unist-parser/1.3.0: 1833 | dependencies: 1834 | lines-and-columns: 1.1.6 1835 | tslib: 1.13.0 1836 | yaml: 1.10.0 1837 | dev: true 1838 | engines: 1839 | node: '>= 6' 1840 | resolution: 1841 | integrity: sha512-kF1OS6fi9BzqX+vVC5hp+R5mmrHLH4f19Nx8fAwb08VqUwgFDBPOOu24VZO06nSOur13CGUTgHuaw5RIzpRnCw== 1842 | /yaml/1.10.0: 1843 | dev: true 1844 | engines: 1845 | node: '>= 6' 1846 | resolution: 1847 | integrity: sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== 1848 | /yauzl/2.10.0: 1849 | dependencies: 1850 | buffer-crc32: 0.2.13 1851 | fd-slicer: 1.1.0 1852 | dev: false 1853 | resolution: 1854 | integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= 1855 | specifiers: 1856 | ajv: ^6.12.4 1857 | am: ^1.0.2 1858 | await-sleep: ^0.0.1 1859 | better-ajv-errors: ^0.6.7 1860 | commander: ^6.0.0 1861 | crypto-random-string: ^3.2.0 1862 | escodegen: ^1.14.3 1863 | esprima: ^4.0.1 1864 | fast-glob: ^3.2.4 1865 | fs-extra: ^9.0.1 1866 | graphology: ^0.17.1 1867 | graphology-graphml: ^0.2.0 1868 | handlebars: ^4.7.6 1869 | iterare: ^1.2.1 1870 | jsonlint: ^1.6.3 1871 | line-column: ^1.0.2 1872 | lodash.groupby: ^4.6.0 1873 | lodash.sortby: ^4.7.0 1874 | prettierx: ^0.14.0 1875 | puppeteer-core: ^1.19.0 1876 | sanitize-filename: ^1.6.3 1877 | tmp-promise: ^3.0.2 1878 | verror: ^1.10.0 1879 | --------------------------------------------------------------------------------