diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 259e0051..010314af 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -17,3 +17,5 @@ jobs: - uses: codespell-project/actions-codespell@94259cd8be02ad2903ba34a22d9c13de21a74461 # v2.0 with: ignore_words_list: crate,raison + exclude_file: .gitignore + skip: package-lock.json diff --git a/bin/.gitkeep b/bin/.gitkeep new file mode 100644 index 00000000..f935021a --- /dev/null +++ b/bin/.gitkeep @@ -0,0 +1 @@ +!.gitignore diff --git a/package-lock.json b/package-lock.json index c60a6c97..488f16ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,8 +4,23 @@ "requires": true, "packages": { "": { + "dependencies": { + "github-slugger": "^2.0.0", + "glob": "^10.4.3", + "remark": "^15.0.1", + "remark-gfm": "^4.0.0", + "unist-builder": "^4.0.0", + "unist-util-find-after": "^5.0.0", + "unist-util-position": "^5.0.0", + "unist-util-remove": "^4.0.0", + "unist-util-select": "^5.1.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.1", + "yaml": "^2.4.5" + }, "devDependencies": { "@eslint/js": "^9.6.0", + "@types/node": "^20.14.10", "eslint": "^9.6.0", "eslint-config-prettier": "^9.1.0", "globals": "^15.8.0", @@ -143,6 +158,102 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -178,6 +289,56 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "license": "MIT" + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -231,7 +392,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -240,7 +400,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -257,11 +416,26 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" }, "node_modules/brace-expansion": { "version": "1.1.11", @@ -294,6 +468,16 @@ "node": ">=6" } }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -310,6 +494,16 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", @@ -345,7 +539,6 @@ "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, "dependencies": { "color-name": "~1.1.4" }, @@ -356,8 +549,7 @@ "node_modules/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 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colorette": { "version": "2.0.20", @@ -384,7 +576,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -394,11 +585,26 @@ "node": ">= 8" } }, + "node_modules/css-selector-parser": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.0.5.tgz", + "integrity": "sha512-3itoDFbKUNx1eKmVpYMFyqKX04Ww9osZ+dLgrk6GEv6KMVeXUhUnp4I5X+evw+u3ZxVU6RFXSSRxlTeMh8bA+g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -411,12 +617,53 @@ } } }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", @@ -614,6 +861,12 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -700,6 +953,22 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/get-east-asian-width": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", @@ -724,6 +993,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/glob": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.3.tgz", + "integrity": "sha512-Q38SGlYRpVtDBPSWEylRyctn7uDeTp4NQERTLiCT1FqA9JXPYWqAVmQU6qh4r/zMM5ehxTcbaO8EjhWnvEhmyg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -736,6 +1034,30 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { "version": "15.8.0", "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", @@ -866,6 +1188,18 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -881,8 +1215,25 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.1.tgz", + "integrity": "sha512-U23pQPDnmYybVkYjObcuYMk43VRlMLLqLI+RdZy8s8WV8WsxO9SnqSroKaluuvcNOdCAlauKszDwd+umbot5Mg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } }, "node_modules/js-yaml": { "version": "4.1.0", @@ -1114,30 +1465,56 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, + "node_modules/lru-cache": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.1.tgz", + "integrity": "sha512-9/8QXrtbGeMB6LxwQd4x1tIMnsmUxMvIH/qWGsccz6bt9Uln3S+sgAaqfQNhbGA8ufzs2fHuP/yqapGgP9Hh2g==", + "license": "ISC", + "engines": { + "node": ">=18" + } + }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, - "engines": { - "node": ">=8.6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -1145,48 +1522,822 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", + "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" }, - "engines": { - "node": "*" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.0.tgz", + "integrity": "sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, "engines": { @@ -1196,6 +2347,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", @@ -1258,6 +2421,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -1283,11 +2452,26 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1365,6 +2549,71 @@ } ] }, + "node_modules/remark": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", + "integrity": "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -1463,7 +2712,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -1475,7 +2723,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -1484,7 +2731,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -1546,6 +2792,36 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -1577,7 +2853,19 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -1639,6 +2927,16 @@ "node": ">=8.0" } }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -1651,6 +2949,159 @@ "node": ">= 0.8.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-builder": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-4.0.0.tgz", + "integrity": "sha512-wmRFnH+BLpZnTKpc5L7O67Kac89s9HMrtELpnNaE6TAobq5DTZZs5YaTQfAZBA9bFPECx2uVAPO31c+GVug8mg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz", + "integrity": "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-select/-/unist-util-select-5.1.0.tgz", + "integrity": "sha512-4A5mfokSHG/rNQ4g7gSbdEs+H586xyd24sdJqF1IWamqrLHvYb+DH48fzxowyOhOfK7YSqX+XlCojAyuuyyT2A==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.1.0", + "nth-check": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -1660,11 +3111,39 @@ "punycode": "^2.1.0" } }, + "node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -1701,6 +3180,53 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -1741,10 +3267,10 @@ } }, "node_modules/yaml": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", - "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", - "dev": true, + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "license": "ISC", "bin": { "yaml": "bin.mjs" }, @@ -1763,6 +3289,16 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index 8f0f9d9a..6b10a4a7 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,26 @@ }, "devDependencies": { "@eslint/js": "^9.6.0", + "@types/node": "^20.14.10", "eslint": "^9.6.0", "eslint-config-prettier": "^9.1.0", "globals": "^15.8.0", "husky": "^9.0.11", "lint-staged": "^15.2.7", "prettier": "3.2.5" + }, + "dependencies": { + "github-slugger": "^2.0.0", + "glob": "^10.4.3", + "remark": "^15.0.1", + "remark-gfm": "^4.0.0", + "unist-builder": "^4.0.0", + "unist-util-find-after": "^5.0.0", + "unist-util-position": "^5.0.0", + "unist-util-remove": "^4.0.0", + "unist-util-select": "^5.1.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.1", + "yaml": "^2.4.5" } } diff --git a/src/constants.mjs b/src/constants.mjs new file mode 100644 index 00000000..34ef83c8 --- /dev/null +++ b/src/constants.mjs @@ -0,0 +1,330 @@ +'use strict'; + +// This is the base-path of API docs within the https://nodejs.org Website +export const DOC_WEB_BASE_PATH = '/docs/'; + +// This is the base URL of the MDN Web documentation +export const DOC_MDN_BASE_URL = 'https://developer.mozilla.org/en-US/docs/Web/'; + +// This is the base URL for the MDN JavaScript documentation +export const DOC_MDN_BASE_URL_JS = `${DOC_MDN_BASE_URL}JavaScript/`; + +// This is the base URL for the MDN JavaScript primitives documentation +export const DOC_MDN_BASE_URL_JS_PRIMITIVES = `${DOC_MDN_BASE_URL_JS}Data_structures`; + +// This is the base URL for the MDN JavaScript global objects documentation +export const DOC_MDN_BASE_URL_JS_GLOBALS = `${DOC_MDN_BASE_URL_JS}Reference/Global_Objects/`; + +// These are YAML keys from the Markdown YAML Metadata that should always be arrays +export const DOC_API_YAML_KEYS_ARRAYS = [ + 'added', + 'napiVersion', + 'deprecated', + 'removed', + 'introduced_in', +]; + +// These are YAML keys from the Markdown YAML metadata that should be +// removed and appended to the `update` key +export const DOC_API_YAML_KEYS_UPDATE = [ + 'added', + 'removed', + 'deprecated', + 'introduced_in', + 'napiVersion', +]; + +// These are string replacements specific to Node.js API docs for anchor IDs +export const DOC_API_SLUGS_REPLACEMENTS = [ + { from: /node.js/i, to: 'nodejs' }, // Replace Node.js + { from: /&/, to: '-and-' }, // Replace & + { from: /[/_,:;\\ ]/g, to: '-' }, // Replace /_,:;\. and whitespace + { from: /--+/g, to: '-' }, // Replace multiple hyphens with single + { from: /^-/, to: '' }, // Remove any leading hyphen + { from: /-$/, to: '' }, // Remove any trailing hyphen +]; + +// These are regular expressions used to determine if a given Markdown heading +// is a specific type of API Doc entry (e.g., Event, Class, Method, etc) +// and to extract the inner content of said Heading to be used as the API doc entry name +export const DOC_API_HEADING_TYPES = [ + { type: 'method', regex: /^`?([A-Z]\w+(?:\.[A-Z]\w+)*\.\w+)\([^)]*\)`?$/i }, + { type: 'event', regex: /^Event: +`?['"]?([^'"]+)['"]?`?$/i }, + { + type: 'class', + regex: + /^Class: +`?([A-Z]\w+(?:\.[A-Z]\w+)*(?: +extends +[A-Z]\w+(?:\.[A-Z]\w+)*)?)`?$/i, + }, + { + type: 'ctor', + regex: /^(?:Constructor: +)?`?new +([A-Z]\w+(?:\.[A-Z]\w+)*)\([^)]*\)`?$/i, + }, + { + type: 'classMethod', + regex: /^Static method: +`?([A-Z]\w+(?:\.[A-Z]\w+)*\.\w+)\([^)]*\)`?$/i, + }, + { + type: 'property', + regex: /^(?:Class property: +)?`?([A-Z]\w+(?:\.[A-Z]\w+)*\.\w+)`?$/i, + }, +]; + +// This is a mapping for types within the Markdown content and their respective +// JavaScript primitive types within the MDN JavaScript docs +// @see DOC_MDN_BASE_URL_JS_PRIMITIVES +export const DOC_TYPES_MAPPING_PRIMITIVES = { + boolean: 'Boolean', + integer: 'Number', // Not a primitive, used for clarification. + null: 'Null', + number: 'Number', + string: 'String', + symbol: 'Symbol', + undefined: 'Undefined', +}; + +// This is a mapping for types within the Markdown content and their respective +// JavaScript globals types within the MDN JavaScript docs +// @see DOC_MDN_BASE_URL_JS_GLOBALS +export const DOC_TYPES_MAPPING_GLOBALS = { + AggregateError: 'AggregateError', + Array: 'Array', + ArrayBuffer: 'ArrayBuffer', + DataView: 'DataView', + Date: 'Date', + Error: 'Error', + EvalError: 'EvalError', + Function: 'Function', + Map: 'Map', + Object: 'Object', + Promise: 'Promise', + RangeError: 'RangeError', + ReferenceError: 'ReferenceError', + RegExp: 'RegExp', + Set: 'Set', + SharedArrayBuffer: 'SharedArrayBuffer', + SyntaxError: 'SyntaxError', + TypeError: 'TypeError', + TypedArray: 'TypedArray', + URIError: 'URIError', + Uint8Array: 'Uint8Array', + bigint: 'BigInt', + 'WebAssembly.Instance': 'WebAssembly/Instance', +}; + +// This is a mapping for types within the Markdown content and their respective +// Node.js types within the Node.js API docs (refers to a different API doc page) +// @note These hashes are generated with the GitHub Slugger +export const DOC_TYPES_MAPPING_NODE_MODULES = { + AbortController: 'globals.html#abortcontroller', + AbortSignal: 'globals.html#abortsignal', + + Blob: 'buffer.html#blob', + + BroadcastChannel: 'worker_threads.html#broadcastchannel-extends-eventtarget', + + AsyncHook: 'async_hooks.html#async_hookscreatehookcallbacks', + AsyncResource: 'async_hooks.html#asyncresource', + + 'brotli options': 'zlib.html#brotlioptions', + + Buffer: 'buffer.html#buffer', + + ChildProcess: 'child_process.html#childprocess', + + 'cluster.Worker': 'cluster.html#worker', + + Cipher: 'crypto.html#cipher', + Decipher: 'crypto.html#decipher', + DiffieHellman: 'crypto.html#diffiehellman', + DiffieHellmanGroup: 'crypto.html#diffiehellmangroup', + ECDH: 'crypto.html#ecdh', + Hash: 'crypto.html#hash', + Hmac: 'crypto.html#hmac', + KeyObject: 'crypto.html#keyobject', + Sign: 'crypto.html#sign', + Verify: 'crypto.html#verify', + 'crypto.constants': 'crypto.html#cryptoconstants', + + CryptoKey: 'webcrypto.html#cryptokey', + CryptoKeyPair: 'webcrypto.html#cryptokeypair', + Crypto: 'webcrypto.html#crypto', + SubtleCrypto: 'webcrypto.html#subtlecrypto', + RsaOaepParams: 'webcrypto.html#rsaoaepparams', + AlgorithmIdentifier: 'webcrypto.html#algorithmidentifier', + AesCtrParams: 'webcrypto.html#aesctrparams', + AesCbcParams: 'webcrypto.html#aescbcparams', + AesGcmParams: 'webcrypto.html#aesgcmparams', + EcdhKeyDeriveParams: 'webcrypto.html#ecdhkeyderiveparams', + HkdfParams: 'webcrypto.html#hkdfparams', + Pbkdf2Params: 'webcrypto.html#pbkdf2params', + HmacKeyGenParams: 'webcrypto.html#hmackeygenparams', + AesKeyGenParams: 'webcrypto.html#aeskeygenparams', + RsaHashedKeyGenParams: 'webcrypto.html#rsahashedkeygenparams', + EcKeyGenParams: 'webcrypto.html#eckeygenparams', + RsaHashedImportParams: 'webcrypto.html#rsahashedimportparams', + EcKeyImportParams: 'webcrypto.html#eckeyimportparams', + HmacImportParams: 'webcrypto.html#hmacimportparams', + EcdsaParams: 'webcrypto.html#ecdsaparams', + RsaPssParams: 'webcrypto.html#rsapssparams', + Ed448Params: 'webcrypto.html#ed448params', + + 'dgram.Socket': 'dgram.html#dgramsocket', + + Channel: 'diagnostics_channel.html#channel', + + Domain: 'domain.html#domain', + + 'errors.Error': 'errors.html#error', + + 'import.meta': 'esm.html#importmeta', + + EventEmitter: 'events.html#eventemitter', + EventTarget: 'events.html#eventtarget', + Event: 'events.html#event', + CustomEvent: 'events.html#customevent', + EventListener: 'events.html#listener', + + FileHandle: 'fs.html#filehandle', + 'fs.Dir': 'fs.html#fsdir', + 'fs.Dirent': 'fs.html#fsdirent', + 'fs.FSWatcher': 'fs.html#fsfswatcher', + 'fs.ReadStream': 'fs.html#fsreadstream', + 'fs.Stats': 'fs.html#fsstats', + 'fs.StatWatcher': 'fs.html#fsstatwatcher', + 'fs.WriteStream': 'fs.html#fswritestream', + + 'http.Agent': 'http.html#httpagent', + 'http.ClientRequest': 'http.html#httpclientrequest', + 'http.IncomingMessage': 'http.html#httpincomingmessage', + 'http.OutgoingMessage': 'http.html#httpoutgoingmessage', + 'http.Server': 'http.html#httpserver', + 'http.ServerResponse': 'http.html#httpserverresponse', + + ClientHttp2Session: 'http2.html#clienthttp2session', + ClientHttp2Stream: 'http2.html#clienthttp2stream', + 'HTTP/2 Headers Object': 'http2.html#headers-object', + 'HTTP/2 Settings Object': 'http2.html#settings-object', + 'http2.Http2ServerRequest': 'http2.html#http2http2serverrequest', + 'http2.Http2ServerResponse': 'http2.html#http2http2serverresponse', + Http2SecureServer: 'http2.html#http2secureserver', + Http2Server: 'http2.html#http2server', + Http2Session: 'http2.html#http2session', + Http2Stream: 'http2.html#http2stream', + ServerHttp2Stream: 'http2.html#serverhttp2stream', + ServerHttp2Session: 'http2.html#serverhttp2session', + + 'https.Server': 'https.html#httpsserver', + + module: 'modules.html#the-module-object', + + 'module.SourceMap': 'module.html#modulesourcemap', + + require: 'modules.html#requireid', + + Handle: 'net.html#serverlistenhandle-backlog-callback', + 'net.BlockList': 'net.html#netblocklist', + 'net.Server': 'net.html#netserver', + 'net.Socket': 'net.html#netsocket', + 'net.SocketAddress': 'net.html#netsocketaddress', + + NodeEventTarget: 'events.html#nodeeventtarget', + + 'os.constants.dlopen': 'os.html#dlopen-constants', + + Histogram: 'perf_hooks.html#histogram', + IntervalHistogram: 'perf_hooks.html#intervalhistogram-extends-histogram', + RecordableHistogram: 'perf_hooks.html#recordablehistogram-extends-histogram', + PerformanceEntry: 'perf_hooks.html#performanceentry', + PerformanceNodeTiming: 'perf_hooks.html#performancenodetiming', + PerformanceObserver: 'perf_hooks.html#perf_hooksperformanceobserver', + PerformanceObserverEntryList: 'perf_hooks.html#performanceobserverentrylist', + + 'readline.Interface': 'readline.html#readlineinterface', + 'readline.InterfaceConstructor': 'readline.html#interfaceconstructor', + 'readlinePromises.Interface': 'readline.html#readlinepromisesinterface', + + 'repl.REPLServer': 'repl.html#replserver', + + Stream: 'stream.html#stream', + 'stream.Duplex': 'stream.html#streamduplex', + Duplex: 'stream.html#streamduplex', + 'stream.Readable': 'stream.html#streamreadable', + Readable: 'stream.html#streamreadable', + 'stream.Transform': 'stream.html#streamtransform', + Transform: 'stream.html#streamtransform', + 'stream.Writable': 'stream.html#streamwritable', + Writable: 'stream.html#streamwritable', + + Immediate: 'timers.html#immediate', + Timeout: 'timers.html#timeout', + Timer: 'timers.html#timers', + + TapStream: 'test.html#tapstream', + + 'tls.SecureContext': 'tls.html#tlscreatesecurecontextoptions', + 'tls.Server': 'tls.html#tlsserver', + 'tls.TLSSocket': 'tls.html#tlstlssocket', + + Tracing: 'tracing.html#tracing-object', + + URL: 'url.html#the-whatwg-url-api', + URLSearchParams: 'url.html#urlsearchparams', + + 'vm.Module': 'vm.html#vmmodule', + 'vm.Script': 'vm.html#vmscript', + 'vm.SourceTextModule': 'vm.html#vmsourcetextmodule', + + MessagePort: 'worker_threads.html#messageport', + Worker: 'worker_threads.html#worker', + + X509Certificate: 'crypto.html#x509certificate', + + 'zlib options': 'zlib.html#options', + + ReadableStream: 'webstreams.html#readablestream', + ReadableStreamDefaultReader: 'webstreams.html#readablestreamdefaultreader', + ReadableStreamBYOBReader: 'webstreams.html#readablestreambyobreader', + ReadableStreamDefaultController: + 'webstreams.html#readablestreamdefaultcontroller', + ReadableByteStreamController: 'webstreams.html#readablebytestreamcontroller', + ReadableStreamBYOBRequest: 'webstreams.html#readablestreambyobrequest', + WritableStream: 'webstreams.html#writablestream', + WritableStreamDefaultWriter: 'webstreams.html#writablestreamdefaultwriter', + WritableStreamDefaultController: + 'webstreams.html#writablestreamdefaultcontroller', + TransformStream: 'webstreams.html#transformstream', + TransformStreamDefaultController: + 'webstreams.html#transformstreamdefaultcontroller', + ByteLengthQueuingStrategy: 'webstreams.html#bytelengthqueuingstrategy', + CountQueuingStrategy: 'webstreams.html#countqueuingstrategy', + TextEncoderStream: 'webstreams.html#textencoderstream', + TextDecoderStream: 'webstreams.html#textdecoderstream', +}; + +// This is a mapping for miscellaneous types within the Markdown content and their respective +// external reference on appropriate 3rd-party vendors/documentation sites. +export const DOC_TYPES_MAPPING_OTHER = { + any: `${DOC_MDN_BASE_URL_JS_PRIMITIVES}#Data_types`, + this: `${DOC_MDN_BASE_URL_JS}Reference/Operators/this`, + + ArrayBufferView: + 'https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView', + + AsyncIterator: 'https://tc39.github.io/ecma262/#sec-asynciterator-interface', + AsyncIterable: 'https://tc39.github.io/ecma262/#sec-asynciterable-interface', + AsyncFunction: 'https://tc39.es/ecma262/#sec-async-function-constructor', + + 'Module Namespace Object': + 'https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects', + + AsyncGeneratorFunction: + 'https://tc39.es/proposal-async-iteration/#sec-asyncgeneratorfunction-constructor', + + Iterable: `${DOC_MDN_BASE_URL_JS}Reference/Iteration_protocols#The_iterable_protocol`, + Iterator: `${DOC_MDN_BASE_URL_JS}Reference/Iteration_protocols#The_iterator_protocol`, + + FormData: `${DOC_MDN_BASE_URL}API/FormData`, + Headers: `${DOC_MDN_BASE_URL}/API/Headers`, + Response: `${DOC_MDN_BASE_URL}/API/Response`, + Request: `${DOC_MDN_BASE_URL}/API/Request`, +}; diff --git a/src/loader.mjs b/src/loader.mjs new file mode 100644 index 00000000..b7c32a82 --- /dev/null +++ b/src/loader.mjs @@ -0,0 +1,39 @@ +'use strict'; + +import { extname } from 'node:path'; +import { readFile } from 'node:fs/promises'; + +import { globSync } from 'glob'; +import { VFile } from 'vfile'; + +/** + * This method creates a simple abstract "Loader", which technically + * could be used for different things, but here we want to use it to load + * Markdown files and transform them into VFiles + */ +const createLoader = () => { + /** + * Loads API Doc files and transforms it into VFiles + * + * @param {string} searchPath A glob/path for API docs to be loaded + * The input string can be a simple path (relative or absolute) + * The input string can also be any allowed glob string + * + * @see https://code.visualstudio.com/docs/editor/glob-patterns + */ + const loadFiles = searchPath => { + const resolvedFiles = globSync(searchPath).filter( + filePath => extname(filePath) === '.md' + ); + + return resolvedFiles.map(async filePath => { + const fileBuffer = await readFile(filePath); + + return new VFile({ path: filePath, value: fileBuffer }); + }); + }; + + return { loadFiles }; +}; + +export default createLoader; diff --git a/src/metadata.mjs b/src/metadata.mjs new file mode 100644 index 00000000..7a02eb65 --- /dev/null +++ b/src/metadata.mjs @@ -0,0 +1,121 @@ +'use strict'; + +/** + * This method allows us to handle creation of Metadata entries + * within the current scope of API docs being parsed + * + * This can be used disconnected with a specific file, and can be aggregated + * to many files to create a full Navigation for a given version of the API + * + * @param {InstanceType} slugger A GitHub Slugger + */ +const createMetadata = slugger => { + /** + * This holds a temporary buffer of raw metadata before being + * transformed into NavigationEntries and MetadataEntries + * + * @type {{ + * heading: import('./types.d.ts').HeadingMetadataEntry, + * stability: import('./types.d.ts').ApiDocMetadataEntry['stability'], + * properties: import('./types.d.ts').ApiDocRawMetadataEntry, + * }} + */ + const internalMetadata = { + heading: { + text: undefined, + type: undefined, + name: undefined, + depth: -1, + }, + stability: undefined, + properties: {}, + }; + + return { + /** + * Set the Heading of a given Metadata + * + * @param {import('./types.d.ts').HeadingMetadataEntry} heading The new heading metadata + */ + setHeading: heading => { + internalMetadata.heading = heading; + }, + /** + * Set the Stability Index of a given Metadata + * + * @param {import('./types.d.ts').ApiDocMetadataEntry['stability']} stability The new stability metadata + */ + setStability: stability => { + internalMetadata.stability = stability; + }, + /** + * Set the Metadata (from YAML if exists) properties to the current Metadata entry + * it also allows for extra data (such as Stability Index) and miscellaneous data to be set + * although it'd be best to only set ones from {ApiDocRawMetadataEntry} + * + * Note: A single API doc entry might have multiple YAML metadata blocks, + * meaning that this method can be called multiple times to update the properties + * and complement each set of data. + * + * @param {Partial} properties Extra Metadata properties to be defined + */ + updateProperties: properties => { + internalMetadata.properties = { + ...internalMetadata.properties, + ...properties, + }; + }, + /** + * Generates a new Navigation entry and pushes them to the internal collection + * of Navigation entries, and returns a MetadataEntry which is then used by the parser + * and forwarded to any relevant generator. + * + * The Navigation entries has a dedicated separate method for retrieval + * as it can be manipulated outside of the scope of the generation of the content + * + * @param {import('vfile').VFile} apiDoc The API doc file being parsed + * @param {import('./types.d.ts').ApiDocMetadataEntry['content']} section An AST tree containing the Nodes of the API doc entry section + * @returns {import('./types.d.ts').ApiDocMetadataEntry} The locally created Metadata entries + */ + create: (apiDoc, section) => { + // This is the ID of a certain Navigation entry, which allows us to anchor + // a certain navigation section to a page ad the exact point of the page (scroll) + // This is useful for classes, globals and other type of YAML entries, as they reside + // within a module (page) and we want to link to them directly + const slugHash = `#${slugger.slug(internalMetadata.heading.text)}`; + + const { + type: yamlType, + name: yamlName, + source_link: sourceLink, + updates = [], + changes = [], + } = internalMetadata.properties; + + // We override the type of the heading if we have a YAML type + internalMetadata.heading.type = yamlType || internalMetadata.heading.type; + + // Returns the Metadata entry for the API doc + return { + // The API file basename (without the extension) + api: yamlName || apiDoc.stem, + // The path/slug of the API section + slug: `${apiDoc.stem}.html${slugHash}`, + // The source link of said API section + sourceLink: sourceLink, + // The latest updates to an API section + updates, + // The full-changeset to an API section + changes, + // The Heading metadata + heading: internalMetadata.heading, + // The Stability Index of the API section + stability: internalMetadata.stability, + // The AST tree of the API section + content: section, + }; + }, + }; +}; + +export default createMetadata; diff --git a/src/parser.mjs b/src/parser.mjs new file mode 100644 index 00000000..e6244474 --- /dev/null +++ b/src/parser.mjs @@ -0,0 +1,199 @@ +'use strict'; + +import { remark } from 'remark'; +import remarkGfm from 'remark-gfm'; + +import { u as createTree } from 'unist-builder'; +import { remove } from 'unist-util-remove'; +import { selectAll } from 'unist-util-select'; +import { SKIP, visit } from 'unist-util-visit'; +import { findAfter } from 'unist-util-find-after'; + +import createMetadata from './metadata.mjs'; +import createQueries from './queries.mjs'; + +import { createNodeSlugger } from './utils/slugger.mjs'; + +/** + * Creates an API doc parser for a given Markdown API doc file + */ +const createParser = () => { + // Creates an instance of the Remark processor with GFM support + // which is used for stringifying the AST tree back to Markdown + const remarkProcessor = remark().use(remarkGfm); + + const { + updateLinkReference, + updateTypeToReferenceLink, + updateMarkdownLink, + addYAMLMetadata, + addHeadingMetadata, + addStabilityIndexMetadata, + } = createQueries(); + + /** + * Parses a given API doc metadata file into a list of Metadata entries + * + * @param {import('vfile').VFile | Promise} apiDoc + */ + const parseApiDoc = async apiDoc => { + /** + * This holds references to all the Metadata entries for a given file + * this is used so we can traverse the AST tree and keep mutating things + * and then stringify the whole api doc file at once without creating sub traversals + * + * Then once we have the whole file parsed, we can split the resulting string into sections + * and seal the Metadata Entries (`.create()`) and return the result to the caller of parae. + * + * @type {Array} + */ + const metadataCollection = []; + + // We allow the API doc VFile to be a Promise of a VFile also, + // hence we want to ensure that it first resolves before we pass it to the parser + const resolvedApiDoc = await Promise.resolve(apiDoc); + + // Creates a new Slugger instance for the current API doc file + const nodeSlugger = createNodeSlugger(); + + // Parses the API doc into an AST tree using `unified` and `remark` + const apiDocTree = remarkProcessor.parse(resolvedApiDoc); + + // Get all Markdown Footnote definitions from the tree + const markdownDefinitions = selectAll('definition', apiDocTree); + + // Handles Link References + visit(apiDocTree, createQueries.UNIST.isLinkReference, node => { + updateLinkReference(node, markdownDefinitions); + + return SKIP; + }); + + // Removes all the original definitions from the tree as they are not needed + // anymore, since all link references got updated to be plain links + remove(apiDocTree, markdownDefinitions); + + // Handles API type references transformation into links that point + // to the reference to a said API type + visit(apiDocTree, createQueries.UNIST.isTextWithType, node => { + updateTypeToReferenceLink(node); + + return SKIP; + }); + + // Handles normalisation URLs that reference to API doc files with .md extension + // to replace the .md into .html, since the API doc files get eventually compiled as HTML + visit(apiDocTree, createQueries.UNIST.isMarkdownUrl, node => { + updateMarkdownLink(node); + + return SKIP; + }); + + // Handles iterating the tree and creating subtrees for each API doc entry + // where an API doc entry is defined by a Heading Node + // (so all elements after a Heading until the next Heading) + // and then it creates and updates a Metadata entry for each API doc entry + // and then generates the final content for each API doc entry and pushes it to the collection + visit(apiDocTree, createQueries.UNIST.isHeading, (headingNode, index) => { + // Creates a new Metadata entry for the current API doc file + const apiEntryMetadata = createMetadata(nodeSlugger); + + // Adds the Metadata of the current Heading Node to the Metadata entry + addHeadingMetadata(headingNode, apiEntryMetadata); + + // We retrieve the immediate next Heading if it exists + // This is used for ensuring that we don't include items that would + // belong only to the next heading to the current Heading metadata + // Note that if there is no next heading, we use the current node as the next one + const nextHeadingNode = + findAfter(apiDocTree, index, createQueries.UNIST.isHeading) ?? + headingNode; + + // This is the cutover index of the subtree that we should get + // of all the Nodes within the AST tree that belong to this section + // If `next` is equals the current heading, it means ther's no next heading + // and we are reaching the end of the document, hence the cutover should be the end of + // the document itself. + const stop = + headingNode === nextHeadingNode + ? apiDocTree.children.length - 1 + : apiDocTree.children.indexOf(nextHeadingNode); + + // Retrieves all the Nodes that should belong to the current API doc section + // `index + 1` is used to skip the current Heading Node + const apiSectionTree = createTree( + 'root', + apiDocTree.children.slice(index + 1, stop) + ); + + // Visits all Stability Index Nodes from the current subtree if there's any + // and then apply the Stability Index Metadata to the current Metadata entry + visit(apiSectionTree, createQueries.UNIST.isStabilityIndex, node => { + // Retrieves the subtree of the Stability Index Node + const stabilityNodes = createTree('root', node.children[0].children); + + // Adds the Stability Index Metadata to the current Metadata entry + addStabilityIndexMetadata(stabilityNodes, apiEntryMetadata); + + return SKIP; + }); + + // Visits all YAML Nodes from the current subtree if there's any + // and then apply the YAML Metadata to the current Metadata entry + visit(apiSectionTree, createQueries.UNIST.isYamlNode, node => { + // Adds the YAML Metadata to the current Metadata entry + addYAMLMetadata(node, apiEntryMetadata); + + return SKIP; + }); + + // Removes already parsed items from the subtree so that they aren't included in the final content + remove(apiSectionTree, [ + createQueries.UNIST.isStabilityIndex, + createQueries.UNIST.isYamlNode, + ]); + + // Applies the AST transformations to the subtree based on the API doc entry Metadata + // Note that running the transformation on the subtree isn't costly as it is a reduced tree + // and the GFM transformations aren't that heavy + const transformedApiSectionTree = remarkProcessor.runSync(apiSectionTree); + + // Adds the `toJSON` method to stringify the tree back to Markdown + // So that it gets serialized correctly by JSON.stringify + transformedApiSectionTree.toJSON = () => + remarkProcessor.stringify(transformedApiSectionTree); + + // We seal and create the API doc entry Metadata and push them to the collection + const parsedApiEntryMetadata = apiEntryMetadata.create( + resolvedApiDoc, + transformedApiSectionTree + ); + + // We push the parsed API doc entry Metadata to the collection + metadataCollection.push(parsedApiEntryMetadata); + + return SKIP; + }); + + // Returns the Metadata entries for the given API doc file + return metadataCollection; + }; + + /** + * This method allows to parse multiple API doc files at once + * and it simply wraps parseApiDoc with the given API docs + * + * @param {Array>} apiDocs List of API doc files to be parsed + */ + const parseApiDocs = async apiDocs => { + // We do a Promise.all, to ensure that each API doc is resolved asynchronously + // but all need to be resolved first before we return the result to the caller + const resolvedApiDocEntries = await Promise.all(apiDocs.map(parseApiDoc)); + + return resolvedApiDocEntries.flat(); + }; + + return { parseApiDocs, parseApiDoc }; +}; + +export default createParser; diff --git a/src/queries.mjs b/src/queries.mjs new file mode 100644 index 00000000..d0c09b99 --- /dev/null +++ b/src/queries.mjs @@ -0,0 +1,156 @@ +'use strict'; + +import * as parserUtils from './utils/parser.mjs'; +import { transformNodesToString } from './utils/unist.mjs'; + +/** + * Creates an instance of the Query Manager, which allows to do multiple sort + * of metadata and content metadata manipulation within an API Doc + */ +const createQueries = () => { + /** + * Sanitizes the YAML source by returning the inner YAML content + * and then parsing it into an API Metadata object and updating the current Metadata + * + * @param {import('unist').Node} node The YAML Node + * @param {ReturnType} apiEntryMetadata The API entry Metadata + */ + const addYAMLMetadata = (node, apiEntryMetadata) => { + const sanitizedString = node.value.replace( + createQueries.QUERIES.yamlInnerContent, + (_, __, inner) => inner + ); + + apiEntryMetadata.updateProperties( + parserUtils.parseYAMLIntoMetadata(sanitizedString) + ); + }; + + /** + * Transforms plain reference to Web/JavaScript/Node.js types + * into Markdown links containing the proper reference to said types + * + * @param {import('unist').Node} node The Type Node + */ + const updateTypeToReferenceLink = node => { + const parsedReference = node.value.replace( + createQueries.QUERIES.normalizeTypes, + parserUtils.transformTypeToReferenceLink + ); + + node.type = 'html'; + node.value = parsedReference; + }; + + /** + * Parse a Heading Node into Metadata and updates the current Metadata + * + * @param {import('unist').Node} node The Heading Node + * @param {ReturnType} apiEntryMetadata The API entry Metadata + */ + const addHeadingMetadata = (node, apiEntryMetadata) => { + const heading = transformNodesToString(node.children); + + const parsedHeading = parserUtils.parseHeadingIntoMetadata( + heading, + node.depth + ); + + apiEntryMetadata.setHeading(parsedHeading); + }; + + /** + * Updates a Markdown Link into a HTML Link for API Docs + * + * @param {import('unist').Node} node Thead Link Node + */ + const updateMarkdownLink = node => { + node.url = node.url.replace( + createQueries.QUERIES.markdownUrl, + (_, filename, hash = '') => `${filename}.html${hash}` + ); + }; + + /** + * Updates a Markdown Link Reference into an actual Link to the Definition + * + * @param {import('unist').Node} node Thead Link Reference Node + * @param {Array} definitions The Definitions of the API Doc + */ + const updateLinkReference = (node, definitions) => { + const definition = definitions.find( + ({ identifier }) => identifier === node.identifier + ); + + node.type = 'link'; + node.url = definition.url; + }; + + /** + * Parses a Stability Index Entry and updates the current Metadata + * + * @param {import('unist').Parent} node Thead Link Reference Node + * @param {ReturnType} apiEntryMetadata The API entry Metadata + */ + const addStabilityIndexMetadata = (node, apiEntryMetadata) => { + /** + * Handles transforming the Stability Index Node into a JSON object + * including the index and a concatenated description of the index + * + * @returns {import('./types.d.ts').StabilityIndexMetadataEntry} + */ + node.toJSON = () => { + const stabilityIndexString = transformNodesToString(node.children); + + const [, index, description] = + createQueries.QUERIES.stabilityIndex.exec(stabilityIndexString); + + return { + index: Number(index), + description: description.replaceAll('\n', ' ').trim(), + }; + }; + + apiEntryMetadata.setStability(node); + }; + + return { + addYAMLMetadata, + updateTypeToReferenceLink, + addHeadingMetadata, + updateMarkdownLink, + updateLinkReference, + addStabilityIndexMetadata, + }; +}; + +// This defines the actual REGEX Queries +createQueries.QUERIES = { + // Fixes the references to Markdown pages into the API documentation + markdownUrl: /^(?![+a-z]+:)([^#?]+)\.md(#.+)?$/i, + // ReGeX to match the {Type} (Structure Type metadatas) + // eslint-disable-next-line no-useless-escape + normalizeTypes: /(\{|<)(?! )[a-z0-9.| \n\[\]\\]+(?! )(\}|>)/gim, + // ReGeX for handling Stability Indexes Metadata + stabilityIndex: /^Stability: ([0-5])(?:\s*-\s*)?(.*)$/s, + // ReGeX for retrieving the inner content from a YAML block + yamlInnerContent: /^/, +}; + +createQueries.UNIST = { + isStabilityIndex: ({ type, children }) => + type === 'blockquote' && + createQueries.QUERIES.stabilityIndex.test(transformNodesToString(children)), + isYamlNode: ({ type, value }) => + type === 'html' && createQueries.QUERIES.yamlInnerContent.test(value), + isTextWithType: ({ type, value }) => + type === 'text' && createQueries.QUERIES.normalizeTypes.test(value), + isMarkdownUrl: ({ type, url }) => + type === 'link' && createQueries.QUERIES.markdownUrl.test(url), + isHeading: ({ type, depth }) => + type === 'heading' && depth >= 1 && depth <= 4, + isLinkReference: ({ type, identifier }) => + type === 'linkReference' && !!identifier, +}; + +export default createQueries; diff --git a/src/types.d.ts b/src/types.d.ts new file mode 100644 index 00000000..bbda36a5 --- /dev/null +++ b/src/types.d.ts @@ -0,0 +1,69 @@ +import { Parent, Node } from 'unist'; + +// String serialization of the AST tree +// @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#tojson_behavior +export interface WithJSON extends T { + toJSON: () => J; +} + +export interface StabilityIndexMetadataEntry { + index: number; + description: string; +} + +export interface HeadingMetadataEntry { + type: + | 'event' + | 'method' + | 'property' + | 'class' + | 'module' + | 'classMethod' + | 'ctor'; + text: string; + name: string; + depth: number; +} + +export interface ApiDocMetadataChange { + // The Node.js version or versions where said change was introduced simultaneously + version: string | string[]; + // The GitHub PR URL of said change + 'pr-url': string; + // The description of said change + description: string; +} + +export interface ApiDocMetadataUpdate { + // The type of the API doc Metadata update + type: 'added' | 'removed' | 'deprecated' | 'introduced_in' | 'napiVersion'; + // The Node.js version or versions where said metadata stability index changed + version: string[]; +} + +export interface ApiDocRawMetadataEntry { + type?: string; + name?: string; + source_link?: string; + updates?: ApiDocMetadataUpdate[]; + changes?: ApiDocMetadataChange[]; +} + +export interface ApiDocMetadataEntry { + // The name of the API doc file without the file extension (basename) + api: string; + // The unique slug of a Heading/Navigation entry which is linkable through an anchor + slug: string; + // The GitHub URL to the source of the API entry + sourceLink: string | undefined; + // Any updates to the API doc Metadata + updates: ApiDocMetadataUpdate[]; + // Any changes to the API doc Metadata + changes: ApiDocMetadataChange[]; + // The parsed Markdown content of a Navigation Entry + heading: HeadingMetadataEntry; + // The API doc metadata Entry Stability Index if exists + stability: WithJSON | undefined; + // The subtree containing all Nodes of the API doc entry + content: WithJSON; +} diff --git a/src/utils/parser.mjs b/src/utils/parser.mjs new file mode 100644 index 00000000..b7714763 --- /dev/null +++ b/src/utils/parser.mjs @@ -0,0 +1,141 @@ +'use strict'; + +import yaml from 'yaml'; + +import { + DOC_API_HEADING_TYPES, + DOC_API_YAML_KEYS_ARRAYS, + DOC_API_YAML_KEYS_UPDATE, + DOC_MDN_BASE_URL_JS_GLOBALS, + DOC_MDN_BASE_URL_JS_PRIMITIVES, + DOC_TYPES_MAPPING_GLOBALS, + DOC_TYPES_MAPPING_NODE_MODULES, + DOC_TYPES_MAPPING_OTHER, + DOC_TYPES_MAPPING_PRIMITIVES, +} from '../constants.mjs'; + +/** + * This method replaces plain text Types within the Markdown content into Markdown links + * that link to the actual relevant reference for such type (either internal or external link) + * + * @param {string} type The plain type to be transformed into a Markdown link + * @returns {string} The Markdown link as a string (formatted in Markdown) + */ +export const transformTypeToReferenceLink = type => { + const typeInput = type.replace('{', '').replace('}', ''); + + /** + * Handles the mapping (if there's a match) of the input text + * into the reference type from the API docs + * + * @param {string} lookupPiece + * @returns {string | undefined} The reference URL or undefined if no match was found + */ + const transformType = lookupPiece => { + // Transform JS primitive type references into Markdown links (MDN) + if (lookupPiece.toLowerCase() in DOC_TYPES_MAPPING_PRIMITIVES) { + const typeValue = DOC_TYPES_MAPPING_PRIMITIVES[lookupPiece.toLowerCase()]; + + return `${DOC_MDN_BASE_URL_JS_PRIMITIVES}#${typeValue}_type`; + } + + // Transforms JS Global type references into Markdown links (MDN) + if (lookupPiece in DOC_TYPES_MAPPING_GLOBALS) { + return `${DOC_MDN_BASE_URL_JS_GLOBALS}${lookupPiece}`; + } + + // Transform other external Web/JavaScript type references into Markdown links + // to diverse different external websites. These already are formatted as links + if (lookupPiece in DOC_TYPES_MAPPING_OTHER) { + return DOC_TYPES_MAPPING_NODE_MODULES[lookupPiece]; + } + + // Transform Node.js type/module references into Markdown links + // that refer to other API docs pages within the Node.js API docs + if (lookupPiece in DOC_TYPES_MAPPING_NODE_MODULES) { + return DOC_TYPES_MAPPING_NODE_MODULES[lookupPiece]; + } + + return undefined; + }; + + const typePieces = typeInput.split('|').map(piece => { + // This is the content to render as the text of the Markdown link + const trimmedPiece = piece.trim(); + + // This is what we will compare against the API types mappings + const result = transformType(trimmedPiece.replace(/(?:\[])+$/, '')); + + return result ? `[\`${trimmedPiece}\`](${result})` : undefined; + }); + + // Filter out pieces that we failed to map and then join the valid ones + // into different links separated by a `|` + const markdownLinks = typePieces.filter(Boolean).join(' | '); + + // Return the replaced links or the original content if they all failed to be replaced + // Note that if some failed to get replaced, only the valid ones will be returned + // NOTE: Based on the original code, we don't seem to care when we fail specific entries to be replaced + // although I believe this should be revisited and either show the original type content or show a warning + return markdownLinks || typeInput; +}; + +/** + * Parses Markdown YAML source into a JavaScript object containing all the metadata + * (this is forwarded to the parser so it knows what to do with said metadata) + * + * @param {string} yamlString The YAML string to be parsed + * @returns {import('../types.d.ts').ApiDocRawMetadataEntry} The parsed YAML metadata + */ +export const parseYAMLIntoMetadata = yamlString => { + const replacedContent = yamlString + // special validations for some non-cool formatted properties of the docs schema + .replace('introduced_in=', 'introduced_in: ') + .replace('source_link=', 'source_link: ') + .replace('type=', 'type: ') + .replace('name=', 'name: '); + + // Ensures that the parsed YAML is an object, because even if it is not + // i.e. a plain string or an array, it will simply not result into anything + const parsedYaml = Object(yaml.parse(replacedContent)); + + // This cleans up the YAML metadata into something more standardized + Object.keys(parsedYaml).forEach(key => { + // Some entries should always be Array for the sake of consistency + if (DOC_API_YAML_KEYS_ARRAYS.includes(key)) { + parsedYaml[key] = [parsedYaml[key]].flat(); + } + + // We transform some entries in a standardized "updates" field + // and then remove them from the parsedYaml + if (DOC_API_YAML_KEYS_UPDATE.includes(key)) { + parsedYaml.updates = [{ type: key, version: parsedYaml[key] }]; + + delete parsedYaml[key]; + } + }); + + return parsedYaml; +}; + +/** + * Parses a raw Heading string into Heading metadata + * + * @param {string} heading The raw Heading text + * @param {number} depth The depth of the heading + * @returns {import('../types.d.ts').HeadingMetadataEntry} Parsed Heading entry + */ +export const parseHeadingIntoMetadata = (heading, depth) => { + for (const { type, regex } of DOC_API_HEADING_TYPES) { + // Attempts to get a match from one of the heading types, if a match is found + // we use that type as the heading type, and extract the regex expression match group + // which should be the inner "plain" heading content (or the title of the heading for navigation) + const [, innerHeading] = heading.match(regex) ?? []; + + if (innerHeading && innerHeading.length) { + return { text: heading, type, name: innerHeading, depth }; + } + } + + return { text: heading, type: 'module', name: heading, depth }; +}; diff --git a/src/utils/slugger.mjs b/src/utils/slugger.mjs new file mode 100644 index 00000000..fc0eb933 --- /dev/null +++ b/src/utils/slugger.mjs @@ -0,0 +1,39 @@ +'use strict'; + +import GitHubSlugger from 'github-slugger'; + +import { DOC_API_SLUGS_REPLACEMENTS } from '../constants.mjs'; + +/** + * Creates a modified version of the GitHub Slugger + * + * @returns {InstanceType} The modified GitHub Slugger + */ +export const createNodeSlugger = () => { + const slugger = new GitHubSlugger(); + + return { + /** + * Creates a new slug based on the provided string + * + * @param {string} title The title to be parsed into a slug + */ + slug: title => { + // Applies certain string replacements that are specific + // to the way how Node.js generates slugs/anchor IDs + return DOC_API_SLUGS_REPLACEMENTS.reduce( + (piece, { from, to }) => piece.replace(from, to), + // Slugify the title using GitHub Slugger + slugger.slug(title) + ); + }, + + /** + * Resets the cache of the Slugger, preventing repeated slugs + * to be marked as repeated. + * + * @returns {void} + */ + reset: () => slugger.reset(), + }; +}; diff --git a/src/utils/unist.mjs b/src/utils/unist.mjs new file mode 100644 index 00000000..5b35288b --- /dev/null +++ b/src/utils/unist.mjs @@ -0,0 +1,50 @@ +'use strict'; + +import { pointEnd, pointStart } from 'unist-util-position'; + +/** + * This utility allows us to join children Nodes into one + * and transfor them back to what their source would look like + * + * @param {Array} nodes Nodes to parsed and joined + * @returns {string} The parsed and joined nodes as a string + */ +export const transformNodesToString = nodes => { + const mappedChildren = nodes.map(node => { + switch (node.type) { + case 'inlineCode': + return `\`${node.value}\``; + case 'strong': + return `**${transformNodesToString(node.children)}**`; + case 'emphasis': + return `_${transformNodesToString(node.children)}_`; + default: + return node.children + ? transformNodesToString(node.children) + : node.value; + } + }); + + return mappedChildren.join(''); +}; + +/** + * This method is an utility that allows us to conditionally invoke/call a callback + * based on test conditions related to a Node's position relative to another one + * being before or not the other Node + * + * NOTE: Not yet used, but probably going to be used by the JSON generator. + * + * @param {import('unist').Node | undefined} nodeA The Node to be used as a position reference to check against + * the other Node. If the other Node is before this one, the callback will be called. + * @param {import('unist').Node | undefined} nodeB The Node to be checked against the position of the first Node + * @param {(nodeA: import('unist').Node, nodeB: import('unist').Node) => void} callback The callback to be called + */ +export const callIfBefore = (nodeA, nodeB, callback) => { + const positionA = pointEnd(nodeA); + const positionB = pointStart(nodeB); + + if (positionA && positionB && positionA.line > positionB.line) { + callback(nodeA, nodeB); + } +};