From d72dd287c87bb2fc24ce63d4f4cb842e85a0b430 Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Mon, 2 Nov 2020 22:40:25 -0800 Subject: [PATCH] WIP (this commit will be re-written): update use native Node ESM for server code, update config files to specifically use .cjs (those tools don't support Node ESM files yet), use a single eslintrc file, all test code uses ESM import/export syntax instead of require (WIP) --- .eslintrc.js => .eslintrc.cjs | 30 + .prettierrc.js => .prettierrc.cjs | 2 + babel.config.cjs | 12 + babel.config.js | 12 - jest.config.js | 27 +- package-lock.json | 554 +++++++++++++++--- package.json | 40 +- packages/docsify-server-renderer/index.js | 8 +- .../docsify-server-renderer/package-lock.json | 65 +- .../docsify-server-renderer/src/utils.test.js | 21 +- server.js | 13 +- src/core/config.js | 2 +- src/core/event/index.js | 2 +- src/core/fetch/ajax.js | 4 +- src/core/fetch/index.js | 12 +- src/core/global-api.js | 2 +- src/core/init/index.js | 2 +- src/core/init/lifecycle.js | 2 +- src/core/render/compiler.js | 7 +- src/core/render/compiler/code.js | 2 +- src/core/render/embed.js | 2 +- src/core/render/index.js | 16 +- src/core/render/progressbar.js | 2 +- src/core/render/slugify.js | 2 +- src/core/router/util.js | 2 +- src/core/util/core.js | 4 +- src/core/util/env.js | 2 +- src/core/util/polyfill/css-vars.js | 2 +- src/plugins/disqus.js | 4 +- src/plugins/emoji.js | 6 +- src/plugins/external-script.js | 2 +- src/plugins/front-matter/index.js | 4 +- src/plugins/front-matter/parser.js | 36 +- src/plugins/front-matter/yaml.js | 396 ++++++------- src/plugins/ga.js | 4 +- src/plugins/matomo.js | 4 +- src/plugins/search/index.js | 2 +- src/plugins/search/search.js | 2 +- test/.eslintrc.js | 12 - test/config/jest-playwright.setup-tests.js | 4 +- test/config/jest.setup-tests.js | 8 +- test/config/jest.setup.cjs | 9 + test/config/jest.setup.js | 5 - test/config/jest.teardown.cjs | 4 + test/config/jest.teardown.js | 5 - test/config/server.js | 29 +- test/e2e/.eslintrc.js | 3 - test/e2e/example.test.js | 20 +- test/e2e/search.test.js | 4 +- test/e2e/vue.test.js | 8 +- test/helpers/docsify-init.js | 36 +- test/helpers/wait-for.js | 2 +- test/integration/docs.test.js | 11 +- test/integration/docsify.test.js | 11 +- test/integration/example.test.js | 9 +- test/integration/global-apis.test.js | 4 +- test/integration/render.test.js | 62 +- test/unit/example.test.js | 56 +- test/unit/render-util.test.js | 2 +- test/unit/router-history-base.test.js | 2 +- test/unit/router-util.test.js | 2 +- test/unit/server.test.js | 49 +- 62 files changed, 1052 insertions(+), 616 deletions(-) rename .eslintrc.js => .eslintrc.cjs (68%) rename .prettierrc.js => .prettierrc.cjs (67%) create mode 100644 babel.config.cjs delete mode 100644 babel.config.js delete mode 100644 test/.eslintrc.js create mode 100644 test/config/jest.setup.cjs delete mode 100644 test/config/jest.setup.js create mode 100644 test/config/jest.teardown.cjs delete mode 100644 test/config/jest.teardown.js delete mode 100644 test/e2e/.eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 68% rename from .eslintrc.js rename to .eslintrc.cjs index b15f54fe..85f78621 100644 --- a/.eslintrc.js +++ b/.eslintrc.cjs @@ -1,3 +1,20 @@ +const deasync = require('deasync'); // powerful magic + +const promiseSync = deasync((promise, cb) => { + promise.then((result) => cb(null, result)).catch((error) => cb(error)); +}); + +const importSync = (name) => promiseSync(import(name)); + +// Look, no await needed here! +const jestConfig = importSync('./jest.config').default; + +const testGlobals = {}; + +for (const key of Object.keys(jestConfig.globals)) { + testGlobals[key] = 'readonly'; +} + module.exports = { root: true, parser: 'babel-eslint', @@ -39,6 +56,7 @@ module.exports = { 'no-var': ['error'], 'no-void': ['error'], 'no-with': ['error'], + 'no-prototype-builtins': 'off', radix: ['error'], 'spaced-comment': ['error', 'always'], strict: ['error', 'global'], @@ -60,4 +78,16 @@ module.exports = { $docsify: 'writable', dom: 'writable', }, + + overrides: [ + { + files: ['test/**/*.js', '**/*.test.js'], + extends: ['plugin:jest/recommended', 'plugin:jest/style'], + globals: testGlobals, + }, + { + files: ['test/e2e/**/*.test.js'], + extends: ['plugin:jest-playwright/recommended'], + }, + ], }; diff --git a/.prettierrc.js b/.prettierrc.cjs similarity index 67% rename from .prettierrc.js rename to .prettierrc.cjs index a425d3f7..3d939b4d 100644 --- a/.prettierrc.js +++ b/.prettierrc.cjs @@ -1,4 +1,6 @@ module.exports = { singleQuote: true, trailingComma: 'es5', + useTabs: false, + tabWidth: 2, }; diff --git a/babel.config.cjs b/babel.config.cjs new file mode 100644 index 00000000..e5d84df6 --- /dev/null +++ b/babel.config.cjs @@ -0,0 +1,12 @@ +module.exports = { + // presets: [ + // [ + // '@babel/preset-env', + // { + // targets: { + // node: 'current', + // }, + // }, + // ], + // ], +}; diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index f037a1a2..00000000 --- a/babel.config.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - presets: [ - [ - '@babel/preset-env', - { - targets: { - node: 'current', - }, - }, - ], - ], -}; diff --git a/jest.config.js b/jest.config.js index 09cfec85..a78a0e8a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,22 +1,31 @@ -const path = require('path'); -const { globals: serverGlobals } = require('./test/config/server.js'); +import path from 'path'; +import server from './test/config/server'; + +const { globals: serverGlobals } = server; +const dirname = path.dirname(import.meta.url.replace('file://', '')); const sharedConfig = { errorOnDeprecated: true, globals: { ...serverGlobals, // BLANK_URL, DOCS_URL, LIB_URL, NODE_MODULES_URL, TEST_HOST - DOCS_PATH: path.resolve(__dirname, 'docs'), - LIB_PATH: path.resolve(__dirname, 'lib'), - SRC_PATH: path.resolve(__dirname, 'src'), + DOCS_PATH: path.resolve(dirname, 'docs'), + LIB_PATH: path.resolve(dirname, 'lib'), + SRC_PATH: path.resolve(dirname, 'src'), }, - globalSetup: './test/config/jest.setup.js', - globalTeardown: './test/config/jest.teardown.js', + globalSetup: './test/config/jest.setup.cjs', + globalTeardown: './test/config/jest.teardown.cjs', resetModules: true, restoreMocks: true, }; -module.exports = { - // Adding globals to config root for easier importing into .eslint.js, but +// Jest configuration: https://jestjs.io/docs/en/configuration + +export default { + // Disable transforms, we'll write plain JS. This is also needed for native + // ESM (see https://jestjs.io/docs/en/ecmascript-modules). + transform: {}, + + // Adding globals to config root for easier importing into .eslint.cjs, but // as of Jest 26.4.2 these globals need to be added to each project config // as well. globals: sharedConfig.globals, diff --git a/package-lock.json b/package-lock.json index caf481fe..6cea8ef5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2362,6 +2362,81 @@ "minimist": "^1.2.0" } }, + "@eslint/eslintrc": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz", + "integrity": "sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "import-fresh": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, "@evocateur/libnpmaccess": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz", @@ -5847,6 +5922,15 @@ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", @@ -8610,6 +8694,16 @@ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true }, + "deasync": { + "version": "0.1.20", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.20.tgz", + "integrity": "sha512-E1GI7jMI57hL30OX6Ht/hfQU8DO4AuB9m72WFm4c38GNbUD4Q03//XZaOIHZiY+H1xUaomcot5yk2q/qIZQkGQ==", + "dev": true, + "requires": { + "bindings": "^1.5.0", + "node-addon-api": "^1.7.1" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -9225,6 +9319,12 @@ "string.prototype.trimright": "^2.1.0" } }, + "es-main": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-main/-/es-main-1.0.2.tgz", + "integrity": "sha512-LLgW8Cby/FiyQygrI23q2EswulHiDKoyjWlDRgTGXjQ3iRim2R26VfoehpxI5oKRXSNams3L/80KtggoUdxdDQ==", + "dev": true + }, "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", @@ -9288,76 +9388,166 @@ } }, "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.12.1.tgz", + "integrity": "sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", + "@eslint/eslintrc": "^0.2.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", + "levn": "^0.4.1", + "lodash": "^4.17.19", "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", + "optionator": "^0.9.1", "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", "table": "^5.2.3", - "text-table": "^0.2.0" + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "color-convert": "^2.0.1" } }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "import-fresh": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", - "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, "resolve-from": { @@ -9367,34 +9557,43 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "ansi-regex": "^5.0.0" } }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, @@ -9599,22 +9798,22 @@ } }, "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "requires": { - "esrecurse": "^4.1.0", + "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "eslint-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", - "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.0.0" + "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { @@ -9629,14 +9828,34 @@ "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" }, "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", "dev": true, "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" + "acorn": "^7.4.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } } }, "esprima": { @@ -9645,21 +9864,37 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "estraverse": { @@ -10001,6 +10236,29 @@ } } }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -10132,6 +10390,12 @@ "flat-cache": "^2.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -10372,9 +10636,9 @@ } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, "flush-write-stream": { @@ -15695,7 +15959,11 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } }, "glob-parent": { "version": "3.1.0", @@ -16889,6 +17157,13 @@ "thenify-all": "^1.0.0" } }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -16932,6 +17207,12 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true + }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", @@ -18455,6 +18736,73 @@ } } }, + "playwright-firefox": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/playwright-firefox/-/playwright-firefox-1.5.2.tgz", + "integrity": "sha512-9iWi357NwVrZIPpMa1Fl2rPJCDAfAeScFc2rdEeIEIY4S6pAiSiXX2cxnZKH6m4X9h8m5FuezINHoW57VqGiXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "extract-zip": "^2.0.1", + "https-proxy-agent": "^5.0.0", + "jpeg-js": "^0.4.2", + "mime": "^2.4.6", + "pngjs": "^5.0.0", + "progress": "^2.0.3", + "proper-lockfile": "^4.1.1", + "proxy-from-env": "^1.1.0", + "rimraf": "^3.0.2", + "ws": "^7.3.1" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "dev": true + } + } + }, "please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", @@ -19029,9 +19377,9 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", "dev": true }, "prettier-linter-helpers": { @@ -19464,9 +19812,9 @@ } }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", "dev": true }, "regexpu-core": { @@ -21410,9 +21758,9 @@ } }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "strong-log-transformer": { @@ -22346,6 +22694,12 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, "v8-to-istanbul": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-6.0.1.tgz", @@ -22562,6 +22916,12 @@ "execa": "^1.0.0" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/package.json b/package.json index 94469e3f..5485ae28 100644 --- a/package.json +++ b/package.json @@ -22,28 +22,33 @@ ], "scripts": { "bootstrap": "npm i && lerna bootstrap", - "serve": "node server", - "serve:ssr": "cross-env SSR=1 node --experimental-specifier-resolution=node server", + "serve": "npm run _node -- server", + "serve:ssr": "cross-env SSR=1 npm run _node -- server", "dev": "run-p serve watch:*", "dev:ssr": "run-p serve:ssr watch:*", - "lint": "eslint .", - "fixlint": "eslint . --fix", - "test": "jest --runInBand", - "test:e2e": "jest --selectProjects e2e", - "test:integration": "jest --selectProjects integration", - "test:unit": "jest --selectProjects unit", - "css": "node build/css", + "lint": "npm run _eslint -- .", + "fixlint": "npm run _eslint -- . --fix", + "test": "npm run _jest -- --runInBand", + "test:e2e": "npm run _jest -- --selectProjects e2e", + "test:integration": "npm run _jest -- --selectProjects integration", + "test:unit": "npm run _jest -- --selectProjects unit", + "css": "npm run _node -- build/css", "watch:css": "npm run css -- -o themes -w", - "watch:js": "node build/build.js", - "build:css:min": "mkdirp lib/themes && npm run css -- -o lib/themes && node build/mincss.js", + "watch:js": "npm run _node -- build/build.js", + "build:css:min": "mkdirp lib/themes && npm run css -- -o lib/themes && npm run _node -- build/mincss.js", "build:css": "mkdirp themes && npm run css -- -o themes", - "build:js": "cross-env NODE_ENV=production node build/build.js", - "build:cover": "node build/cover.js", + "build:js": "cross-env NODE_ENV=production npm run _node -- build/build.js", + "build:cover": "npm run _node -- build/cover.js", "build": "rimraf lib themes && run-s build:js build:css build:css:min build:cover", "prepare": "npm run build", "pub:next": "cross-env RELEASE_TAG=next sh build/release.sh", "pub": "sh build/release.sh", - "postinstall": "opencollective-postinstall" + "postinstall": "opencollective-postinstall", + "_node": "node --experimental-specifier-resolution=node", + "_eslint": "DISABLE_V8_COMPILE_CACHE=1 npm run _node -- ./node_modules/.bin/eslint", + "// ^ _eslint comment": "The DISABLE_V8_COMPILE_CACHE=1 var enables ESM import() in .eslintrc.cjs. See https://github.com/eslint/eslint/issues/13684", + "_jest": "npm run _node -- --experimental-vm-modules ./node_modules/.bin/jest", + "// ^ _jest comment": "--experimental-vm-modules is needed in order to enable full native ESM support in Jest" }, "husky-OFF": { "hooks": { @@ -79,7 +84,9 @@ "copy-dir": "^1.2.0", "cross-env": "^6.0.3", "cssnano": "^4.1.10", - "eslint": "^5.16.0", + "deasync": "^0.1.20", + "es-main": "^1.0.2", + "eslint": "^7.12.1", "eslint-plugin-import": "^2.20.1", "eslint-plugin-jest": "^24.0.2", "eslint-plugin-jest-playwright": "^0.2.1", @@ -94,7 +101,8 @@ "mkdirp": "^0.5.1", "npm-run-all": "^4.1.5", "playwright": "^1.4.1", - "prettier": "^1.19.1", + "playwright-firefox": "^1.5.2", + "prettier": "^2.0.0", "rimraf": "^3.0.0", "rollup": "^1.23.1", "rollup-plugin-async": "^1.2.0", diff --git a/packages/docsify-server-renderer/index.js b/packages/docsify-server-renderer/index.js index 3a48bef4..694aec9d 100644 --- a/packages/docsify-server-renderer/index.js +++ b/packages/docsify-server-renderer/index.js @@ -62,6 +62,10 @@ export default class Renderer { return isAbsolutePath(file) ? file : cwd(`./${file}`); } + /** + * @param {string} url + * @returns {Promise} + */ async renderToString(url) { this.url = url = this.router.parse(url).path; this.isRemoteUrl = isExternal(this.url); @@ -128,10 +132,10 @@ export default class Renderer { html = this.compiler.cover(html); break; case 'main': - tokens = await new Promise(r => { + tokens = await new Promise((r) => { prerenderEmbed( { - fetch: url => this._loadFile(this._getPath(url)), + fetch: (url) => this._loadFile(this._getPath(url)), compiler: this.compiler, raw: html, }, diff --git a/packages/docsify-server-renderer/package-lock.json b/packages/docsify-server-renderer/package-lock.json index 0305fcfe..ebd37793 100644 --- a/packages/docsify-server-renderer/package-lock.json +++ b/packages/docsify-server-renderer/package-lock.json @@ -1,6 +1,6 @@ { "name": "docsify-server-renderer", - "version": "4.11.2", + "version": "4.11.6", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -16,11 +16,11 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", + "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "delegate": { @@ -30,23 +30,24 @@ "optional": true }, "docsify": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/docsify/-/docsify-4.11.2.tgz", - "integrity": "sha512-vQVg+ERdYgrlgLcwTX9FdjUn3xb7PSwaiYopIAmCLraHJCr1e0r8Uzi2vm6XEwTrSrdd6C5j3Eg+QctsOGA4Gg==", + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/docsify/-/docsify-4.11.6.tgz", + "integrity": "sha512-6h3hB2Ni7gpOeu1fl1sDOmufuplIDmeFHsps17Qbg9VOS3h2tJ63FiW2w5oAydGyzaLrqu58FV7Mg4b6p0z9mg==", "requires": { - "marked": "^0.7.0", - "medium-zoom": "^1.0.5", + "dompurify": "^2.0.8", + "marked": "^1.1.1", + "medium-zoom": "^1.0.6", "opencollective-postinstall": "^2.0.2", "prismjs": "^1.19.0", "strip-indent": "^3.0.0", - "tinydate": "^1.0.0", + "tinydate": "^1.3.0", "tweezer.js": "^1.4.0" } }, "dompurify": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.8.tgz", - "integrity": "sha512-vIOSyOXkMx81ghEalh4MLBtDHMx1bhKlaqHDMqM2yeitJ996SLOk5mGdDpI9ifJAgokred8Rmu219fX4OltqXw==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.2.tgz", + "integrity": "sha512-BsGR4nDLaC5CNBnyT5I+d5pOeaoWvgVeg6Gq/aqmKYWMPR07131u60I80BvExLAJ0FQEIBQ1BTicw+C5+jOyrg==" }, "good-listener": { "version": "1.2.2", @@ -58,19 +59,19 @@ } }, "marked": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", - "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==" + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.3.tgz", + "integrity": "sha512-RQuL2i6I6Gn+9n81IDNGbL0VHnta4a+8ZhqvryXEniTb/hQNtf3i26hi1XWUhzb9BgVyWHKR3UO8MaHtKoYibw==" }, "medium-zoom": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.5.tgz", - "integrity": "sha512-aLGa6WlTuFKWvH88bqTrY5ztJMN+D0hd8UX6BYc4YSoPayppzETjZUcdVcksgaoQEMg4cZSmXPg846fTp2rjRQ==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.6.tgz", + "integrity": "sha512-UdiUWfvz9fZMg1pzf4dcuqA0W079o0mpqbTnOz5ip4VGYX96QjmbM+OgOU/0uOzAytxC0Ny4z+VcYQnhdifimg==" }, "min-indent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.0.tgz", - "integrity": "sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" }, "ms": { "version": "2.1.2", @@ -83,14 +84,14 @@ "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, "opencollective-postinstall": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz", - "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==" }, "prismjs": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.19.0.tgz", - "integrity": "sha512-IVFtbW9mCWm9eOIaEkNyo2Vl4NnEifis2GQ7/MLRG5TQe6t+4Sj9J5QWI9i3v+SS43uZBlCAOn+zYTVYQcPXJw==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.22.0.tgz", + "integrity": "sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w==", "requires": { "clipboard": "^2.0.0" } @@ -121,9 +122,9 @@ "optional": true }, "tinydate": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.2.0.tgz", - "integrity": "sha512-3GwPk8VhDFnUZ2TrgkhXJs6hcMAIIw4x/xkz+ayK6dGoQmp2nUwKzBXK0WnMsqkh6vfUhpqQicQF3rbshfyJkg==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", + "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==" }, "tweezer.js": { "version": "1.5.0", diff --git a/packages/docsify-server-renderer/src/utils.test.js b/packages/docsify-server-renderer/src/utils.test.js index ca0dca55..9dbecb01 100644 --- a/packages/docsify-server-renderer/src/utils.test.js +++ b/packages/docsify-server-renderer/src/utils.test.js @@ -1,25 +1,24 @@ // @ts-check - import { isExternal } from './utils'; -// import { docsifyInit } from '../helpers/docsify-init'; describe('isExternal', () => { test('detects whether links are external or not', async () => { - // initJSDOM('', { - // url: 'http://127.0.0.1:3000', - // runScripts: 'dangerously', - // resources: 'usable', - // }); - - // docsifyInit(); + // Note, Jest tests operate under the origin "http://127.0.0.1:3001" expect(isExternal).toBeInstanceOf(Function); expect(isExternal('/foo.md')).toBe(false); expect(isExternal('//foo.md')).toBe(true); - expect(isExternal('//127.0.0.1:3000/foo.md')).toBe(false); - expect(isExternal('http://127.0.0.1:3001/foo.md')).toBe(true); + expect(isExternal('foo.md')).toBe(false); + expect(isExternal('//127.0.0.1:3000/foo.md')).toBe(true); + expect(isExternal('//127.0.0.1:3001/foo.md')).toBe(false); + expect(isExternal('http://127.0.0.1:3000/foo.md')).toBe(true); + expect(isExternal('https://127.0.0.1:3000/foo.md')).toBe(true); + expect(isExternal('http://127.0.0.1:3001/foo.md')).toBe(false); + expect(isExternal('https://127.0.0.1:3001/foo.md')).toBe(true); expect(isExternal('https://google.com/foo.md')).toBe(true); expect(isExternal('//google.com/foo.md')).toBe(true); expect(isExternal('/google.com/foo.md')).toBe(false); + expect(isExternal('google.com')).toBe(false); + expect(isExternal('google.com/foo.md')).toBe(false); }); }); diff --git a/server.js b/server.js index 4d11e439..4796b3a7 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,5 @@ -// const liveServer = require('live-server'); import liveServer from 'live-server'; + const isSSR = !!process.env.SSR; const middleware = []; @@ -12,13 +12,7 @@ async function main() { // URL to operate under (it probably can be anything). initJSDOM('', { url: 'https://127.0.0.1:3000' }); - // const requireESM = require('esm')(module /* , options */); - // const { Renderer, getServerHTMLTemplate } = requireESM( - // './packages/docsify-server-renderer/index' - // ); - const { Renderer, getServerHTMLTemplate } = await import( - // './packages/docsify-server-renderer/index.js' './packages/docsify-server-renderer/index' ); @@ -41,11 +35,11 @@ async function main() { }, }); - middleware.push(function(req, res, next) { + middleware.push(function (req, res, next) { if (/\.(css|js)$/.test(req.url)) { return next(); } - renderer.renderToString(req.url).then(html => res.end(html)); + renderer.renderToString(req.url).then((html) => res.end(html)); }); } @@ -59,7 +53,6 @@ async function main() { } async function initJSDOM(markup, options) { - // const { JSDOM } = require('jsdom'); const { JSDOM } = (await import('jsdom')).default; const dom = new JSDOM(markup, options); diff --git a/src/core/config.js b/src/core/config.js index 2d23f5db..2fa99fba 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -2,7 +2,7 @@ import { merge, hyphenate, isPrimitive, hasOwn } from './util/core'; const currentScript = document.currentScript; -export default function(vm) { +export default function (vm) { const config = merge( { el: '#app', diff --git a/src/core/event/index.js b/src/core/event/index.js index 4a312421..88bd54e8 100644 --- a/src/core/event/index.js +++ b/src/core/event/index.js @@ -4,7 +4,7 @@ import * as sidebar from './sidebar'; import { scrollIntoView, scroll2Top } from './scroll'; export function eventMixin(proto) { - proto.$resetEvents = function(source) { + proto.$resetEvents = function (source) { const { auto2top } = this.config; (() => { diff --git a/src/core/fetch/ajax.js b/src/core/fetch/ajax.js index 319ab1a8..a7896b0e 100644 --- a/src/core/fetch/ajax.js +++ b/src/core/fetch/ajax.js @@ -13,7 +13,7 @@ const cache = {}; */ export function get(url, hasBar = false, headers = {}) { const xhr = new XMLHttpRequest(); - const on = function() { + const on = function () { xhr.addEventListener.apply(xhr, arguments); }; @@ -33,7 +33,7 @@ export function get(url, hasBar = false, headers = {}) { xhr.send(); return { - then: function(success, error = noop) { + then: function (success, error = noop) { if (hasBar) { const id = setInterval( _ => diff --git a/src/core/fetch/index.js b/src/core/fetch/index.js index ea48ecb1..6b0b1a32 100644 --- a/src/core/fetch/index.js +++ b/src/core/fetch/index.js @@ -60,7 +60,7 @@ export function fetchMixin(proto) { return path404; }; - proto._loadSideAndNav = function(path, qs, loadSidebar, cb) { + proto._loadSideAndNav = function (path, qs, loadSidebar, cb) { return () => { if (!loadSidebar) { return cb(); @@ -76,7 +76,7 @@ export function fetchMixin(proto) { }; }; - proto._fetch = function(cb = noop) { + proto._fetch = function (cb = noop) { const { path, query } = this.route; const qs = stringifyQuery(query, ['id']); const { loadNavbar, requestHeaders, loadSidebar } = this.config; @@ -114,7 +114,7 @@ export function fetchMixin(proto) { ); }; - proto._fetchCover = function() { + proto._fetchCover = function () { const { coverpage, requestHeaders } = this.config; const query = this.route.query; const root = getParentPath(this.route.path); @@ -150,7 +150,7 @@ export function fetchMixin(proto) { } }; - proto.$fetch = function( + proto.$fetch = function ( cb = noop, $resetEvents = this.$resetEvents.bind(this) ) { @@ -171,7 +171,7 @@ export function fetchMixin(proto) { } }; - proto._fetchFallbackPage = function(path, qs, cb = noop) { + proto._fetchFallbackPage = function (path, qs, cb = noop) { const { requestHeaders, fallbackLanguages, loadSidebar } = this.config; if (!fallbackLanguages) { @@ -210,7 +210,7 @@ export function fetchMixin(proto) { * @returns {Boolean} True if the requested page is not found * @private */ - proto._fetch404 = function(path, qs, cb = noop) { + proto._fetch404 = function (path, qs, cb = noop) { const { loadSidebar, requestHeaders, notFoundPage } = this.config; const fnLoadSideAndNav = this._loadSideAndNav(path, qs, loadSidebar, cb); diff --git a/src/core/global-api.js b/src/core/global-api.js index a5f69f6f..53695975 100644 --- a/src/core/global-api.js +++ b/src/core/global-api.js @@ -10,7 +10,7 @@ import { get } from './fetch/ajax'; // major release. We'll tell people to get everything from the DOCSIFY global // when using the global build, but we'll highly recommend for them to import // from the ESM build (f.e. lib/docsify.esm.js and lib/docsify.min.esm.js). -export default function() { +export default function () { window.Docsify = { util, dom, diff --git a/src/core/init/index.js b/src/core/init/index.js index 255aad06..1a62cd43 100644 --- a/src/core/init/index.js +++ b/src/core/init/index.js @@ -7,7 +7,7 @@ import { isFn } from '../util/core'; import { initLifecycle, callHook } from './lifecycle'; export function initMixin(proto) { - proto._init = function() { + proto._init = function () { const vm = this; vm.config = config(vm); diff --git a/src/core/init/lifecycle.js b/src/core/init/lifecycle.js index d695ed6e..291e0d28 100644 --- a/src/core/init/lifecycle.js +++ b/src/core/init/lifecycle.js @@ -21,7 +21,7 @@ export function initLifecycle(vm) { export function callHook(vm, hookName, data, next = noop) { const queue = vm._hooks[hookName]; - const step = function(index) { + const step = function (index) { const hookFn = queue[index]; if (index >= queue.length) { diff --git a/src/core/render/compiler.js b/src/core/render/compiler.js index 68edd274..85491517 100644 --- a/src/core/render/compiler.js +++ b/src/core/render/compiler.js @@ -28,8 +28,9 @@ const compileMedia = { }, iframe(url, title) { return { - html: ``, + html: ``, }; }, video(url, title) { @@ -205,7 +206,7 @@ export class Compiler { * @param {Number} level Type of heading (h tag) * @returns {String} Heading element */ - origin.heading = renderer.heading = function(text, level) { + origin.heading = renderer.heading = function (text, level) { let { str, config } = getAndRemoveConfig(text); const nextToc = { level, title: removeAtag(str) }; diff --git a/src/core/render/compiler/code.js b/src/core/render/compiler/code.js index 2aa14deb..b7fb060d 100644 --- a/src/core/render/compiler/code.js +++ b/src/core/render/compiler/code.js @@ -3,7 +3,7 @@ import Prism from 'prismjs'; import 'prismjs/components/prism-markup-templating'; export const highlightCodeCompiler = ({ renderer }) => - (renderer.code = function(code, lang = 'markup') { + (renderer.code = function (code, lang = 'markup') { const langOrMarkup = Prism.languages[lang] || Prism.languages.markup; const text = Prism.highlight( code.replace(/@DOCSIFY_QM@/g, '`'), diff --git a/src/core/render/embed.js b/src/core/render/embed.js index 5159754a..34fcb779 100644 --- a/src/core/render/embed.js +++ b/src/core/render/embed.js @@ -15,7 +15,7 @@ function walkFetchEmbed({ embedTokens, compile, fetch }, cb) { while ((token = embedTokens[step++])) { // eslint-disable-next-line no-shadow - const next = (function(token) { + const next = (function (token) { return text => { let embedToken; if (text) { diff --git a/src/core/render/index.js b/src/core/render/index.js index de7de51d..6db092e5 100644 --- a/src/core/render/index.js +++ b/src/core/render/index.js @@ -90,7 +90,7 @@ function renderMain(html) { if (!isAlreadyVue) { new window.Vue({ - mounted: function() { + mounted: function () { this.$destroy(); }, }).$mount(elm); @@ -121,14 +121,14 @@ function renderNameLink(vm) { } export function renderMixin(proto) { - proto._renderTo = function(el, content, replace) { + proto._renderTo = function (el, content, replace) { const node = dom.getNode(el); if (node) { node[replace ? 'outerHTML' : 'innerHTML'] = content; } }; - proto._renderSidebar = function(text) { + proto._renderSidebar = function (text) { const { maxLevel, subMaxLevel, loadSidebar, hideSidebar } = this.config; if (hideSidebar) { @@ -156,7 +156,7 @@ export function renderMixin(proto) { this._bindEventOnRendered(activeEl); }; - proto._bindEventOnRendered = function(activeEl) { + proto._bindEventOnRendered = function (activeEl) { const { autoHeader } = this.config; scrollActiveSidebar(this.router); @@ -172,14 +172,14 @@ export function renderMixin(proto) { } }; - proto._renderNav = function(text) { + proto._renderNav = function (text) { text && this._renderTo('nav', this.compiler.compile(text)); if (this.config.loadNavbar) { getAndActive(this.router, 'nav'); } }; - proto._renderMain = function(text, opt = {}, next) { + proto._renderMain = function (text, opt = {}, next) { if (!text) { return renderMain.call(this, text); } @@ -217,7 +217,7 @@ export function renderMixin(proto) { }); }; - proto._renderCover = function(text, coverOnly) { + proto._renderCover = function (text, coverOnly) { const el = dom.getNode('.cover'); dom.toggleClass( @@ -261,7 +261,7 @@ export function renderMixin(proto) { sticky(); }; - proto._updateRender = function() { + proto._updateRender = function () { // Render name link renderNameLink(this); }; diff --git a/src/core/render/progressbar.js b/src/core/render/progressbar.js index 762ec628..c48b9619 100644 --- a/src/core/render/progressbar.js +++ b/src/core/render/progressbar.js @@ -17,7 +17,7 @@ function init() { /** * Render progress bar */ -export default function({ loaded, total, step }) { +export default function ({ loaded, total, step }) { let num; !barEl && init(); diff --git a/src/core/render/slugify.js b/src/core/render/slugify.js index 1d3c24b3..ca0efa87 100644 --- a/src/core/render/slugify.js +++ b/src/core/render/slugify.js @@ -32,6 +32,6 @@ export function slugify(str) { return slug; } -slugify.clear = function() { +slugify.clear = function () { cache = {}; }; diff --git a/src/core/router/util.js b/src/core/router/util.js index fc3e2f79..53a98486 100644 --- a/src/core/router/util.js +++ b/src/core/router/util.js @@ -13,7 +13,7 @@ export function parseQuery(query) { } // Simple parse - query.split('&').forEach(function(param) { + query.split('&').forEach(function (param) { const parts = param.replace(/\+/g, ' ').split('='); res[parts[0]] = parts[1] && decode(parts[1]); diff --git a/src/core/util/core.js b/src/core/util/core.js index 9d263841..233a0eaf 100644 --- a/src/core/util/core.js +++ b/src/core/util/core.js @@ -6,7 +6,7 @@ export function cached(fn) { const cache = Object.create(null); - return function(str) { + return function (str) { const key = isPrimitive(str) ? str : JSON.stringify(str); const hit = cache[key]; return hit || (cache[key] = fn(str)); @@ -29,7 +29,7 @@ export const hasOwn = Object.prototype.hasOwnProperty; */ export const merge = Object.assign || - function(to) { + function (to) { for (let i = 1; i < arguments.length; i++) { const from = Object(arguments[i]); diff --git a/src/core/util/env.js b/src/core/util/env.js index 015179c5..22c47382 100644 --- a/src/core/util/env.js +++ b/src/core/util/env.js @@ -7,7 +7,7 @@ export const isMobile = inBrowser && document.body.clientWidth <= 600; */ export const supportsPushState = inBrowser && - (function() { + (function () { // Borrowed wholesale from https://github.com/defunkt/jquery-pjax return ( window.history && diff --git a/src/core/util/polyfill/css-vars.js b/src/core/util/polyfill/css-vars.js index 34e201f2..6c9ef2a3 100644 --- a/src/core/util/polyfill/css-vars.js +++ b/src/core/util/polyfill/css-vars.js @@ -8,7 +8,7 @@ function replaceVar(block, color) { ); } -export default function(color) { +export default function (color) { // Variable support if (window.CSS && window.CSS.supports && window.CSS.supports('(--v:red)')) { return; diff --git a/src/plugins/disqus.js b/src/plugins/disqus.js index 4355692e..38719055 100644 --- a/src/plugins/disqus.js +++ b/src/plugins/disqus.js @@ -28,7 +28,7 @@ function install(hook, vm) { dom.appendTo(dom.find('.content'), div); // eslint-disable-next-line - window.disqus_config = function() { + window.disqus_config = function () { this.page.url = location.origin + '/-' + vm.route.path; this.page.identifier = vm.route.path; this.page.title = document.title; @@ -39,7 +39,7 @@ function install(hook, vm) { if (typeof window.DISQUS !== 'undefined') { window.DISQUS.reset({ reload: true, - config: function() { + config: function () { this.page.url = location.origin + '/-' + vm.route.path; this.page.identifier = vm.route.path; this.page.title = document.title; diff --git a/src/plugins/emoji.js b/src/plugins/emoji.js index 8eb13190..2cc8c813 100644 --- a/src/plugins/emoji.js +++ b/src/plugins/emoji.js @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ const AllGithubEmoji = { - '100': 'unicode/1f4af', - '1234': 'unicode/1f522', + 100: 'unicode/1f4af', + 1234: 'unicode/1f522', '+1': 'unicode/1f44d', '-1': 'unicode/1f44e', '1st_place_medal': 'unicode/1f947', @@ -1804,7 +1804,7 @@ const AllGithubEmoji = { // Emoji from GitHub API // https://api.github.com/emojis -window.emojify = function(match, $1) { +window.emojify = function (match, $1) { return AllGithubEmoji.hasOwnProperty($1) === false ? match : ' curLevel) { - var oldBlock = currentBlock - currentBlock = new Block(level) - oldBlock.addChild(currentBlock) - blocks.push(currentBlock) - levels.push(level) + var oldBlock = currentBlock; + currentBlock = new Block(level); + oldBlock.addChild(currentBlock); + blocks.push(currentBlock); + levels.push(level); } else if (level < curLevel) { - var added = false + var added = false; - var k = levels.length - 1 + var k = levels.length - 1; for (; k >= 0; --k) { if (levels[k] == level) { - currentBlock = new Block(level) - blocks.push(currentBlock) - levels.push(level) - if (blocks[k].parent != null) blocks[k].parent.addChild(currentBlock) - added = true - break + currentBlock = new Block(level); + blocks.push(currentBlock); + levels.push(level); + if (blocks[k].parent != null) blocks[k].parent.addChild(currentBlock); + added = true; + break; } } if (!added) { - errors.push('Error: Invalid indentation at line ' + i + ': ' + line) - return + errors.push('Error: Invalid indentation at line ' + i + ': ' + line); + return; } } - currentBlock.lines.push(line.replace(regex['trim'], '')) - curLevel = level + currentBlock.lines.push(line.replace(regex['trim'], '')); + curLevel = level; } - return result + return result; } function processValue(val) { - val = val.replace(regex['trim'], '') - var m = null + val = val.replace(regex['trim'], ''); + var m = null; if (val == 'true') { - return true + return true; } else if (val == 'false') { - return false + return false; } else if (val == '.NaN') { - return Number.NaN + return Number.NaN; } else if (val == 'null') { - return null + return null; } else if (val == '.inf') { - return Number.POSITIVE_INFINITY + return Number.POSITIVE_INFINITY; } else if (val == '-.inf') { - return Number.NEGATIVE_INFINITY + return Number.NEGATIVE_INFINITY; } else if ((m = val.match(regex['dashesString']))) { - return m[1] + return m[1]; } else if ((m = val.match(regex['quotesString']))) { - return m[1] + return m[1]; } else if ((m = val.match(regex['float']))) { - return parseFloat(m[0]) + return parseFloat(m[0]); } else if ((m = val.match(regex['integer']))) { - return parseInt(m[0]) + return parseInt(m[0]); } else if (!isNaN((m = Date.parse(val)))) { - return new Date(m) + return new Date(m); } else if ((m = val.match(regex['single_key_value']))) { - var res = {} - res[m[1]] = processValue(m[2]) - return res + var res = {}; + res[m[1]] = processValue(m[2]); + return res; } else if ((m = val.match(regex['array']))) { var count = 0, - c = ' ' - var res = [] - var content = '' - var str = false + c = ' '; + var res = []; + var content = ''; + var str = false; for (var j = 0, lenJ = m[1].length; j < lenJ; ++j) { - c = m[1][j] + c = m[1][j]; if (c == "'" || c == '"') { if (str === false) { - str = c - content += c - continue + str = c; + content += c; + continue; } else if ((c == "'" && str == "'") || (c == '"' && str == '"')) { - str = false - content += c - continue + str = false; + content += c; + continue; } } else if (str === false && (c == '[' || c == '{')) { - ++count + ++count; } else if (str === false && (c == ']' || c == '}')) { - --count + --count; } else if (str === false && count == 0 && c == ',') { - res.push(processValue(content)) - content = '' - continue + res.push(processValue(content)); + content = ''; + continue; } - content += c + content += c; } - if (content.length > 0) res.push(processValue(content)) - return res + if (content.length > 0) res.push(processValue(content)); + return res; } else if ((m = val.match(regex['map']))) { var count = 0, - c = ' ' - var res = [] - var content = '' - var str = false + c = ' '; + var res = []; + var content = ''; + var str = false; for (var j = 0, lenJ = m[1].length; j < lenJ; ++j) { - c = m[1][j] + c = m[1][j]; if (c == "'" || c == '"') { if (str === false) { - str = c - content += c - continue + str = c; + content += c; + continue; } else if ((c == "'" && str == "'") || (c == '"' && str == '"')) { - str = false - content += c - continue + str = false; + content += c; + continue; } } else if (str === false && (c == '[' || c == '{')) { - ++count + ++count; } else if (str === false && (c == ']' || c == '}')) { - --count + --count; } else if (str === false && count == 0 && c == ',') { - res.push(content) - content = '' - continue + res.push(content); + content = ''; + continue; } - content += c + content += c; } - if (content.length > 0) res.push(content) + if (content.length > 0) res.push(content); - var newRes = {} + var newRes = {}; for (var j = 0, lenJ = res.length; j < lenJ; ++j) { if ((m = res[j].match(regex['key_value']))) { - newRes[m[1]] = processValue(m[2]) + newRes[m[1]] = processValue(m[2]); } } - return newRes - } else return val + return newRes; + } else return val; } function processFoldedBlock(block) { - var lines = block.lines - var children = block.children - var str = lines.join(' ') - var chunks = [str] + var lines = block.lines; + var children = block.children; + var str = lines.join(' '); + var chunks = [str]; for (var i = 0, len = children.length; i < len; ++i) { - chunks.push(processFoldedBlock(children[i])) + chunks.push(processFoldedBlock(children[i])); } - return chunks.join('\n') + return chunks.join('\n'); } function processLiteralBlock(block) { - var lines = block.lines - var children = block.children - var str = lines.join('\n') + var lines = block.lines; + var children = block.children; + var str = lines.join('\n'); for (var i = 0, len = children.length; i < len; ++i) { - str += processLiteralBlock(children[i]) + str += processLiteralBlock(children[i]); } - return str + return str; } function processBlock(blocks) { - var m = null - var res = {} - var lines = null - var children = null - var currentObj = null + var m = null; + var res = {}; + var lines = null; + var children = null; + var currentObj = null; - var level = -1 + var level = -1; - var processedBlocks = [] + var processedBlocks = []; - var isMap = true + var isMap = true; for (var j = 0, lenJ = blocks.length; j < lenJ; ++j) { - if (level != -1 && level != blocks[j].level) continue + if (level != -1 && level != blocks[j].level) continue; - processedBlocks.push(j) + processedBlocks.push(j); - level = blocks[j].level - lines = blocks[j].lines - children = blocks[j].children - currentObj = null + level = blocks[j].level; + lines = blocks[j].lines; + children = blocks[j].children; + currentObj = null; for (var i = 0, len = lines.length; i < len; ++i) { - var line = lines[i] + var line = lines[i]; if ((m = line.match(regex['key']))) { - var key = m[1] + var key = m[1]; if (key[0] == '-') { - key = key.replace(regex['item'], '') + key = key.replace(regex['item'], ''); if (isMap) { - isMap = false + isMap = false; if (typeof res.length === 'undefined') { - res = [] + res = []; } } - if (currentObj != null) res.push(currentObj) - currentObj = {} - isMap = true + if (currentObj != null) res.push(currentObj); + currentObj = {}; + isMap = true; } if (typeof m[2] != 'undefined') { - var value = m[2].replace(regex['trim'], '') + var value = m[2].replace(regex['trim'], ''); if (value[0] == '&') { - var nb = processBlock(children) - if (currentObj != null) currentObj[key] = nb - else res[key] = nb - reference_blocks[value.substr(1)] = nb + var nb = processBlock(children); + if (currentObj != null) currentObj[key] = nb; + else res[key] = nb; + reference_blocks[value.substr(1)] = nb; } else if (value[0] == '|') { if (currentObj != null) - currentObj[key] = processLiteralBlock(children.shift()) - else res[key] = processLiteralBlock(children.shift()) + currentObj[key] = processLiteralBlock(children.shift()); + else res[key] = processLiteralBlock(children.shift()); } else if (value[0] == '*') { - var v = value.substr(1) - var no = {} + var v = value.substr(1); + var no = {}; if (typeof reference_blocks[v] == 'undefined') { - errors.push("Reference '" + v + "' not found!") + errors.push("Reference '" + v + "' not found!"); } else { for (var k in reference_blocks[v]) { - no[k] = reference_blocks[v][k] + no[k] = reference_blocks[v][k]; } - if (currentObj != null) currentObj[key] = no - else res[key] = no + if (currentObj != null) currentObj[key] = no; + else res[key] = no; } } else if (value[0] == '>') { if (currentObj != null) - currentObj[key] = processFoldedBlock(children.shift()) - else res[key] = processFoldedBlock(children.shift()) + currentObj[key] = processFoldedBlock(children.shift()); + else res[key] = processFoldedBlock(children.shift()); } else { - if (currentObj != null) currentObj[key] = processValue(value) - else res[key] = processValue(value) + if (currentObj != null) currentObj[key] = processValue(value); + else res[key] = processValue(value); } } else { - if (currentObj != null) currentObj[key] = processBlock(children) - else res[key] = processBlock(children) + if (currentObj != null) currentObj[key] = processBlock(children); + else res[key] = processBlock(children); } } else if (line.match(/^-\s*$/)) { if (isMap) { - isMap = false + isMap = false; if (typeof res.length === 'undefined') { - res = [] + res = []; } } - if (currentObj != null) res.push(currentObj) - currentObj = {} - isMap = true - continue + if (currentObj != null) res.push(currentObj); + currentObj = {}; + isMap = true; + continue; } else if ((m = line.match(/^-\s*(.*)/))) { - if (currentObj != null) currentObj.push(processValue(m[1])) + if (currentObj != null) currentObj.push(processValue(m[1])); else { if (isMap) { - isMap = false + isMap = false; if (typeof res.length === 'undefined') { - res = [] + res = []; } } - res.push(processValue(m[1])) + res.push(processValue(m[1])); } - continue + continue; } } if (currentObj != null) { if (isMap) { - isMap = false + isMap = false; if (typeof res.length === 'undefined') { - res = [] + res = []; } } - res.push(currentObj) + res.push(currentObj); } } for (var j = processedBlocks.length - 1; j >= 0; --j) { - blocks.splice.call(blocks, processedBlocks[j], 1) + blocks.splice.call(blocks, processedBlocks[j], 1); } - return res + return res; } function semanticAnalysis(blocks) { - var res = processBlock(blocks.children) - return res + var res = processBlock(blocks.children); + return res; } function preProcess(src) { - var m - var lines = src.split('\n') + var m; + var lines = src.split('\n'); - var r = regex['comment'] + var r = regex['comment']; for (var i in lines) { if ((m = lines[i].match(r))) { @@ -443,24 +445,24 @@ function preProcess(src) { lines[i] = ""; */ if (typeof m[3] !== 'undefined') { - lines[i] = m[0].substr(0, m[0].length - m[3].length) + lines[i] = m[0].substr(0, m[0].length - m[3].length); } } } - return lines.join('\n') + return lines.join('\n'); } function load(str) { - errors = [] - reference_blocks = [] - processing_time = new Date().getTime() - var pre = preProcess(str) - var doc = parser(pre) - var res = semanticAnalysis(doc) - processing_time = new Date().getTime() - processing_time + errors = []; + reference_blocks = []; + processing_time = new Date().getTime(); + var pre = preProcess(str); + var doc = parser(pre); + var res = semanticAnalysis(doc); + processing_time = new Date().getTime() - processing_time; - return res + return res; } -export default load +export default load; diff --git a/src/plugins/ga.js b/src/plugins/ga.js index 2a6474ac..37167a4d 100644 --- a/src/plugins/ga.js +++ b/src/plugins/ga.js @@ -11,7 +11,7 @@ function init(id) { appendScript(); window.ga = window.ga || - function() { + function () { (window.ga.q = window.ga.q || []).push(arguments); }; @@ -28,7 +28,7 @@ function collect() { window.ga('send', 'pageview'); } -const install = function(hook) { +const install = function (hook) { if (!$docsify.ga) { console.error('[Docsify] ga is required.'); return; diff --git a/src/plugins/matomo.js b/src/plugins/matomo.js index 2074be76..48abb5e5 100644 --- a/src/plugins/matomo.js +++ b/src/plugins/matomo.js @@ -9,7 +9,7 @@ function init(options) { window._paq = window._paq || []; window._paq.push(['trackPageView']); window._paq.push(['enableLinkTracking']); - setTimeout(function() { + setTimeout(function () { appendScript(options); window._paq.push(['setTrackerUrl', options.host + '/matomo.php']); window._paq.push(['setSiteId', String(options.id)]); @@ -26,7 +26,7 @@ function collect() { window._paq.push(['trackPageView']); } -const install = function(hook) { +const install = function (hook) { if (!$docsify.matomo) { // eslint-disable-next-line no-console console.error('[Docsify] matomo is required.'); diff --git a/src/plugins/search/index.js b/src/plugins/search/index.js index e97c3b02..c3bdab96 100644 --- a/src/plugins/search/index.js +++ b/src/plugins/search/index.js @@ -13,7 +13,7 @@ const CONFIG = { pathNamespaces: undefined, }; -const install = function(hook, vm) { +const install = function (hook, vm) { const { util } = Docsify; const opts = vm.config.search || CONFIG; diff --git a/src/plugins/search/search.js b/src/plugins/search/search.js index 5c7f38bc..12447fa1 100644 --- a/src/plugins/search/search.js +++ b/src/plugins/search/search.js @@ -58,7 +58,7 @@ function getTableData(token) { if (!token.text && token.type === 'table') { token.cells.unshift(token.header); token.text = token.cells - .map(function(rows) { + .map(function (rows) { return rows.join(' | '); }) .join(' |\n '); diff --git a/test/.eslintrc.js b/test/.eslintrc.js deleted file mode 100644 index e273ac7f..00000000 --- a/test/.eslintrc.js +++ /dev/null @@ -1,12 +0,0 @@ -const jestConfig = require('../jest.config.js'); - -module.exports = { - env: { - 'jest/globals': true, - }, - extends: ['plugin:jest/recommended', 'plugin:jest/style'], - globals: { - ...jestConfig.globals, - }, - plugins: ['jest'], -}; diff --git a/test/config/jest-playwright.setup-tests.js b/test/config/jest-playwright.setup-tests.js index d6cba628..a8b01bf4 100644 --- a/test/config/jest-playwright.setup-tests.js +++ b/test/config/jest-playwright.setup-tests.js @@ -1,4 +1,4 @@ -/* global browserName page */ +/* global browserName page jestPlaywright */ const { configureToMatchImageSnapshot } = require('jest-image-snapshot'); // Lifecycle Hooks @@ -41,7 +41,7 @@ beforeAll(async () => { }); beforeEach(async () => { - await global.jestPlaywright.resetPage(); + await jestPlaywright.resetPage(); // Goto URL () // https://playwright.dev/#path=docs%2Fapi.md&q=pagegotourl-options diff --git a/test/config/jest.setup-tests.js b/test/config/jest.setup-tests.js index 2d29eb85..32e64154 100644 --- a/test/config/jest.setup-tests.js +++ b/test/config/jest.setup-tests.js @@ -28,14 +28,14 @@ beforeEach(async () => { 'google_tag_data', 'marked', 'Prism', - ].forEach(prop => { - if (global[prop]) { - delete global[prop]; + ].forEach((prop) => { + if (globalThis[prop]) { + delete globalThis[prop]; } }); // Remove attributes - [...rootElm.attributes].forEach(attr => rootElm.removeAttribute(attr.name)); + [...rootElm.attributes].forEach((attr) => rootElm.removeAttribute(attr.name)); // Restore base elements rootElm.innerHTML = ''; diff --git a/test/config/jest.setup.cjs b/test/config/jest.setup.cjs new file mode 100644 index 00000000..7a78dd43 --- /dev/null +++ b/test/config/jest.setup.cjs @@ -0,0 +1,9 @@ +// This has to be a CommonJS file because Jest currently imports it using +// `require()` instead of `import` (to be continued)... + +module.exports = async () => { + // ...(continued) but we can use import in here to transition back into ESM land. + const server = (await import('./server')).default; + + await server.startAsync(); +}; diff --git a/test/config/jest.setup.js b/test/config/jest.setup.js deleted file mode 100644 index 42f92218..00000000 --- a/test/config/jest.setup.js +++ /dev/null @@ -1,5 +0,0 @@ -const server = require('./server.js'); - -module.exports = async () => { - await server.startAsync(); -}; diff --git a/test/config/jest.teardown.cjs b/test/config/jest.teardown.cjs new file mode 100644 index 00000000..d1d740a0 --- /dev/null +++ b/test/config/jest.teardown.cjs @@ -0,0 +1,4 @@ +module.exports = async () => { + const server = (await import('./server')).default; + server.stop(); +}; diff --git a/test/config/jest.teardown.js b/test/config/jest.teardown.js deleted file mode 100644 index 647b2cea..00000000 --- a/test/config/jest.teardown.js +++ /dev/null @@ -1,5 +0,0 @@ -const server = require('./server.js'); - -module.exports = async () => { - server.stop(); -}; diff --git a/test/config/server.js b/test/config/server.js index d027cdb0..5027217d 100644 --- a/test/config/server.js +++ b/test/config/server.js @@ -1,7 +1,10 @@ -const browserSync = require('browser-sync').create(); -const path = require('path'); +import path from 'path'; +import browserSyncModule from 'browser-sync'; +import esMain from 'es-main'; +const browserSync = browserSyncModule.create(); const hasStartArg = process.argv.includes('--start'); +const dirname = path.dirname(import.meta.url.replace('file://', '')); const serverConfig = { host: '127.0.0.1', @@ -14,7 +17,7 @@ function startServer(options = {}, cb = Function.prototype) { middleware: [ { route: '/_blank.html', - handle: function(req, res, next) { + handle: function (req, res, next) { res.setHeader('Content-Type', 'text/html'); res.end(''); next(); @@ -31,18 +34,18 @@ function startServer(options = {}, cb = Function.prototype) { }, ], server: { - baseDir: path.resolve(__dirname, '../'), + baseDir: path.resolve(dirname, '../'), routes: { - '/docs': path.resolve(__dirname, '../../docs'), + '/docs': path.resolve(dirname, '../../docs'), '/docs/changelog.md': './CHANGELOG.md', - '/lib': path.resolve(__dirname, '../../lib'), - '/node_modules': path.resolve(__dirname, '../../node_modules'), + '/lib': path.resolve(dirname, '../../lib'), + '/node_modules': path.resolve(dirname, '../../node_modules'), }, }, snippetOptions: { rule: { match: /<\/body>/i, - fn: function(snippet, match) { + fn: function (snippet, match) { // Override changelog alias to load local changelog (see routes) const injectJS = `