diff --git a/.gitignore b/.gitignore index 29e113d0709ddb..67663d274ce3b6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ test/treeshake/stats.html test/e2e/chromium test/e2e/output-screenshots -**/node_modules \ No newline at end of file +**/node_modules +**/docs_new \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8026643ec8fd4a..73ff9557f131ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-terser": "^0.4.0", "chalk": "^5.2.0", + "clean-jsdoc-theme": "^4.3.0", "concurrently": "^9.0.0", "dpdm": "^3.14.0", "eslint": "^8.37.0", @@ -21,6 +22,7 @@ "eslint-plugin-import": "^2.27.5", "failonlyreporter": "^1.0.0", "jimp": "^1.6.0", + "jsdoc": "^4.0.4", "magic-string": "^0.30.0", "pixelmatch": "^6.0.0", "puppeteer": "^22.0.0", @@ -45,6 +47,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", @@ -54,6 +65,21 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.26.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/runtime": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", @@ -72,6 +98,19 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dev": true }, + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -719,6 +758,18 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdoc/salty": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.8.tgz", + "integrity": "sha512-5e+SFVavj1ORKlKaKr2BmTOekmXbelU7dC0cDkQLqag7xfuTPuGMUFx7KWJuv4bYZrTsoL2Z18VVCOKYxzoHcg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, "node_modules/@mdn/browser-compat-data": { "version": "5.6.11", "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.6.11.tgz", @@ -1520,6 +1571,28 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true + }, "node_modules/@types/node": { "version": "16.9.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", @@ -2037,6 +2110,12 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "node_modules/bmp-ts": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", @@ -2358,6 +2437,16 @@ "node": ">=6" } }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -2390,6 +2479,18 @@ } ] }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -2425,6 +2526,49 @@ "devtools-protocol": "*" } }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-jsdoc-theme": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/clean-jsdoc-theme/-/clean-jsdoc-theme-4.3.0.tgz", + "integrity": "sha512-QMrBdZ2KdPt6V2Ytg7dIt0/q32U4COpxvR0UDhPjRRKRL0o0MvRCR5YpY37/4rPF1SI1AYEKAWyof7ndCb/dzA==", + "dev": true, + "dependencies": { + "@jsdoc/salty": "^0.2.4", + "fs-extra": "^10.1.0", + "html-minifier-terser": "^7.2.0", + "klaw-sync": "^6.0.0", + "lodash": "^4.17.21", + "showdown": "^2.1.0" + }, + "peerDependencies": { + "jsdoc": ">=3.x <=4.x" + } + }, + "node_modules/clean-jsdoc-theme/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -3022,6 +3166,16 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/dpdm": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/dpdm/-/dpdm-3.14.0.tgz", @@ -4559,6 +4713,36 @@ "node": ">=12" } }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/htmlparser2": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", @@ -5225,12 +5409,59 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", "dev": true }, + "node_modules/jsdoc": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", + "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^14.1.1", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -5297,6 +5528,24 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5316,6 +5565,15 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -5408,6 +5666,15 @@ "node": ">=8" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -5656,6 +5923,51 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -5975,6 +6287,16 @@ "node": ">= 0.4.0" } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -6676,6 +6998,16 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6737,6 +7069,16 @@ "node": ">= 0.8" } }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -6971,6 +7313,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/puppeteer": { "version": "22.15.0", "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.15.0.tgz", @@ -7204,6 +7555,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7213,6 +7573,15 @@ "node": ">=0.10.0" } }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -7818,6 +8187,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/showdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", + "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==", + "dev": true, + "dependencies": { + "commander": "^9.0.0" + }, + "bin": { + "showdown": "bin/showdown.js" + }, + "funding": { + "type": "individual", + "url": "https://www.paypal.me/tiviesantos" + } + }, + "node_modules/showdown/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -8794,6 +9188,12 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -8819,6 +9219,12 @@ "through": "^2.3.8" } }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "dev": true + }, "node_modules/unique-filename": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", @@ -9239,6 +9645,12 @@ "node": ">=4.0" } }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 5a2df9621aee42..3b9dc2b4876446 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,9 @@ "type": "git", "url": "https://github.com/mrdoob/three.js" }, - "sideEffects": [ "./src/nodes/**/*" ], + "sideEffects": [ + "./src/nodes/**/*" + ], "files": [ "build", "examples/jsm", @@ -45,6 +47,7 @@ "test": "npm run lint && npm run test-unit && npm run test-unit-addons", "build": "rollup -c utils/build/rollup.config.js", "build-module": "rollup -c utils/build/rollup.config.js --configOnlyModule", + "build-docs": "jsdoc src/nodes -c utils/docs/jsdoc.config.json", "dev": "concurrently --names \"ROLLUP,HTTP\" -c \"bgBlue.bold,bgGreen.bold\" \"rollup -c utils/build/rollup.config.js -w -m inline\" \"servez -p 8080\"", "dev-ssl": "concurrently --names \"ROLLUP,HTTPS\" -c \"bgBlue.bold,bgGreen.bold\" \"rollup -c utils/build/rollup.config.js -w -m inline\" \"servez -p 8080 --ssl\"", "lint-core": "eslint src", @@ -93,6 +96,7 @@ "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-terser": "^0.4.0", "chalk": "^5.2.0", + "clean-jsdoc-theme": "^4.3.0", "concurrently": "^9.0.0", "dpdm": "^3.14.0", "eslint": "^8.37.0", @@ -102,6 +106,7 @@ "eslint-plugin-import": "^2.27.5", "failonlyreporter": "^1.0.0", "jimp": "^1.6.0", + "jsdoc": "^4.0.4", "magic-string": "^0.30.0", "pixelmatch": "^6.0.0", "puppeteer": "^22.0.0", diff --git a/src/nodes/core/Node.js b/src/nodes/core/Node.js index 326164f7cdab67..236cf00a90fd7d 100644 --- a/src/nodes/core/Node.js +++ b/src/nodes/core/Node.js @@ -6,6 +6,11 @@ import { MathUtils } from '../../math/MathUtils.js'; let _nodeId = 0; +/** + * Base class for all nodes. + * + * @augments EventDispatcher + */ class Node extends EventDispatcher { static get type() { @@ -14,31 +19,98 @@ class Node extends EventDispatcher { } + /** + * Constructs a new node. + * + * @param {String?} nodeType - The node type. + */ constructor( nodeType = null ) { super(); + /** + * The node type. This represents the result type of the node (e.g. `float` or `vec3`). + * + * @type {String?} + * @default null + */ this.nodeType = nodeType; + /** + * The update type of the node's {@link Node#update} method. Possible values are listed in {@link NodeUpdateType}. + * + * @type {String} + * @default 'none' + */ this.updateType = NodeUpdateType.NONE; + + /** + * The update type of the node's {@link Node#updateBefore} method. Possible values are listed in {@link NodeUpdateType}. + * + * @type {String} + * @default 'none' + */ this.updateBeforeType = NodeUpdateType.NONE; + + /** + * The update type of the node's {@link Node#updateAfter} method. Possible values are listed in {@link NodeUpdateType}. + * + * @type {String} + * @default 'none' + */ this.updateAfterType = NodeUpdateType.NONE; + /** + * The UUID of the node. + * + * @type {String} + * @readonly + */ this.uuid = MathUtils.generateUUID(); + /** + * The version of the node. The version automatically is increased when {@link Node#needsUpdate} is set to `true`. + * + * @type {Number} + * @readonly + * @default 0 + */ this.version = 0; - this._cacheKey = null; - this._cacheKeyVersion = 0; - + /** + * Whether this node is global or not. This property is relevant for the internal + * node caching system. All nodes which should be declared just once should + * set this flag to `true` (a typical example is `AttributeNode`). + * + * @type {Boolean} + * @default false + */ this.global = false; + /** + * This flag can be used for type testing (whether a given object is of type `Node` or not). + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNode = true; + // private + + this._cacheKey = null; + this._cacheKeyVersion = 0; + Object.defineProperty( this, 'id', { value: _nodeId ++ } ); } + /** + * Set this property to `true` when the node should be regenerated. + * + * @type {Boolean} + * @default false + */ set needsUpdate( value ) { if ( value === true ) { @@ -49,12 +121,25 @@ class Node extends EventDispatcher { } + /** + * The type of the class. The value is usually the constructor name. + * + * @type {String} + * @readonly + */ get type() { return this.constructor.type; } + /** + * Convenient method for defining {@link Node#update}. + * + * @param {Function} callback - The update method. + * @param {String} updateType - The update type. + * @return {Node} A reference to this node. + */ onUpdate( callback, updateType ) { this.updateType = updateType; @@ -64,24 +149,51 @@ class Node extends EventDispatcher { } + /** + * Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but + * this method automatically sets the update type to `FRAME`. + * + * @param {Function} callback - The update method. + * @return {Node} A reference to this node. + */ onFrameUpdate( callback ) { return this.onUpdate( callback, NodeUpdateType.FRAME ); } + /** + * Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but + * this method automatically sets the update type to `RENDER`. + * + * @param {Function} callback - The update method. + * @return {Node} A reference to this node. + */ onRenderUpdate( callback ) { return this.onUpdate( callback, NodeUpdateType.RENDER ); } + /** + * Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but + * this method automatically sets the update type to `OBJECT`. + * + * @param {Function} callback - The update method. + * @return {Node} A reference to this node. + */ onObjectUpdate( callback ) { return this.onUpdate( callback, NodeUpdateType.OBJECT ); } + /** + * Convenient method for defining {@link Node#updateReference}. + * + * @param {Function} callback - The update method. + * @return {Node} A reference to this node. + */ onReference( callback ) { this.updateReference = callback.bind( this.getSelf() ); @@ -90,6 +202,12 @@ class Node extends EventDispatcher { } + /** + * The `this` reference might point to a Proxy so this method can be used + * to get the reference to the actual node instance. + * + * @return {Node} A reference to the node. + */ getSelf() { // Returns non-node object. @@ -98,18 +216,38 @@ class Node extends EventDispatcher { } + /** + * Nodes might refer to other objects like materials. This method allows to dynamically update the reference + * to such objects based on a given state (e.g. the current node frame or builder). + * + * @param {Any} state - This method can be invocated in different contexts so `state` can refer to any object type. + * @return {Any} The updated reference. + */ updateReference( /*state*/ ) { return this; } + /** + * By default this method returns the value of the {@link Node#global} flag. This method + * can be overwritten in dervied classes if an analytical way is required to determine the + * global status. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Boolean} Whether this node is global or not. + */ isGlobal( /*builder*/ ) { return this.global; } + /** + * Returns a generator that can be used to iterate over the child nodes. + * + * @return {Generator} The generator. + */ * getChildren() { for ( const { childNode } of getNodeChildren( this ) ) { @@ -120,12 +258,28 @@ class Node extends EventDispatcher { } + /** + * Calling this method dispatches the `dispose` event. This event can be used + * to register event listeners for clean up tasks. + */ dispose() { this.dispatchEvent( { type: 'dispose' } ); } + /** + * Callback for {@link Node#traverse}. + * + * @callback traverseCallback + * @param {Node} node - The current node. + */ + + /** + * Can be used to traverse through the node's hierarchy. + * + * @param {traverseCallback} callback - A callback that is executed per node. + */ traverse( callback ) { callback( this ); @@ -138,6 +292,12 @@ class Node extends EventDispatcher { } + /** + * Returns the cache key for this node. + * + * @param {Boolean} [force=false] - When set to `true`, a recompuatation of the cache key is forced. + * @return {Number} The cache key of the node. + */ getCacheKey( force = false ) { force = force || this.version !== this._cacheKeyVersion; @@ -153,36 +313,72 @@ class Node extends EventDispatcher { } + /** + * Returns the references to this node which is by default `this`. + * + * @return {Node} A reference to this node. + */ getScope() { return this; } + /** + * Returns the hash of the node which is used to identify the node. By default it's + * the {@link Node#uuid} however derived node classes might have to overwrite this method + * depending on their implementation. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {String} The hash. + */ getHash( /*builder*/ ) { return this.uuid; } + /** + * Returns the update type of {@link Node#update}. + * + * @return {NodeUpdateType} The update type. + */ getUpdateType() { return this.updateType; } + /** + * Returns the update type of {@link Node#updateBefore}. + * + * @return {NodeUpdateType} The update type. + */ getUpdateBeforeType() { return this.updateBeforeType; } + /** + * Returns the update type of {@link Node#updateAfter}. + * + * @return {NodeUpdateType} The update type. + */ getUpdateAfterType() { return this.updateAfterType; } + /** + * Certain types are composed of multiple elements. For example a `vec3` + * is composed of three `float` values. This method returns the type of + * these elements. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {String} The type of the node. + */ getElementType( builder ) { const type = this.getNodeType( builder ); @@ -192,6 +388,12 @@ class Node extends EventDispatcher { } + /** + * Returns the node's type. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {String} The type of the node. + */ getNodeType( builder ) { const nodeProperties = builder.getNodeProperties( this ); @@ -206,6 +408,15 @@ class Node extends EventDispatcher { } + /** + * This method is used during the build process of a node and ensures + * equal nodes are not built multiple times but just once. For exmaple if + * `attribute( 'uv' )` is used multiple times by the user, the build + * process makes sure to process just the first node. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The shared node if possible. Otherwise `this` is returned. + */ getShared( builder ) { const hash = this.getHash( builder ); @@ -215,6 +426,14 @@ class Node extends EventDispatcher { } + /** + * Represents the setup stage which is the first step of the build process, see {@link Node#build} method. + * This method is often overwritten in derived modules to prepare the node which is used as the output/result. + * The output node must be returned in the `return` statement. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node?} The output node. + */ setup( builder ) { const nodeProperties = builder.getNodeProperties( this ); @@ -232,6 +451,12 @@ class Node extends EventDispatcher { } + /** + * Represents the analyze stage which is the second step of the build process, see {@link Node#build} method. + * This stage anaylzes the node hierarchy and ensures descendent nodes are built. + * + * @param {NodeBuilder} builder - The current node builder. + */ analyze( builder ) { const usageCount = builder.increaseUsage( this ); @@ -256,6 +481,14 @@ class Node extends EventDispatcher { } + /** + * Represents the generate stage which is the third step of the build process, see {@link Node#build} method. + * This state builds the output node and returns the resulting shader string. + * + * @param {NodeBuilder} builder - The current node builder. + * @param {String?} output - Can be used to define the output type. + * @return {String?} The generated shader string. + */ generate( builder, output ) { const { outputNode } = builder.getNodeProperties( this ); @@ -268,24 +501,50 @@ class Node extends EventDispatcher { } + /** + * The method can be implemented to update the node's internal state before it is used to render an object. + * The {@link Node#updateBeforeType} property defines how often the update is executed. + * + * @param {NodeFrame} frame - A reference to the current node frame. + */ updateBefore( /*frame*/ ) { console.warn( 'Abstract function.' ); } + /** + * The method can be implemented to update the node's internal state after it was used to render an object. + * The {@link Node#updateAfterType} property defines how often the update is executed. + * + * @param {NodeFrame} frame - A reference to the current node frame. + */ updateAfter( /*frame*/ ) { console.warn( 'Abstract function.' ); } + /** + * The method can be implemented to update the node's internal state when it is used to render an object. + * The {@link Node#updateType} property defines how often the update is executed. + * + * @param {NodeFrame} frame - A reference to the current node frame. + */ update( /*frame*/ ) { console.warn( 'Abstract function.' ); } + /** + * This method performs the build of a node. The behavior of this method as well as its return value depend + * on the current build stage (setup, analyze or generate). + * + * @param {NodeBuilder} builder - The current node builder. + * @param {String?} output - Can be used to define the output type. + * @return {String?} When this method is executed in the setup or analyze stage, `null` is returned. In the generate stage, the generated shader string. + */ build( builder, output = null ) { const refNode = this.getShared( builder ); @@ -384,12 +643,22 @@ class Node extends EventDispatcher { } + /** + * Returns the child nodes as a JSON object. + * + * @return {Object} The serialiezed child objects as JSON. + */ getSerializeChildren() { return getNodeChildren( this ); } + /** + * Serializes the node to JSON. + * + * @param {Object} json - The output JSON object. + */ serialize( json ) { const nodeChildren = this.getSerializeChildren(); @@ -424,6 +693,11 @@ class Node extends EventDispatcher { } + /** + * Deerializes the node from the given JSON. + * + * @param {Object} json - The JSON object. + */ deserialize( json ) { if ( json.inputNodes !== undefined ) { @@ -472,6 +746,12 @@ class Node extends EventDispatcher { } + /** + * Seralizes the node into the three.js JSON Object/Scene format. + * + * @param {Object?} meta - An optional JSON object that already holds serialized data from other scene objects. + * @return {Object} The serialized node. + */ toJSON( meta ) { const { uuid, type } = this; diff --git a/src/nodes/core/constants.js b/src/nodes/core/constants.js index 5c0af31f1af8b7..27364a993fb081 100644 --- a/src/nodes/core/constants.js +++ b/src/nodes/core/constants.js @@ -1,8 +1,17 @@ + export const NodeShaderStage = { VERTEX: 'vertex', FRAGMENT: 'fragment' }; +/** + * Update types of a node. + * + * @property {string} NONE The update method is not executed. + * @property {string} FRAME The update method is executed per frame. + * @property {string} RENDER The update method is executed per render. A frame might be produced by multiple render calls so this value allows more detailed updates than FRAME. + * @property {string} OBJECT The update method is executed per {@link Object3D} that uses the node for rendering. + */ export const NodeUpdateType = { NONE: 'none', FRAME: 'frame', diff --git a/src/nodes/display/ColorAdjustment.js b/src/nodes/display/ColorAdjustment.js index 305d81bb82d3ce..a17e26cd4a27fb 100644 --- a/src/nodes/display/ColorAdjustment.js +++ b/src/nodes/display/ColorAdjustment.js @@ -5,6 +5,8 @@ import { ColorManagement } from '../../math/ColorManagement.js'; import { Vector3 } from '../../math/Vector3.js'; import { LinearSRGBColorSpace } from '../../constants.js'; +/** @module ColorAdjustment **/ + export const grayscale = /*@__PURE__*/ Fn( ( [ color ] ) => { return luminance( color.rgb ); @@ -52,6 +54,7 @@ export const threshold = ( color, threshold ) => mix( vec3( 0.0 ), color, lumina * saturation. The CDL should be typically be given input in a log space (such as LogC, ACEScc, * or AgX Log), and will return output in the same space. Output may require clamping >=0. * + * @method * @param {vec4} color Input (-Infinity < input < +Infinity) * @param {number | vec3} slope Slope (0 ≤ slope < +Infinity) * @param {number | vec3} offset Offset (-Infinity < offset < +Infinity; typically -1 < offset < 1) @@ -62,8 +65,8 @@ export const threshold = ( color, threshold ) => mix( vec3( 0.0 ), color, lumina * * References: * - ASC CDL v1.2 - * - https://blender.stackexchange.com/a/55239/43930 - * - https://docs.acescentral.com/specifications/acescc/ + * - {@link https://blender.stackexchange.com/a/55239/43930} + * - {@link https://docs.acescentral.com/specifications/acescc/} */ export const cdl = /*@__PURE__*/ Fn( ( [ color, diff --git a/src/nodes/functions/material/getAlphaHashThreshold.js b/src/nodes/functions/material/getAlphaHashThreshold.js index cc15a23ad2ab51..6b1cf5ac64080e 100644 --- a/src/nodes/functions/material/getAlphaHashThreshold.js +++ b/src/nodes/functions/material/getAlphaHashThreshold.js @@ -1,8 +1,6 @@ import { abs, add, ceil, clamp, dFdx, dFdy, exp2, float, floor, Fn, fract, length, log2, max, min, mul, sin, sub, vec2, vec3 } from '../../tsl/TSLBase.js'; -/** - * See: https://casual-effects.com/research/Wyman2017Hashed/index.html - */ +// See: https://casual-effects.com/research/Wyman2017Hashed/index.html const ALPHA_HASH_SCALE = 0.05; // Derived from trials only, and may be changed. diff --git a/src/nodes/utils/PostProcessingUtils.js b/src/nodes/utils/PostProcessingUtils.js index 8489bdf618e086..409bf5ced9487b 100644 --- a/src/nodes/utils/PostProcessingUtils.js +++ b/src/nodes/utils/PostProcessingUtils.js @@ -3,15 +3,18 @@ import { textureSize } from '../accessors/TextureSizeNode.js'; import { textureLoad } from '../accessors/TextureNode.js'; import { WebGPUCoordinateSystem } from '../../constants.js'; +/** @module PostProcessingUtils **/ + /** -* Computes a position in view space based on a fragment's screen position expressed as uv coordinates, the fragments -* depth value and the camera's inverse projection matrix. -* -* @param {vec2} screenPosition - The fragment's screen position expressed as uv coordinates. -* @param {float} depth - The fragment's depth value. -* @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix. -* @return {vec3} The fragments position in view space. -*/ + * Computes a position in view space based on a fragment's screen position expressed as uv coordinates, the fragments + * depth value and the camera's inverse projection matrix. + * + * @method + * @param {vec2} screenPosition - The fragment's screen position expressed as uv coordinates. + * @param {float} depth - The fragment's depth value. + * @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix. + * @return {vec3} The fragments position in view space. + */ export const getViewPosition = /*@__PURE__*/ Fn( ( [ screenPosition, depth, projectionMatrixInverse ], builder ) => { let clipSpacePosition; @@ -34,13 +37,14 @@ export const getViewPosition = /*@__PURE__*/ Fn( ( [ screenPosition, depth, proj } ); /** -* Computes a screen position expressed as uv coordinates based on a fragment's position in view space -* and the camera's projection matrix -* -* @param {vec3} viewPosition - The fragments position in view space. -* @param {mat4} projectionMatrix - The camera's projection matrix. -* @return {vec2} The fragment's screen position expressed as uv coordinates. -*/ + * Computes a screen position expressed as uv coordinates based on a fragment's position in view space + * and the camera's projection matrix + * + * @method + * @param {vec3} viewPosition - The fragments position in view space. + * @param {mat4} projectionMatrix - The camera's projection matrix. + * @return {vec2} The fragment's screen position expressed as uv coordinates. + */ export const getScreenPosition = /*@__PURE__*/ Fn( ( [ viewPosition, projectionMatrix ] ) => { const sampleClipPos = projectionMatrix.mul( vec4( viewPosition, 1.0 ) ); @@ -50,14 +54,15 @@ export const getScreenPosition = /*@__PURE__*/ Fn( ( [ viewPosition, projectionM } ); /** -* Computes a normal vector based on depth data. Can be used as a fallback when no normal render -* target is available or if flat surface normals are required. -* -* @param {vec2} uv - The texture coordinate. -* @param {DepthTexture} depthTexture - The depth texture. -* @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix. -* @return {vec3} The computed normal vector. -*/ + * Computes a normal vector based on depth data. Can be used as a fallback when no normal render + * target is available or if flat surface normals are required. + * + * @method + * @param {vec2} uv - The texture coordinate. + * @param {DepthTexture} depthTexture - The depth texture. + * @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix. + * @return {vec3} The computed normal vector. + */ export const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projectionMatrixInverse ] ) => { const size = textureSize( textureLoad( depthTexture ) ); diff --git a/utils/docs/jsdoc.config.json b/utils/docs/jsdoc.config.json new file mode 100644 index 00000000000000..76e9502895fd79 --- /dev/null +++ b/utils/docs/jsdoc.config.json @@ -0,0 +1,10 @@ +{ + "opts": { + "destination": "docs_new", + "encoding": "utf8", + "package": "package.json", + "recurse": true, + "template": "node_modules/clean-jsdoc-theme" + }, + "plugins": [ "plugins/markdown" ] +}