3 Commits

Author SHA1 Message Date
hikari 330c4946b8 feat: add table of contents and strip fCC directive syntax
Node.js CI / CI (push) Failing after 17s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 2m12s
2026-04-17 13:52:40 -07:00
hikari 99b5cb6935 fix: add puppeteer as dev dependency to resolve postinstall failure 2026-04-17 13:52:37 -07:00
hikari bc3bceded8 chore: replace .npmrc with pnpm-workspace.yaml
Node.js CI / CI (push) Failing after 23s
Security Scan and Upload / Security & DefectDojo Upload (push) Failing after 14m24s
2026-03-02 16:28:46 -08:00
5 changed files with 143 additions and 120 deletions
-25
View File
@@ -1,25 +0,0 @@
# Package Manager Configuration
# Force pnpm usage - breaks npm/yarn intentionally
node-linker=pnpm
# Security: Disable all lifecycle scripts
ignore-scripts=true
enable-pre-post-scripts=false
# Security: Require packages to be 10+ days old before installation
minimum-release-age=14400
# Security: Verify package integrity hashes
verify-store-integrity=true
# Security: Enforce strict trust policies
trust-policy=strict
# Security: Strict peer dependency resolution
strict-peer-dependencies=true
# Performance: Use symlinks for node_modules
symlink=true
# Lockfile: Ensure lockfile is not modified during install
frozen-lockfile=false
+2 -1
View File
@@ -18,8 +18,9 @@
"devDependencies": {
"@nhcarrigan/eslint-config": "5.2.0",
"@nhcarrigan/typescript-config": "4.0.0",
"@types/node": "25.2.3",
"@types/node": "24.7.0",
"eslint": "9.37.0",
"puppeteer": "24.40.0",
"tsx": "4.20.6",
"typescript": "5.9.3"
},
+76 -65
View File
@@ -14,16 +14,19 @@ importers:
devDependencies:
'@nhcarrigan/eslint-config':
specifier: 5.2.0
version: 5.2.0(@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(playwright@1.56.0)(react@19.2.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@25.2.3)(tsx@4.20.6))
version: 5.2.0(@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(playwright@1.56.0)(react@19.2.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@24.7.0)(tsx@4.20.6))
'@nhcarrigan/typescript-config':
specifier: 4.0.0
version: 4.0.0(typescript@5.9.3)
'@types/node':
specifier: 25.2.3
version: 25.2.3
specifier: 24.7.0
version: 24.7.0
eslint:
specifier: 9.37.0
version: 9.37.0
puppeteer:
specifier: 24.40.0
version: 24.40.0(typescript@5.9.3)
tsx:
specifier: 4.20.6
version: 4.20.6
@@ -313,8 +316,8 @@ packages:
resolution: {integrity: sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
'@puppeteer/browsers@2.10.10':
resolution: {integrity: sha512-3ZG500+ZeLql8rE0hjfhkycJjDj0pI/btEh3L9IkWUYcOrgP0xCNRq3HbtbqOPbvDhFaAWD88pDFtlLv8ns8gA==}
'@puppeteer/browsers@2.13.0':
resolution: {integrity: sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA==}
engines: {node: '>=18'}
hasBin: true
@@ -478,8 +481,8 @@ packages:
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
'@types/node@25.2.3':
resolution: {integrity: sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==}
'@types/node@24.7.0':
resolution: {integrity: sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw==}
'@types/normalize-package-data@2.4.4':
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
@@ -822,6 +825,7 @@ packages:
basic-ftp@5.0.5:
resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==}
engines: {node: '>=10.0.0'}
deprecated: Security vulnerability fixed in 5.2.1, please upgrade
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
@@ -900,8 +904,8 @@ packages:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
chromium-bidi@9.1.0:
resolution: {integrity: sha512-rlUzQ4WzIAWdIbY/viPShhZU2n21CxDUgazXVbw4Hu1MwaeUSEksSeM6DqPgpRjCLXRk702AVRxJxoOz0dw4OA==}
chromium-bidi@14.0.0:
resolution: {integrity: sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==}
peerDependencies:
devtools-protocol: '*'
@@ -1024,8 +1028,8 @@ packages:
resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
engines: {node: '>= 14'}
devtools-protocol@0.0.1508733:
resolution: {integrity: sha512-QJ1R5gtck6nDcdM+nlsaJXcelPEI7ZxSMw1ujHpO1c4+9l+Nue5qlebi9xO1Z2MGr92bFOQTW7/rrheh5hHxDg==}
devtools-protocol@0.0.1581282:
resolution: {integrity: sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ==}
dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
@@ -2024,12 +2028,12 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
puppeteer-core@24.23.0:
resolution: {integrity: sha512-yl25C59gb14sOdIiSnJ08XiPP+O2RjuyZmEG+RjYmCXO7au0jcLf7fRiyii96dXGUBW7Zwei/mVKfxMx/POeFw==}
puppeteer-core@24.40.0:
resolution: {integrity: sha512-MWL3XbUCfVgGR0gRsidzT6oKJT2QydPLhMITU6HoVWiiv4gkb6gJi3pcdAa8q4HwjBTbqISOWVP4aJiiyUJvag==}
engines: {node: '>=18'}
puppeteer@24.23.0:
resolution: {integrity: sha512-BVR1Lg8sJGKXY79JARdIssFWK2F6e1j+RyuJP66w4CUmpaXjENicmA3nNpUXA8lcTdDjAndtP+oNdni3T/qQqA==}
puppeteer@24.40.0:
resolution: {integrity: sha512-IxQbDq93XHVVLWHrAkFP7F7iHvb9o0mgfsSIMlhHb+JM+JjM1V4v4MNSQfcRWJopx9dsNOr9adYv0U5fm9BJBQ==}
engines: {node: '>=18'}
hasBin: true
@@ -2151,6 +2155,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
semver@7.7.4:
resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
engines: {node: '>=10'}
hasBin: true
serve-handler@6.1.6:
resolution: {integrity: sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==}
@@ -2437,8 +2446,8 @@ packages:
resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
engines: {node: '>= 0.4'}
typed-query-selector@2.12.0:
resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==}
typed-query-selector@2.12.1:
resolution: {integrity: sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA==}
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
@@ -2449,8 +2458,8 @@ packages:
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
engines: {node: '>= 0.4'}
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
undici-types@7.14.0:
resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==}
update-browserslist-db@1.1.3:
resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
@@ -2537,8 +2546,8 @@ packages:
jsdom:
optional: true
webdriver-bidi-protocol@0.3.6:
resolution: {integrity: sha512-mlGndEOA9yK9YAbvtxaPTqdi/kaCWYYfwrZvGzcmkr/3lWM+tQj53BxtpVd6qbC6+E5OnHXgCcAhre6AkXzxjA==}
webdriver-bidi-protocol@0.4.1:
resolution: {integrity: sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==}
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
@@ -2581,8 +2590,8 @@ packages:
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
ws@8.18.3:
resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
ws@8.20.0:
resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
@@ -2794,7 +2803,7 @@ snapshots:
'@jridgewell/sourcemap-codec@1.5.5': {}
'@nhcarrigan/eslint-config@5.2.0(@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(playwright@1.56.0)(react@19.2.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@25.2.3)(tsx@4.20.6))':
'@nhcarrigan/eslint-config@5.2.0(@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(playwright@1.56.0)(react@19.2.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@24.7.0)(tsx@4.20.6))':
dependencies:
'@eslint-community/eslint-plugin-eslint-comments': 4.4.1(eslint@9.37.0)
'@eslint/compat': 1.2.4(eslint@9.37.0)
@@ -2803,7 +2812,7 @@ snapshots:
'@stylistic/eslint-plugin': 2.12.1(eslint@9.37.0)(typescript@5.9.3)
'@typescript-eslint/eslint-plugin': 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3)
'@typescript-eslint/parser': 8.19.0(eslint@9.37.0)(typescript@5.9.3)
'@vitest/eslint-plugin': 1.1.24(@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@25.2.3)(tsx@4.20.6))
'@vitest/eslint-plugin': 1.1.24(@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@24.7.0)(tsx@4.20.6))
eslint: 9.37.0
eslint-plugin-deprecation: 3.0.0(eslint@9.37.0)(typescript@5.9.3)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.19.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)
@@ -2816,7 +2825,7 @@ snapshots:
playwright: 1.56.0
react: 19.2.0
typescript: 5.9.3
vitest: 3.2.4(@types/node@25.2.3)(tsx@4.20.6)
vitest: 3.2.4(@types/node@24.7.0)(tsx@4.20.6)
transitivePeerDependencies:
- '@typescript-eslint/utils'
- eslint-import-resolver-typescript
@@ -2841,13 +2850,13 @@ snapshots:
'@pkgr/core@0.1.2': {}
'@puppeteer/browsers@2.10.10':
'@puppeteer/browsers@2.13.0':
dependencies:
debug: 4.4.3
extract-zip: 2.0.1
progress: 2.0.3
proxy-agent: 6.5.0
semver: 7.7.2
semver: 7.7.4
tar-fs: 3.1.1
yargs: 17.7.2
transitivePeerDependencies:
@@ -2957,15 +2966,15 @@ snapshots:
'@types/json5@0.0.29': {}
'@types/node@25.2.3':
'@types/node@24.7.0':
dependencies:
undici-types: 7.16.0
undici-types: 7.14.0
'@types/normalize-package-data@2.4.4': {}
'@types/yauzl@2.10.3':
dependencies:
'@types/node': 25.2.3
'@types/node': 24.7.0
optional: true
'@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3)':
@@ -3135,13 +3144,13 @@ snapshots:
'@typescript-eslint/types': 8.46.0
eslint-visitor-keys: 4.2.1
'@vitest/eslint-plugin@1.1.24(@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@25.2.3)(tsx@4.20.6))':
'@vitest/eslint-plugin@1.1.24(@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@24.7.0)(tsx@4.20.6))':
dependencies:
'@typescript-eslint/utils': 8.46.0(eslint@9.37.0)(typescript@5.9.3)
eslint: 9.37.0
optionalDependencies:
typescript: 5.9.3
vitest: 3.2.4(@types/node@25.2.3)(tsx@4.20.6)
vitest: 3.2.4(@types/node@24.7.0)(tsx@4.20.6)
'@vitest/expect@3.2.4':
dependencies:
@@ -3151,13 +3160,13 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
'@vitest/mocker@3.2.4(vite@7.1.9(@types/node@25.2.3)(tsx@4.20.6))':
'@vitest/mocker@3.2.4(vite@7.1.9(@types/node@24.7.0)(tsx@4.20.6))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.19
optionalDependencies:
vite: 7.1.9(@types/node@25.2.3)(tsx@4.20.6)
vite: 7.1.9(@types/node@24.7.0)(tsx@4.20.6)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -3460,9 +3469,9 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
chromium-bidi@9.1.0(devtools-protocol@0.0.1508733):
chromium-bidi@14.0.0(devtools-protocol@0.0.1581282):
dependencies:
devtools-protocol: 0.0.1508733
devtools-protocol: 0.0.1581282
mitt: 3.0.1
zod: 3.25.76
@@ -3578,7 +3587,7 @@ snapshots:
escodegen: 2.1.0
esprima: 4.0.1
devtools-protocol@0.0.1508733: {}
devtools-protocol@0.0.1581282: {}
dir-glob@3.0.1:
dependencies:
@@ -4514,7 +4523,7 @@ snapshots:
iconv-lite: 0.6.3
listr: 0.14.3
marked: 4.3.0
puppeteer: 24.23.0(typescript@5.9.3)
puppeteer: 24.40.0(typescript@5.9.3)
semver: 7.7.2
serve-handler: 6.1.6
transitivePeerDependencies:
@@ -4770,15 +4779,15 @@ snapshots:
punycode@2.3.1: {}
puppeteer-core@24.23.0:
puppeteer-core@24.40.0:
dependencies:
'@puppeteer/browsers': 2.10.10
chromium-bidi: 9.1.0(devtools-protocol@0.0.1508733)
'@puppeteer/browsers': 2.13.0
chromium-bidi: 14.0.0(devtools-protocol@0.0.1581282)
debug: 4.4.3
devtools-protocol: 0.0.1508733
typed-query-selector: 2.12.0
webdriver-bidi-protocol: 0.3.6
ws: 8.18.3
devtools-protocol: 0.0.1581282
typed-query-selector: 2.12.1
webdriver-bidi-protocol: 0.4.1
ws: 8.20.0
transitivePeerDependencies:
- bare-buffer
- bufferutil
@@ -4786,14 +4795,14 @@ snapshots:
- supports-color
- utf-8-validate
puppeteer@24.23.0(typescript@5.9.3):
puppeteer@24.40.0(typescript@5.9.3):
dependencies:
'@puppeteer/browsers': 2.10.10
chromium-bidi: 9.1.0(devtools-protocol@0.0.1508733)
'@puppeteer/browsers': 2.13.0
chromium-bidi: 14.0.0(devtools-protocol@0.0.1581282)
cosmiconfig: 9.0.0(typescript@5.9.3)
devtools-protocol: 0.0.1508733
puppeteer-core: 24.23.0
typed-query-selector: 2.12.0
devtools-protocol: 0.0.1581282
puppeteer-core: 24.40.0
typed-query-selector: 2.12.1
transitivePeerDependencies:
- bare-buffer
- bufferutil
@@ -4948,6 +4957,8 @@ snapshots:
semver@7.7.2: {}
semver@7.7.4: {}
serve-handler@6.1.6:
dependencies:
bytes: 3.0.0
@@ -5301,7 +5312,7 @@ snapshots:
possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10
typed-query-selector@2.12.0: {}
typed-query-selector@2.12.1: {}
typescript@5.9.3: {}
@@ -5312,7 +5323,7 @@ snapshots:
has-symbols: 1.1.0
which-boxed-primitive: 1.1.1
undici-types@7.16.0: {}
undici-types@7.14.0: {}
update-browserslist-db@1.1.3(browserslist@4.26.3):
dependencies:
@@ -5329,13 +5340,13 @@ snapshots:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
vite-node@3.2.4(@types/node@25.2.3)(tsx@4.20.6):
vite-node@3.2.4(@types/node@24.7.0)(tsx@4.20.6):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 7.1.9(@types/node@25.2.3)(tsx@4.20.6)
vite: 7.1.9(@types/node@24.7.0)(tsx@4.20.6)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -5350,7 +5361,7 @@ snapshots:
- tsx
- yaml
vite@7.1.9(@types/node@25.2.3)(tsx@4.20.6):
vite@7.1.9(@types/node@24.7.0)(tsx@4.20.6):
dependencies:
esbuild: 0.25.10
fdir: 6.5.0(picomatch@4.0.3)
@@ -5359,15 +5370,15 @@ snapshots:
rollup: 4.52.4
tinyglobby: 0.2.15
optionalDependencies:
'@types/node': 25.2.3
'@types/node': 24.7.0
fsevents: 2.3.3
tsx: 4.20.6
vitest@3.2.4(@types/node@25.2.3)(tsx@4.20.6):
vitest@3.2.4(@types/node@24.7.0)(tsx@4.20.6):
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@25.2.3)(tsx@4.20.6))
'@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@24.7.0)(tsx@4.20.6))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -5385,11 +5396,11 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 7.1.9(@types/node@25.2.3)(tsx@4.20.6)
vite-node: 3.2.4(@types/node@25.2.3)(tsx@4.20.6)
vite: 7.1.9(@types/node@24.7.0)(tsx@4.20.6)
vite-node: 3.2.4(@types/node@24.7.0)(tsx@4.20.6)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 25.2.3
'@types/node': 24.7.0
transitivePeerDependencies:
- jiti
- less
@@ -5404,7 +5415,7 @@ snapshots:
- tsx
- yaml
webdriver-bidi-protocol@0.3.6: {}
webdriver-bidi-protocol@0.4.1: {}
which-boxed-primitive@1.1.1:
dependencies:
@@ -5471,7 +5482,7 @@ snapshots:
wrappy@1.0.2: {}
ws@8.18.3: {}
ws@8.20.0: {}
y18n@5.0.8: {}
+21
View File
@@ -0,0 +1,21 @@
# Security
# Do not execute any scripts of installed packages (project scripts still run)
ignoreDepScripts: true
# Do not automatically run pre/post scripts (e.g. preinstall, postbuild)
enablePrePostScripts: false
# Only allow packages published at least 10 days ago (reduces risk of compromised packages)
minimumReleaseAge: 14400
# Fail if a package's trust level has decreased compared to previous releases
trustPolicy: no-downgrade
# Ignore trust policy for packages published more than 1 year ago (predates provenance signing)
trustPolicyIgnoreAfter: 525960
# Fail if there are missing or invalid peer dependencies
strictPeerDependencies: true
# Prevent transitive dependencies from using exotic sources (git repos, direct tarball URLs)
blockExoticSubdeps: true
# Lockfile
# Allow the lockfile to be updated during install (set to true in CI for stricter reproducibility)
preferFrozenLockfile: false
+44 -29
View File
@@ -4,13 +4,7 @@
* @author Naomi Carrigan
*/
import {
readFile,
appendFile,
writeFile,
readdir,
unlink,
} from "node:fs/promises";
import { readFile, writeFile, readdir, unlink } from "node:fs/promises";
import { join } from "node:path";
import { mdToPdf } from "md-to-pdf";
import order from "../data/order.json" assert { type: "json" };
@@ -46,38 +40,59 @@ const sortFiles = (a: string, b: string): number => {
return aIndex - bIndex;
};
interface FileEntry {
body: string;
title: string;
}
const slugify = (text: string): string => {
return text.
toLowerCase().
replaceAll(/[^\w\s-]/gu, "").
replaceAll(/\s+/gu, "-");
};
const processFile = async(file: string): Promise<FileEntry> => {
const content = await readFile(file, "utf8");
const titleMatch = /^title: (?<title>.*)/mu.exec(content);
const title = titleMatch?.groups?.title ?? "Unknown";
const body = content.
replace(/^---\n[\S\s]*?\n---\n/u, "").
trim().
replace(/^#+ --.*--/u, "").
trim().
replaceAll(/^:::.*$/gmu, "").
trim();
return { body, title };
};
const rollupFiles = async(
inputDirectory: string,
outputFile: string,
): Promise<void> => {
try {
console.log("Process started...");
await writeFile(outputFile, `${starterText}\n`);
console.log("Reading content directory...");
const unsortedFiles = await readDirectoryRecursively(inputDirectory);
console.log(unsortedFiles);
const files = unsortedFiles.toSorted(sortFiles);
console.log("Files found, processing...");
for (const file of files) {
if (file === ".gitkeep") {
continue;
}
if (file.endsWith(".md")) {
const content = await readFile(file, "utf8");
const strippedFrontmatter = content.
replace(/^---\n[\S\s]*?\n---\n/, "").
trim();
// Title is in front matter
const title = /^title: (?<title>.*)/m.exec(content)?.groups?.title;
const strippedFccHeadings = strippedFrontmatter.
replace(/^#+ --.*--/, "").
trim();
await appendFile(
outputFile,
`---\n\n# ${title ?? "Unknown"}\n${strippedFccHeadings}\n\n`,
);
}
}
const mdFiles = files.filter((file) => {
return file.endsWith(".md");
});
const entries = await Promise.all(
mdFiles.map(async(file) => {
return await processFile(file);
}),
);
const tocLines = entries.map(({ title }) => {
return `- [${title}](#${slugify(title)})`;
});
const toc = `## Table of Contents\n\n${tocLines.join("\n")}\n\n---`;
const sections = entries.map(({ body, title }) => {
return `---\n\n# ${title}\n\n${body}\n\n`;
});
await writeFile(outputFile, `${starterText}\n${toc}\n\n${sections.join("")}`);
console.log(`Successfully rolled up files into ${outputFile}`);
} catch (error) {
console.error("Error rolling up files:", error);