diff --git a/package-lock.json b/package-lock.json index 76acded6..f8978423 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,12 @@ "typescript": "^4.5.5" } }, + "node_modules/@alex_neo/jest-expect-message": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@alex_neo/jest-expect-message/-/jest-expect-message-1.0.5.tgz", + "integrity": "sha512-1eBykZCd0pPGl5qKtV6Z5ARA6yuhXzHsVN2h5GH5/H6svYa37Jr7vMio5OFpiw1LBHtscrZs7amSkZkcwm0cvQ==", + "dev": true + }, "node_modules/@ampproject/remapping": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", @@ -1605,10 +1611,6 @@ "resolved": "packages/typedoc-pluginutils", "link": true }, - "node_modules/@knodes/typedoc-theme": { - "resolved": "packages/typedoc-theme", - "link": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7239,11 +7241,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -7260,14 +7257,6 @@ "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" }, - "node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -8134,6 +8123,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, "engines": { "node": ">=6" } @@ -8755,45 +8745,6 @@ "source-map": "^0.6.0" } }, - "node_modules/source-map-sync": { - "version": "0.8.0-beta.2", - "resolved": "https://registry.npmjs.org/source-map-sync/-/source-map-sync-0.8.0-beta.2.tgz", - "integrity": "sha512-Q4ejvN6wENaQdYVcq4lMm/vHN9TiSoc/6hQbUhP2DogZ0kYIEYaQlYLbgJ8hEF0eFpQDeEkQAsMiARscl1Ur/Q==", - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-sync/node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/source-map-sync/node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "node_modules/source-map-sync/node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, "node_modules/spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", @@ -10880,12 +10831,11 @@ "license": "MIT", "dependencies": { "lodash": "^4.17.0", - "magic-string": "^0.25.7", "pkg-up": "^3.1.0", - "semver": "^7.3.5", - "source-map-sync": "^0.8.0-beta.2" + "semver": "^7.3.5" }, "devDependencies": { + "@alex_neo/jest-expect-message": "^1.0.5", "@knodes/eslint-config": "^1.6.3", "@testing-library/jest-dom": "^5.16.2", "@types/jest": "^27.4.1", @@ -11172,6 +11122,7 @@ "packages/typedoc-theme": { "name": "@knodes/typedoc-theme", "version": "0.22.0", + "extraneous": true, "license": "MIT", "dependencies": { "@knodes/typedoc-pluginutils": "*" @@ -11219,245 +11170,15 @@ "optional": true } } - }, - "packages/typedoc-theme/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "packages/typedoc-theme/node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "packages/typedoc-theme/node_modules/data-urls": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.1.tgz", - "integrity": "sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw==", - "dev": true, - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^10.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "packages/typedoc-theme/node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "packages/typedoc-theme/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/typedoc-theme/node_modules/jsdom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", - "integrity": "sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==", - "dev": true, - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.5.0", - "acorn-globals": "^6.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.1", - "decimal.js": "^10.3.1", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^3.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^10.0.0", - "ws": "^8.2.3", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "packages/typedoc-theme/node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/w3c-xmlserializer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", - "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", - "dev": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/whatwg-url": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", - "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", - "dev": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/typedoc-theme/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "packages/typedoc-theme/node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "engines": { - "node": ">=12" - } } }, "dependencies": { + "@alex_neo/jest-expect-message": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@alex_neo/jest-expect-message/-/jest-expect-message-1.0.5.tgz", + "integrity": "sha512-1eBykZCd0pPGl5qKtV6Z5ARA6yuhXzHsVN2h5GH5/H6svYa37Jr7vMio5OFpiw1LBHtscrZs7amSkZkcwm0cvQ==", + "dev": true + }, "@ampproject/remapping": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", @@ -13278,6 +12999,7 @@ "@knodes/typedoc-pluginutils": { "version": "file:packages/typedoc-pluginutils", "requires": { + "@alex_neo/jest-expect-message": "^1.0.5", "@knodes/eslint-config": "^1.6.3", "@testing-library/jest-dom": "^5.16.2", "@types/jest": "^27.4.1", @@ -13302,11 +13024,9 @@ "jest-junit": "^13.0.0", "jsdom": "^19.0.0", "lodash": "^4.17.0", - "magic-string": "^0.25.7", "pkg-up": "^3.1.0", "rimraf": "^3.0.2", "semver": "^7.3.5", - "source-map-sync": "^0.8.0-beta.2", "tmp": "^0.2.1", "ts-jest": "^27.1.3", "type-fest": "^2.12.0", @@ -13491,210 +13211,6 @@ } } }, - "@knodes/typedoc-theme": { - "version": "file:packages/typedoc-theme", - "requires": { - "@knodes/eslint-config": "^1.6.3", - "@knodes/typedoc-pluginutils": "*", - "@testing-library/jest-dom": "^5.16.2", - "@types/jest": "^27.4.1", - "@types/jsdom": "^16.2.14", - "@types/lodash": "^4.14.178", - "@types/marked": "^4.0.2", - "@types/mock-fs": "^4.13.1", - "@types/node": "^17.0.21", - "@types/react": "^17.0.39", - "@typescript-eslint/eslint-plugin": "^5.12.1", - "@typescript-eslint/parser": "^5.12.1", - "conventional-changelog-cli": "^2.2.2", - "eslint": "^8.9.0", - "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jsdoc": "^37.9.4", - "eslint-plugin-prefer-arrow": "^1.2.3", - "eslint-plugin-sort-export-all": "^1.2.1", - "jest": "^27.5.1", - "jest-extended": "^2.0.0", - "jest-junit": "^13.0.0", - "jsdom": "^19.0.0", - "marked": "^4.0.12", - "rimraf": "^3.0.2", - "ts-jest": "^27.1.3", - "typedoc": "^0.22.12", - "typescript": "^4.5.5" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "data-urls": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.1.tgz", - "integrity": "sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^10.0.0" - } - }, - "domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "requires": { - "webidl-conversions": "^7.0.0" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "requires": { - "whatwg-encoding": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "jsdom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", - "integrity": "sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.5.0", - "acorn-globals": "^6.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.1", - "decimal.js": "^10.3.1", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^3.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^10.0.0", - "ws": "^8.2.3", - "xml-name-validator": "^4.0.0" - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "w3c-xmlserializer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", - "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", - "dev": true, - "requires": { - "xml-name-validator": "^4.0.0" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "requires": { - "iconv-lite": "0.6.3" - } - }, - "whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true - }, - "whatwg-url": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", - "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - }, - "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true - } - } - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -17921,11 +17437,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -17939,14 +17450,6 @@ "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -18588,7 +18091,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "q": { "version": "1.5.1", @@ -19057,44 +18561,6 @@ "source-map": "^0.6.0" } }, - "source-map-sync": { - "version": "0.8.0-beta.2", - "resolved": "https://registry.npmjs.org/source-map-sync/-/source-map-sync-0.8.0-beta.2.tgz", - "integrity": "sha512-Q4ejvN6wENaQdYVcq4lMm/vHN9TiSoc/6hQbUhP2DogZ0kYIEYaQlYLbgJ8hEF0eFpQDeEkQAsMiARscl1Ur/Q==", - "requires": { - "whatwg-url": "^7.0.0" - }, - "dependencies": { - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "requires": { - "punycode": "^2.1.0" - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - } - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, "spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", diff --git a/packages/typedoc-pluginutils/jest.config.js b/packages/typedoc-pluginutils/jest.config.js index 351dbe41..60b5353b 100644 --- a/packages/typedoc-pluginutils/jest.config.js +++ b/packages/typedoc-pluginutils/jest.config.js @@ -5,7 +5,10 @@ const base = require( '../../jest.config.base' ); module.exports = { ...base, projects: [ - base.projects[0], + { + ...base.projects[0], + setupFilesAfterEnv: [ ...base.projects[1].setupFilesAfterEnv, '@alex_neo/jest-expect-message' ], + }, { ...base.projects[1], setupFilesAfterEnv: [ ...base.projects[1].setupFilesAfterEnv, '@testing-library/jest-dom' ], diff --git a/packages/typedoc-pluginutils/package.json b/packages/typedoc-pluginutils/package.json index 889455cf..ba98c501 100644 --- a/packages/typedoc-pluginutils/package.json +++ b/packages/typedoc-pluginutils/package.json @@ -37,16 +37,15 @@ }, "dependencies": { "lodash": "^4.17.0", - "magic-string": "^0.25.7", "pkg-up": "^3.1.0", - "semver": "^7.3.5", - "source-map-sync": "^0.8.0-beta.2" + "semver": "^7.3.5" }, "peerDependencies": { "lodash": "^4.17.0", "typedoc": "^0.22.0" }, "devDependencies": { + "@alex_neo/jest-expect-message": "^1.0.5", "@knodes/eslint-config": "^1.6.3", "@testing-library/jest-dom": "^5.16.2", "@types/jest": "^27.4.1", diff --git a/packages/typedoc-pluginutils/src/markdown-replacer.spec.ts b/packages/typedoc-pluginutils/src/markdown-replacer.spec.ts new file mode 100644 index 00000000..de2e9e8f --- /dev/null +++ b/packages/typedoc-pluginutils/src/markdown-replacer.spec.ts @@ -0,0 +1,149 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +import assert from 'assert'; + +import { relative, resolve } from 'path'; + +import { escapeRegExp } from 'lodash'; + +import { Application, DeclarationReflection, MarkdownEvent, ReflectionKind, SourceFile } from 'typedoc'; + +jest.mock( './base-plugin' ); +const { ABasePlugin } = require( './base-plugin' ) as jest.Mocked; +jest.mock( './current-page-memo' ); +const { CurrentPageMemo } = require( './current-page-memo' ) as jest.Mocked; + +import { MarkdownReplacer } from './markdown-replacer'; + +class TestPlugin extends ABasePlugin { + public override application: jest.MockedObjectDeep; + public constructor(){ + super( {} as any, __filename ); + this.application = { + renderer: { + on: jest.fn(), + }, + converter: { + on: jest.fn(), + }, + } as any; + const pseudoLogger = { + makeChildLogger: jest.fn().mockImplementation( () => pseudoLogger ), + error: jest.fn().mockImplementation( assert.fail ), + warn: jest.fn().mockImplementation( assert.fail ), + } as any; + ( this as any ).logger = pseudoLogger; + } + // eslint-disable-next-line @typescript-eslint/no-empty-function + public initialize(): void {} + public relativeToRoot( path: string ){ + return relative( process.cwd(), path ); + } +} +const mockCurrentPage = ( name: string, source: string, line: number, character: number ) => { + const ref = new DeclarationReflection( name, ReflectionKind.Class ); + ref.sources = [ + { fileName: source, file: new SourceFile( source ), character, line }, + ]; + Object.defineProperty( CurrentPageMemo.prototype, 'currentReflection', { writable: true, value: ref } ); + Object.defineProperty( CurrentPageMemo.prototype, 'hasCurrent', { writable: true, value: true } ); +}; +afterEach( () => { + Object.defineProperty( CurrentPageMemo.prototype, 'currentReflection', { writable: true, value: undefined } ); + Object.defineProperty( CurrentPageMemo.prototype, 'hasCurrent', { writable: true, value: false } ); +} ); +describe( MarkdownReplacer.name, () => { + describe( 'Once', () => { + let plugin: TestPlugin; + let replacer: MarkdownReplacer; + beforeEach( () => { + plugin = new TestPlugin(); + replacer = new MarkdownReplacer( plugin ); + } ); + describe( 'Source map', () => { + it.each( [ + [ 'hello ## world', [ 'hello.ts:1:7' ]], + [ 'hello \n## world', [ 'hello.ts:2:1' ]], + [ '\nhello ## world', [ 'hello.ts:2:7' ]], + [ 'hello ## world##\nHow are you doing ?\n##', [ 'hello.ts:1:7', 'hello.ts:1:15', 'hello.ts:3:1' ]], + ] )( 'should match %j with sourcemaps %j', ( source, expectedMaps ) => { + mockCurrentPage( 'Test', resolve( 'hello.ts' ), 1, 1 ); + const fn = jest.fn().mockReturnValue( '#' ); + replacer.bindReplace( /##/g, fn, 'Replacer' ); + const evt = new MarkdownEvent( MarkdownEvent.PARSE, source, source ); + plugin.application.renderer.on.mock.calls[0][1]( evt ); + expectedMaps.forEach( ( m, i ) => { + expect( fn.mock.calls[i][1]() ).toContain( `${m} ` ); + expect( fn.mock.calls[i][1]() ).toContain( 'Replacer)' ); + } ); + } ); + } ); + } ); + describe( 'Multi', () => { + let plugin: TestPlugin; + let replacer: MarkdownReplacer; + beforeEach( () => { + plugin = new TestPlugin(); + replacer = new MarkdownReplacer( plugin ); + } ); + describe( 'Source map', () => { + it.each( [ + [ 'hello ## world', 'Simple', [ + { match: /##/g, label: '##', maps: [ { map: 'hello.ts:1:7', ctxs: [ '##' ] } ], replacer: jest.fn().mockReturnValueOnce( '@' ) }, + ]], + [ 'hello ## world', 'Overlapping same size', [ + { match: /##/g, label: '##', maps: [ { map: 'hello.ts:1:7', ctxs: [ '##' ] } ], replacer: jest.fn().mockReturnValueOnce( '{}' ) }, + { match: /\{\}/g, label: '{}', maps: [ { map: 'hello.ts:1:7', ctxs: [ '##', '{}' ] } ], replacer: jest.fn().mockReturnValueOnce( '=' ) }, + ]], + [ 'hello ## world', 'Overlapping diff size', [ + { match: /##/g, label: '##', maps: [ { map: 'hello.ts:1:7', ctxs: [ '##' ] } ], replacer: jest.fn().mockReturnValueOnce( '@@@{}' ) }, + { match: /\{\}/g, label: '{}', maps: [ { map: 'hello.ts:1:7', ctxs: [ '##', '{}' ] } ], replacer: jest.fn().mockReturnValueOnce( '=' ) }, + ]], + [ 'hello ## world {}', '1=>2 + 2', [ + { match: /##/g, label: '##', maps: [ { map: 'hello.ts:1:7', ctxs: [ '##' ] } ], replacer: jest.fn().mockReturnValueOnce( '{}' ) }, + { match: /\{\}/g, label: '{}', maps: [ + { map: 'hello.ts:1:7', ctxs: [ '##', '{}' ] }, + { map: 'hello.ts:1:16', ctxs: [ '{}' ] }, + ], replacer: jest.fn().mockReturnValueOnce( '=' ) }, + ]], + [ 'hello \n{}\n## world ', '2 + 1=>2', [ + { match: /##/g, label: '##', maps: [ { map: 'hello.ts:3:1', ctxs: [ '##' ] } ], replacer: jest.fn().mockReturnValueOnce( '{}' ) }, + { match: /\{\}/g, label: '{}', maps: [ + { map: 'hello.ts:2:1', ctxs: [ '{}' ] }, + { map: 'hello.ts:3:1', ctxs: [ '##', '{}' ] }, + ], replacer: jest.fn().mockReturnValueOnce( '=' ) }, + ]], + [ 'hello\n## world\n@@@{==}', '1=>2 + 2', [ + { match: /##/g, label: '##', maps: [ { map: 'hello.ts:2:1', ctxs: [ '##' ] } ], replacer: jest.fn().mockReturnValue( '@@@{==}' ) }, + { match: /\{==\}/g, label: '{==}', maps: [ + { map: 'hello.ts:2:1', ctxs: [ '##', '{==}' ] }, + { map: 'hello.ts:3:4', ctxs: [ '{==}' ] }, + ], replacer: jest.fn().mockReturnValue( '=' ) }, + ]], + [ 'hello\n## world\n{==}\n##', '1=>2 + 2 + 1=>2', [ + { match: /##/g, label: '##', maps: [ + { map: 'hello.ts:2:1', ctxs: [ '##' ] }, + { map: 'hello.ts:4:1', ctxs: [ '##' ] }, + ], replacer: jest.fn().mockReturnValue( '@@@{==}' ) }, + { match: /\{==\}/g, label: '{==}', maps: [ + { map: 'hello.ts:2:1', ctxs: [ '##', '{==}' ] }, + { map: 'hello.ts:3:1', ctxs: [ '{==}' ] }, + { map: 'hello.ts:4:1', ctxs: [ '##', '{==}' ] }, + ], replacer: jest.fn().mockReturnValue( '=' ) }, + ]], + ] )( 'should match %j with sourcemaps %# (%s)', ( source, _label, binds ) => { + mockCurrentPage( 'Test', resolve( 'hello.ts' ), 1, 1 ); + binds.forEach( b => replacer.bindReplace( b.match, b.replacer, b.label ) ); + const evt = new MarkdownEvent( MarkdownEvent.PARSE, source, source ); + binds.forEach( ( _b, i ) => plugin.application.renderer.on.mock.calls[i][1]( evt ) ); + binds.forEach( b => { + expect( b.replacer, `Replacer ${b.label}` ).toHaveBeenCalledTimes( b.maps.length ); + b.maps.forEach( ( m, j ) => { + const mapStr = b.replacer.mock.calls[j][1](); + expect( mapStr, `Replacer ${b.label}, call ${j}` ) + .toMatch( new RegExp( `^${escapeRegExp( m.map )} \\(.*? of ${m.ctxs.map( escapeRegExp ).join( ' . ' )}\\)` ) ); + } ); + } ); + } ); + } ); + } ); +} ); diff --git a/packages/typedoc-pluginutils/src/markdown-replacer.ts b/packages/typedoc-pluginutils/src/markdown-replacer.ts index ab30acb7..40935ba5 100644 --- a/packages/typedoc-pluginutils/src/markdown-replacer.ts +++ b/packages/typedoc-pluginutils/src/markdown-replacer.ts @@ -1,13 +1,31 @@ import assert from 'assert'; -import { isNil, isNumber, isString, once } from 'lodash'; -import MagicString from 'magic-string'; +import { isNil, isNumber, isString, last, once } from 'lodash'; import { Context, Converter, JSX, MarkdownEvent, SourceFile } from 'typedoc'; import { ABasePlugin } from './base-plugin'; import { CurrentPageMemo } from './current-page-memo'; import { reflectionSourceUtils, textUtils } from './utils'; +interface ISourceEdit { + from: number; + to: number; + source: string; + replacement: string; +} +interface ISourceMapContainer { + editions: ISourceEdit[]; + getEditionContext: ( position: number ) => ( { + line: number; + column: number; + expansions: ISourceMapContainer[]; + index: number; + source: string; + } ); + label: string; + plugin: ABasePlugin; + regex: RegExp; +} const spitArgs = ( ...args: Parameters[1]> ) => { const indexIdx = args.findIndex( isNumber ); if( isNil( indexIdx ) ){ @@ -53,11 +71,20 @@ export class MarkdownReplacer { ]; } } ); - private static readonly _eventsOffsets = new WeakMap(); + private static readonly _mapContainers = new WeakMap(); private readonly _logger = this.plugin.logger.makeChildLogger( 'MarkdownReplacer' ); private readonly _currentPageMemo = new CurrentPageMemo( this.plugin ); + /** + * Get the list of source map containers for the given event. + * + * @param event - The event to get source maps for. + * @returns the source map list. + */ + private static _getEventMapContainers( event: MarkdownEvent ): ISourceMapContainer[] { + return this._mapContainers.get( event ) ?? []; + } public constructor( protected readonly plugin: ABasePlugin, @@ -70,10 +97,11 @@ export class MarkdownReplacer { * * @param regex - The regex to match. * @param callback - The callback to execute with fullMatch, captures, & a source hint. + * @param label - The replacer name. */ - public bindReplace( regex: RegExp, callback: MarkdownReplacer.ReplaceCallback ) { + public bindReplace( regex: RegExp, callback: MarkdownReplacer.ReplaceCallback, label = `${this.plugin.name}: Unnamed markdown replace` ) { assert( regex.flags.includes( 'g' ) ); - this.plugin.application.renderer.on( MarkdownEvent.PARSE, this._processMarkdown.bind( this, regex, callback ), undefined, 100 ); + this.plugin.application.renderer.on( MarkdownEvent.PARSE, this._processMarkdown.bind( this, regex, callback, label ), undefined, 100 ); } @@ -82,42 +110,76 @@ export class MarkdownReplacer { * * @param regex - The regex to match. * @param callback - The callback to execute with fullMatch, captures, & a source hint. + * @param label - The replacer name. * @param event - The event to modify. */ private _processMarkdown( regex: RegExp, callback: MarkdownReplacer.ReplaceCallback, + label: string, event: MarkdownEvent, ) { - // TODO: Proper sourcemap support - let magic: MagicString | undefined = new MagicString( event.parsedText ); - event.parsedText = event.parsedText.replace( + const mapContainers = MarkdownReplacer._getEventMapContainers( event ); + const sourceFile = this._currentPageMemo.hasCurrent ? reflectionSourceUtils.getReflectionSourceFileName( this._currentPageMemo.currentReflection ) : undefined; + const relativeSource = sourceFile ? this.plugin.relativeToRoot( sourceFile ) : undefined; + const originalText = event.parsedText; + const edits: ISourceEdit[] = []; + const getCtxInParent = last( mapContainers )?.getEditionContext ?? + ( pos => ( { ...textUtils.getCoordinates( originalText, pos ), source: originalText, index: pos, expansions: [] } ) ); + event.parsedText = originalText.replace( regex, ( ...args ) => { - const { captures, fullMatch, index, source } = spitArgs( ...args ); + const { captures, fullMatch, index } = spitArgs( ...args ); const replacement = callback( { fullMatch, captures }, () => { - const sourceFile = reflectionSourceUtils.getReflectionSourceFileName( this._currentPageMemo.currentReflection ); - if( !sourceFile ){ + if( !relativeSource ){ return 'UNKNOWN SOURCE'; } - const pos = textUtils.getCoordinates( source, index ); - const { line, column } = pos; + const { line, column, expansions } = getCtxInParent( index ); const posStr = line && column ? `:${line}:${column}` : ''; - return this.plugin.relativeToRoot( sourceFile ) + posStr; + const expansionContext = ` (in expansion of ${expansions.concat( [ thisContainer ] ).map( e => e.label ).join( ' ⇒ ' )})`; + return relativeSource + posStr + expansionContext; } ); if( isNil( replacement ) ){ return fullMatch; } const replacementStr = typeof replacement === 'string' ? replacement : JSX.renderElement( replacement ); - try { - magic = magic?.overwrite( index, index + fullMatch.length, replacementStr ); - } catch( _e: any ){ - magic = undefined; - } + edits.push( { from: index, to: index + fullMatch.length, replacement: replacementStr, source: fullMatch } ); return replacementStr; } ); + const thisContainer: ISourceMapContainer = { + regex, + editions: edits, + label, + plugin: this.plugin, + getEditionContext: ( pos: number ) => { + const { offsetedPos, didEdit } = edits.reduce( + ( acc, edit ) => { + const isAfterEdit = edit.from <= acc.offsetedPos; + if( !isAfterEdit ){ + return acc; + } + const _didEdit = edit.from + edit.replacement.length > acc.offsetedPos; + return { + offsetedPos: acc.offsetedPos + ( _didEdit ? + edit.from - acc.offsetedPos : + edit.source.length - edit.replacement.length ), + didEdit: _didEdit || acc.didEdit, + }; + }, + { offsetedPos: pos, didEdit: false } ); + const parentCtx = getCtxInParent( offsetedPos ); + if( didEdit ){ + parentCtx.expansions = [ ...parentCtx.expansions, thisContainer ]; + } + return parentCtx; + }, + }; + MarkdownReplacer._mapContainers.set( event, [ + ...mapContainers, + thisContainer, + ] ); } } export namespace MarkdownReplacer { diff --git a/packages/typedoc-pluginutils/types/test.d.ts b/packages/typedoc-pluginutils/types/test.d.ts index 412465e6..0c354a89 100644 --- a/packages/typedoc-pluginutils/types/test.d.ts +++ b/packages/typedoc-pluginutils/types/test.d.ts @@ -1 +1,10 @@ import './expect-type'; + +declare global { + namespace jest { + interface Expect { + // eslint-disable-next-line @typescript-eslint/prefer-function-type -- Declaration merging + ( actual: T, message?: string ): JestMatchers; + } + } +}