{"_id":"@domstack/static","_rev":"12-0a6e695112c440384ef47eb0ced5b3ed","name":"@domstack/static","dist-tags":{"beta":"11.0.0-beta.7","latest":"11.0.3"},"versions":{"11.0.0-beta.0":{"name":"@domstack/static","version":"11.0.0-beta.0","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0-beta.0","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"e7f95a4308a46b1a64dc39a0c5613de9b2224f15","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0-beta.0.tgz","fileCount":373,"integrity":"sha512-M3jRdAglFoDpaSMRmfMe5IWdfeZjv+PZKZKB1786eFMOiyZPXNuV/CTjQAEcrB2YCkG8OhcLVD6e0Hs4QQbD/w==","signatures":[{"sig":"MEQCIC/dVF6CemF+bq4gRLWk1BCRSJ1ZXSJE5gQoO4GhQvolAiAqUPwYpNJrTLH1SVY9RE/LmhUi+xmL7fi9DRHKozBU1A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2104904},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"5a7274111642e6dfe9352b2f81055d6d1cda9821","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.4.2","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.25.0","js-yaml":"^4.1.0","chokidar":"^4.0.0","mine.css":"^10.0.0","read-pkg":"^9.0.1","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^0.9.0"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.8.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^15.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0-beta.0_1753031022265_0.6341736802725233","host":"s3://npm-registry-packages-npm-production"}},"11.0.0-beta.1":{"name":"@domstack/static","version":"11.0.0-beta.1","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0-beta.1","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"4fd09c684cf32debbdd5244071e7ec8a6d170b93","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0-beta.1.tgz","fileCount":379,"integrity":"sha512-njqfg7YMPKEn3fZHWGYS4zcuimhbSm39fLqJZCORGyoxghBKMcEAG2Ahqw6UpQDuIJdkBYzGYExw3+xkb9Aoug==","signatures":[{"sig":"MEYCIQCcQHI6eZh53ka9Z3F7zMgWzq6fgXlAqj763ggw2qUnLgIhAPhwlYOcRtynF9flu+wrxbLlnOTE/P30Qw8ktzHaTac1","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2312540},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"2fd3a2b853e981b9942601c47fd48a41357398af","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.5.1","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.5.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.25.0","js-yaml":"^4.1.0","chokidar":"^4.0.0","mine.css":"^10.0.0","read-pkg":"^9.0.1","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^0.9.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.8.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^15.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0-beta.1_1755388475328_0.5627420119324968","host":"s3://npm-registry-packages-npm-production"}},"11.0.0-beta.2":{"name":"@domstack/static","version":"11.0.0-beta.2","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0-beta.2","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"822e796481d4cb09ba754537a920dc030b48c4c6","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0-beta.2.tgz","fileCount":379,"integrity":"sha512-G0YFgFdKaqjpcfKiylJvNmxjmi1EiNhmyjLdETRlaedoSQU6KQeTiTxYyIUkW6ygVOaqHgKTYzWV4R/wLDWiGg==","signatures":[{"sig":"MEUCIQDJbhDbWJVWmJ6B3+3I3KgTy2Z76NzPW+N5IMgfB9wrRgIgAmxpzDxGHVt8TK0KKQzjkfNRMEDdho1XMbjK1ZiES+w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2316903},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"83a685839a009c96daa65afdd60f69c87cbb42b7","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.5.1","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.5.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.25.0","js-yaml":"^4.1.0","chokidar":"^4.0.0","mine.css":"^10.0.0","read-pkg":"^9.0.1","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^0.9.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.8.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^15.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0-beta.2_1755391714445_0.7499531810931503","host":"s3://npm-registry-packages-npm-production"}},"11.0.0-beta.3":{"name":"@domstack/static","version":"11.0.0-beta.3","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0-beta.3","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"425f4acfbf27c344a54c649db600bdfa06a3e4d2","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0-beta.3.tgz","fileCount":379,"integrity":"sha512-gM1VtqDCi4nS6fE9SNKV8RnHKQl15SsQxCQpPuaRYjTYSemnbNGhibvF3vqrPD0OlHN1OluE+p1Hrjtm4RNCjw==","signatures":[{"sig":"MEQCIDVRWC1diUM84yOu1AvcAkezyH9UCRD8dNmDbhl45RVkAiA3CEv+KU/AlD9NhMYo/G4WRunEF7I1xXSVJSexbOpVUA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2318734},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"f3fe3a6a2f526c521489e19a826a0e581f4198c2","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.5.1","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.5.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.25.0","js-yaml":"^4.1.0","chokidar":"^4.0.0","mine.css":"^10.0.0","read-pkg":"^9.0.1","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^0.9.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.8.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^15.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0-beta.3_1755391878256_0.5859206546845472","host":"s3://npm-registry-packages-npm-production"}},"11.0.0-beta.4":{"name":"@domstack/static","version":"11.0.0-beta.4","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0-beta.4","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"a613b29e1b10a648900b9fa95f4f6fe87b8e97e9","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0-beta.4.tgz","fileCount":379,"integrity":"sha512-pfaA6/FRKdbV97uZgILSXaKOvtE5ky75XZP35R8h2CLwu5g71Tnm2HDSQEnCN5tIwFL1HygqhQqmsuJ6rpT9bg==","signatures":[{"sig":"MEUCIQDXlBEm7pG1OiomXWGCzyghCRYj52CJKMw7XNWVuUXfDAIgWyEeciplN7JvahNUTzZ4sCdJ4tulF5flh2anLQlKIsI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2319367},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"2e7e94efbc8fbdf287c89e1386bfeb3d6be4149f","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.5.1","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.5.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.25.0","js-yaml":"^4.1.0","chokidar":"^4.0.0","mine.css":"^10.0.0","read-pkg":"^9.0.1","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^0.9.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.8.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^15.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0-beta.4_1755392084889_0.8662397087238856","host":"s3://npm-registry-packages-npm-production"}},"11.0.0-beta.5":{"name":"@domstack/static","version":"11.0.0-beta.5","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0-beta.5","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"79c6bbe28774a32bfefac88ac5f8ac81e94ec32e","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0-beta.5.tgz","fileCount":379,"integrity":"sha512-IgMTppkedg0Djxp+33MF5wvyNrLwtspQqgd42spwiGyTxGrx9FE1NJCdzb9Ee1FGd2VvslSafpRoqrjYjZKZDw==","signatures":[{"sig":"MEYCIQCPbgFhVqpdU16WvbLoChsS5QrOFCC5yUMG3Lx0pRz1PAIhAPVl8mdkaUWQlKwrTj7FjaaT9skZmMugUBaf/jAsxHM8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2319680},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"a91b488052f2da6ca2e661f4dd375bff42847dca","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.5.1","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.5.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.25.0","js-yaml":"^4.1.0","chokidar":"^4.0.0","mine.css":"^10.0.0","read-pkg":"^9.0.1","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^0.9.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.8.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^15.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0-beta.5_1755393566127_0.46243156461704094","host":"s3://npm-registry-packages-npm-production"}},"11.0.0-beta.6":{"name":"@domstack/static","version":"11.0.0-beta.6","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0-beta.6","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"40e4db5f057bac2b3a415630f8635998c138d518","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0-beta.6.tgz","fileCount":379,"integrity":"sha512-4XThqfFGhfbveyIhA0rcv1UVJAAKSZ5Oz5W8/iIpyXABv09A55N9HwltolbEn/MJdeaj+lEasjcZwdhIGEFlMw==","signatures":[{"sig":"MEUCIGC/tfHCJc+n+sJp5obEW1NN8ZGNVs5KuTFVQSjQc5eIAiEA+y3RPBBcRxPvOw/9adF8lI3nqKJ5khJM9xvVIqufzsA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2322448},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"0c52f39d7eb72fba5aaa4badb7788fbaa66eb874","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.5.1","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.5.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.25.0","js-yaml":"^4.1.0","chokidar":"^4.0.0","mine.css":"^10.0.0","read-pkg":"^9.0.1","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^0.9.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.9.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^16.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0-beta.6_1755456034077_0.3344557662537482","host":"s3://npm-registry-packages-npm-production"}},"11.0.0-beta.7":{"name":"@domstack/static","version":"11.0.0-beta.7","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0-beta.7","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"35e7811eaf57cd67f6fa5b434974fceda2e86af0","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0-beta.7.tgz","fileCount":379,"integrity":"sha512-NzH2LHHC7ORiy39v+w4b2uJvbldZvptktBNVVWdS223vOpWXu5/7ItQ0tbmZF19mH3e6Tj7T0CLJNjMxfHOzPQ==","signatures":[{"sig":"MEUCIQCiEucpydRr56sTPDDzS6zZuSkmQhR2xHFL0eMqm8yuRAIgLxVA/yGsT5IYH5VkXBXDvCZuXUOOwJ5ADKJMIeKSL04=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2330940},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"0b3b80f7e53c28d1865439adb09b3dfb0cfed71b","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.5.1","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.5.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.25.0","js-yaml":"^4.1.0","chokidar":"^4.0.0","mine.css":"^10.0.0","read-pkg":"^9.0.1","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^0.9.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.9.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^16.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0-beta.7_1755463006429_0.5962865070491616","host":"s3://npm-registry-packages-npm-production"}},"11.0.0":{"name":"@domstack/static","version":"11.0.0","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.0","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"acbbb12b328605c6ae6bc57dd56666ab410c26f7","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.0.tgz","fileCount":416,"integrity":"sha512-E2E/BtiXTy2R3JPqq9sIfYzX6IM13pffKdSRvlJTgdUS1vAXY3PhFBfJFvDYVZqlDuy+eamkwQqirI31U2X2jQ==","signatures":[{"sig":"MEUCIQCe8boXqNTpuKafJ3JcboSvMDurtiQlqkdRrYUab3rzyQIgeeKZ5pu2azJYHQQUHhk0Lr4MTv6DxjXYb1LvR9hYOHc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2437951},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"6961b22880a44e24caa8526375f123184b75fe2e","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.6.2","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.27.1","js-yaml":"^4.1.0","chokidar":"^5.0.0","mine.css":"^10.0.0","read-pkg":"^10.0.0","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^1.1.0","@11ty/dependency-tree-typescript":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.9.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^16.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.0_1771693411423_0.9333615517220657","host":"s3://npm-registry-packages-npm-production"}},"11.0.1":{"name":"@domstack/static","version":"11.0.1","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.1","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"788714f86bdab5be10c2e9ce3b7bdffdd63d0bd4","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.1.tgz","fileCount":416,"integrity":"sha512-as8jYXxGeeP87R7940LOiTCWL7CnojcEMs3aFXH4KAZqKAbYd6Gambc2AzI+AngCwgzUTvEpCJ5j3qpE5YY1zA==","signatures":[{"sig":"MEYCIQD4TD7sB+J2YjQ8n2XLnyLa2JIChbEkXClcH+t3d1fSjQIhANBc3BG+JOZRiZhv+Bh2yNOmIlG2WkGX8FvIii1zxHEQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2438144},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"b8e36151c3fa88ce145ca24c6246439811a357c9","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.6.2","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.27.1","js-yaml":"^4.1.0","chokidar":"^5.0.0","mine.css":"^10.0.0","read-pkg":"^10.0.0","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^1.1.0","@11ty/dependency-tree-typescript":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.9.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^16.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.1_1771693598377_0.6646631450160958","host":"s3://npm-registry-packages-npm-production"}},"11.0.2":{"name":"@domstack/static","version":"11.0.2","keywords":[],"author":{"url":"https://bret.io","name":"Bret Comnes","email":"bcomnes@gmail.com"},"license":"MIT","_id":"@domstack/static@11.0.2","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"homepage":"https://github.com/bcomnes/domstack","bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"bin":{"dom":"bin.js","domstack":"bin.js"},"dist":{"shasum":"4fbfc7bcfcdc0de323b1ec5f948f085da5b8157c","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.2.tgz","fileCount":417,"integrity":"sha512-pAAgDNBe5lJP5uNZSCKva2kAHE72tmLQ6Z9qePHBrNIZ6p0TWPjY71bMDdkv+rRiDoS0fQoR1qRNeddjPc9prA==","signatures":[{"sig":"MEUCIB/YP3nbOU8KJSAL9rHtMuPHjPUM61UdXmv2NnZqbQlHAiEAiQw/hlOqkig36qDWmv5TyT0QmiNa86t/BTWoKCMYdDo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2439964},"main":"./index.js","type":"module","types":"index.d.ts","engines":{"node":">=22.0.0"},"funding":{"url":"https://github.com/sponsors/bcomnes","type":"individual"},"gitHead":"6a6d7628faacc51300c00452f19cc32b5e2862bb","scripts":{"test":"npm run clean && run-s test:*","build":"npm run clean && run-p build:*","clean":"run-p clean:*","start":"npm run watch","watch":"npm run clean && run-p watch:*","version":"run-s version:*","test:tsc":"tsc","postpublish":"npm run clean","version:git":"git add CHANGELOG.md","clean:public":"rm -rf public && mkdir -p public","example:basic":"cd examples/basic && npm i && npm run build","build-examples":"run-p example:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","watch:domstack":"npm run build:domstack -- --watch","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","build:declaration":"tsc -p declaration.tsconfig.json","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","test:installed-check":"installed-check --ignore-dev","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build"},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"repository":{"url":"git+https://github.com/bcomnes/domstack.git","type":"git"},"_npmVersion":"11.6.2","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"htm":"^3.1.1","cpx2":"^8.0.0","p-map":"^7.0.2","ignore":"^7.0.0","preact":"^10.26.6","pretty":"^2.0.0","esbuild":"^0.27.1","js-yaml":"^4.1.0","chokidar":"^5.0.0","mine.css":"^10.0.0","read-pkg":"^10.0.0","argsclopts":"^1.0.4","clean-deep":"^3.4.0","handlebars":"^4.7.8","make-array":"^1.0.5","markdown-it":"^14.1.0","pretty-tree":"^1.0.0","browser-sync":"^3.0.2","highlight.js":"^11.9.0","package-json":"^10.0.0","write-package":"^7.0.1","markdown-it-ins":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-abbr":"^2.0.0","markdown-it-mark":"^4.0.0","markdown-it-attrs":"^4.1.6","markdown-it-emoji":"^3.0.0","package-directory":"^8.1.0","markdown-it-anchor":"^9.0.1","async-folder-walker":"^3.0.5","markdown-it-deflist":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-task-lists":"^2.1.1","markdown-it-highlightjs":"^4.1.0","preact-render-to-string":"^6.5.13","markdown-it-table-of-contents":"^1.1.0","@11ty/dependency-tree-typescript":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","gh-release":"^7.0.2","typescript":"~5.9.2","@types/node":"^24.0.1","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","@types/js-yaml":"^4.0.9","auto-changelog":"^2.4.0","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","@types/markdown-it":"^14.1.1","@voxpelli/tsconfig":"^16.0.0","@types/browser-sync":"^2.29.0","@types/markdown-it-footnote":"^3.0.4"},"_npmOperationalInternal":{"tmp":"tmp/static_11.0.2_1771694866717_0.10010232933975449","host":"s3://npm-registry-packages-npm-production"}},"11.0.3":{"name":"@domstack/static","description":"@domstack/static: a traditional web bakery made with html, md, css and js.","version":"11.0.3","type":"module","main":"./index.js","types":"index.d.ts","bin":{"domstack":"bin.js","dom":"bin.js"},"author":{"name":"Bret Comnes","email":"bcomnes@gmail.com","url":"https://bret.io"},"bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"engines":{"node":">=22.0.0"},"dependencies":{"@11ty/dependency-tree-typescript":"^1.0.0","argsclopts":"^1.0.4","async-folder-walker":"^3.0.5","browser-sync":"^3.0.2","chokidar":"^5.0.0","clean-deep":"^3.4.0","cpx2":"^8.0.0","esbuild":"^0.27.1","handlebars":"^4.7.8","highlight.js":"^11.9.0","htm":"^3.1.1","ignore":"^7.0.0","js-yaml":"^4.1.0","make-array":"^1.0.5","markdown-it":"^14.1.0","markdown-it-abbr":"^2.0.0","markdown-it-anchor":"^9.0.1","markdown-it-attrs":"^4.1.6","markdown-it-deflist":"^3.0.0","markdown-it-emoji":"^3.0.0","markdown-it-footnote":"^4.0.0","markdown-it-highlightjs":"^4.1.0","markdown-it-ins":"^4.0.0","markdown-it-mark":"^4.0.0","markdown-it-sub":"^2.0.0","markdown-it-sup":"^2.0.0","markdown-it-table-of-contents":"^1.1.0","markdown-it-task-lists":"^2.1.1","mine.css":"^10.0.0","p-map":"^7.0.2","package-directory":"^8.1.0","package-json":"^10.0.0","preact":"^10.26.6","preact-render-to-string":"^6.5.13","pretty":"^2.0.0","pretty-tree":"^1.0.0","read-pkg":"^10.0.0","write-package":"^7.0.1"},"devDependencies":{"c8":"^10.0.0","cheerio":"^1.0.0-rc.10","@types/browser-sync":"^2.29.0","@types/js-yaml":"^4.0.9","@types/markdown-it":"^14.1.1","@types/markdown-it-footnote":"^3.0.4","@types/node":"^24.0.1","@voxpelli/tsconfig":"^16.0.0","auto-changelog":"^2.4.0","gh-release":"^7.0.2","installed-check":"^9.3.0","jsonfeed-to-atom":"^1.2.5","neostandard":"^0.12.0","npm-run-all2":"^8.0.1","typescript":"~5.9.2"},"homepage":"https://github.com/bcomnes/domstack","keywords":[],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bcomnes/domstack.git"},"scripts":{"prepublishOnly":"npm run build && git push --follow-tags && gh-release -y","postpublish":"npm run clean","version":"run-s version:*","version:changelog":"auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:'","version:git":"git add CHANGELOG.md","test":"npm run clean && run-s test:*","test:installed-check":"installed-check --ignore-dev","test:neostandard":"eslint . --ignore-pattern 'test-cases/build-errors/src/**/*.js' --ignore-pattern 'test-cases/page-build-errors/src/**/*.js'","test:node-test":"c8 --reporter=lcov --reporter=text node --test --test-reporter spec","test:tsc":"tsc","build-examples":"run-p example:*","clean":"run-p clean:*","clean:public":"rm -rf public && mkdir -p public","clean:declarations-top":"rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')","clean:declarations-lib":"rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')","clean-node_modules":"rm -rf node_modules && rm -rf examples/*/node_modules","build":"npm run clean && run-p build:*","build:domstack":"./bin.js --src . --ignore examples,test-cases,coverage,*.tsconfig.json,fonts","build:declaration":"tsc -p declaration.tsconfig.json","watch":"npm run clean && run-p watch:*","watch:domstack":"npm run build:domstack -- --watch","example:basic":"cd examples/basic && npm i && npm run build","example:string-layouts":"cd examples/string-layouts && npm i --production && npm run build","example:default-layout":"cd examples/default-layout && npm i --production && npm run build","example:nested-dest":"cd examples/nested-dest && npm i --production && npm run build","example:uhtml-isomorphic":"cd examples/uhtml-isomorphic && npm i --production && npm run build","start":"npm run watch"},"funding":{"type":"individual","url":"https://github.com/sponsors/bcomnes"},"gitHead":"e398fab0774670546be97a4c4731cbea4fba3e31","_id":"@domstack/static@11.0.3","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-ES1SCpueuI8/tKrAginzT5+Wt8IXvyh2e+G3C2lVrx3UzUpItj1LBTOAc9HDAa/gBDsSTFZQC2PILRsIbRXSZA==","shasum":"e224b829f97273d2eda3b657d2446d9e7be4e8f1","tarball":"https://registry.npmjs.org/@domstack/static/-/static-11.0.3.tgz","fileCount":417,"unpackedSize":2439820,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBQuGBbI4H/9Gm9LxJ6R9EPjskySaWYsGzrRqTJbjFDxAiEAxY6Gpn80Wn04Xg2Best/xhUsNi0aIgcNEj4GapdLnoU="}]},"_npmUser":{"name":"bret","email":"bcomnes@gmail.com"},"directories":{},"maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/static_11.0.3_1771698233078_0.00861074268647255"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-20T17:03:42.195Z","modified":"2026-02-21T18:23:53.475Z","11.0.0-beta.0":"2025-07-20T17:03:42.545Z","11.0.0-beta.1":"2025-08-16T23:54:35.595Z","11.0.0-beta.2":"2025-08-17T00:48:34.687Z","11.0.0-beta.3":"2025-08-17T00:51:18.486Z","11.0.0-beta.4":"2025-08-17T00:54:45.126Z","11.0.0-beta.5":"2025-08-17T01:19:26.378Z","11.0.0-beta.6":"2025-08-17T18:40:34.355Z","11.0.0-beta.7":"2025-08-17T20:36:46.708Z","11.0.0":"2026-02-21T17:03:31.661Z","11.0.1":"2026-02-21T17:06:38.641Z","11.0.2":"2026-02-21T17:27:46.943Z","11.0.3":"2026-02-21T18:23:53.328Z"},"bugs":{"url":"https://github.com/bcomnes/domstack/issues"},"author":{"name":"Bret Comnes","email":"bcomnes@gmail.com","url":"https://bret.io"},"license":"MIT","homepage":"https://github.com/bcomnes/domstack","keywords":[],"repository":{"type":"git","url":"git+https://github.com/bcomnes/domstack.git"},"description":"@domstack/static: a traditional web bakery made with html, md, css and js.","maintainers":[{"name":"bret","email":"bcomnes@gmail.com"}],"readme":"# domstack\n[![npm version](https://img.shields.io/npm/v/@domstack/static.svg)](https://npmjs.org/package/@domstack/static)\n[![Actions Status](https://github.com/bcomnes/domstack/workflows/tests/badge.svg)](https://github.com/bcomnes/domstack/actions)\n[![Coverage Status](https://coveralls.io/repos/github/bcomnes/domstack/badge.svg?branch=master)](https://coveralls.io/github/bcomnes/domstack?branch=master)\n[![Types in JS](https://img.shields.io/badge/types_in_js-yes-brightgreen)](https://github.com/voxpelli/types-in-js)\n[![Neocities][neocities-img]](https://domstack.net)\n\n`domstack`: Cut the [gordian knot](https://en.wikipedia.org/wiki/Gordian_Knot) of modern web development and build websites with a stack of html, md, css, ts, tsx, (and/or js/jsx).\n\nDOMStack provides a few project conventions around esbuild ande Node.js that lets you quickly, cleanly and easily build websites and web apps using all of your favorite technolgies without any framework specific impurities, unlocking the web platform as a freeform canvas.\n\nIt's fast to learn, quick to build with, and performs better than you are used to.\n\n`domstack` currently ships a static site generator tool which is great for building static wesbites, and static PWA/MPAs.\nThere is an experimental fastify plugin in the works that will unlock dynamic hypermedia webapps using the same project structure.\n\n```console\nnpm install @domstack/static\n```\n\n- 🌎 [domstack docs website](https://domstack.net)\n- 💬 [Discord Chat](https://discord.gg/AVTsPRGeR9)\n- 📢 [v11 - top-bun is now domstack](./docs/v11-migration.md)\n- 📢 [v7 Announcement](https://bret.io/blog/2023/reintroducing-top-bun/)\n- 📘 [Full TypeScript Support](#typescript-support)\n\n## Migrating from top-bun\n\ndomstack v11 is a major release that renames the project from `top-bun` to `@domstack/static`. The full migration guide is at [docs/v11-migration.md](docs/v11-migration.md). Key changes at a glance:\n\n- **Package**: `top-bun` → `@domstack/static`\n- **CLI**: `top-bun`/`tb` → `domstack`/`dom`\n- **Programmatic API**: `TopBun` class → `DomStack`, all `TopBun*` types/errors/warnings renamed to `DomStack*`\n- **`postVars` removed**: migrate `postVars` exports from `page.vars.js` files to a single `global.data.js` with a default export\n- **New reserved filenames**: `global.data.js`, `markdown-it.settings.js`, `page.md`, `*.worker.{js,ts}` are now special — rename any colliding files\n- **Default layout**: switched from `uhtml-isomorphic` to `preact`; add `uhtml-isomorphic` to your own deps if you import it directly\n- **Output paths**: `top-bun-esbuild-meta.json` → `domstack-esbuild-meta.json`, `top-bun-defaults/` → `domstack-defaults/`\n- **Conflict now throws**: using both `browser` in `global.vars.js` and `define` in `esbuild.settings.js` is now a hard error\n\nSee [docs/v11-migration.md](docs/v11-migration.md) for the complete migration guide with code examples.\n\n## Table of Contents\n\n[[toc]]\n\n## Usage\n\n```console\n$ domstack --help\nUsage: domstack [options]\n\n    Example: domstack --src website --dest public\n\n    --src, -s             path to source directory (default: \"src\")\n    --dest, -d            path to build destination directory (default: \"public\")\n    --ignore, -i          comma separated gitignore style ignore string\n    --drafts              Build draft pages with the `.draft.{md,js,ts,html}` page suffix.\n    --eject, -e           eject the DOMStack default layout, style and client into the src flag directory\n    --watch, -w           build, watch and serve the site build\n    --watch-only          watch and build the src folder without serving\n    --copy                path to directories to copy into dist; can be used multiple times\n    --help, -h            show help\n    --version, -v         show version information\ndomstack (v11.0.0)\n```\n\n`domstack` builds a `src` directory into a `dest` directory (default: `public`).\n`domstack` is also aliased to a `dom` bin.\n\n- Running `domstack` will result in a `build` by default.\n- Running `domstack --watch` or `domstack -w` will build the site and start an auto-reloading development web-server that watches for changes (provided by [Browsersync](https://browsersync.io)).\n- Running `domstack --eject` or `domstack -e` will extract the default layout, global styles, and client-side JavaScript into your source directory and add the necessary dependencies to your package.json.\n\n`domstack` is primarily a unix `bin` written for the [Node.js](https://nodejs.org) runtime that is intended to be installed from `npm` as a `devDependency` inside a `package.json` committed to a `git` repository.\nIt can be used outside of this context, but it works best within it.\n\n## Core Concepts\n\n`domstack` is a static site generator that builds a website from \"pages\" in a `src` directory, nearly 1:1 into a `dest` directory.\nBy building \"pages\" from their `src` location to the `dest` destination, the directory structure inside of `src` becomes a \"filesystem router\" naturally, without any additional moving systems or structures.\n\nA `src` directory tree might look something like this:\n\n```bash\nsrc % tree\n.\n├── md-page\n│        ├── page.md # page.md (or README.md) in a directory turns into /md-page/index.html. page.md takes precedence.\n│        ├── client.ts # Every page can define its own client.ts script that loads only with it.\n│        ├── style.css # Every page can define its own style.css style that loads only with it.\n│        ├── loose-md-page.md # loose markdown get built in place, but lacks some page features.\n│        └── nested-page # pages are built in place and can nest.\n│               ├── README.md # This page is accessed at /md-page/nested-page/. (page.md works here too)\n│               ├── style.css # nested pages are just pages, so they also can have a page scoped client and style.\n│               └── client.js # Anywhere JS loads, you can use .js or .ts\n├── html-page\n│        ├── client.tsx # client bundles can also be written in .jsx/.tsx\n│        ├── page.html # Raw html pages are also supported. They support handlebars template blocks.\n│        ├── page.vars.ts # pages can define page variables in a page.vars.ts\n│        └── style.css\n├── js-page\n│        └── page.js # A page can also just be a plain javascript function that returns content. They can also be type checked.\n├── ts-page\n│        ├── client.ts # domstack provides type-stripping via Node.JS and esbuild\n│        ├── page.vars.ts # use tsc to run typechecking\n│        └── page.ts\n├── feeds\n│        └── feeds.template.ts # Templates let you generate any file you want from variables and page data.\n├── page-with-workers\n│        ├── client.ts\n│        └── page.ts\n│        ├── counter.worker.ts # Web workers use a .worker.{ts,js} naming convention and are auto-bundled\n│        └── analytics.worker.js\n├── layouts # layouts can live anywhere. The inner content of your page is slotted into your layout.\n│        ├── blog.layout.ts # pages specify which layout they want by setting a `layout` page variable.\n│        ├── blog.layout.css # layouts can define an additional layout style.\n│        ├── blog.layout.client.ts # layouts can also define a layout client.\n│        ├── article.layout.ts # layouts can extend other layouts, since they are just functions.\n│        ├── javascript.layout.js # layouts can also be written in javascript\n│        └── root.layout.ts # the default layout is called \"root\"\n├── globals # global assets can live anywhere. Here they are in a folder called globals.\n│        ├── global.client.ts # you can define a global client that loads on every page.\n│        ├── global.css # you can define a global css file that loads on every page.\n│        ├── global.vars.ts # site wide variables get defined in global.vars.ts\n│        ├── global.data.ts # optional file to derive and aggregate data from all pages before rendering\n│        ├── markdown-it.settings.ts # You can customize the markdown-it instance used to render markdown\n│        └── esbuild.settings.ts # You can even customize the build settings passed to esbuild\n├── page.md # The top level page can also be a page.md (or README.md) file.\n├── client.ts # the top level page can define a page scoped js client.\n├── style.css # the top level page can define a page scoped css style.\n└── favicon-16x16.png # static assets can live anywhere. Anything other than JS, CSS and HTML get copied over automatically.\n```\n\nThe core idea of `domstack` is that a `src` directory of markdown, html and ts/js \"inner\" documents will be transformed into layout wrapped html documents in the `dest` directory, along with page scoped js and css bundles, as well as a global stylesheet and global js bundle.\n\nIt ships with sane defaults so that you can point `domstack` at a standard [markdown documented repository](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github) and have it build a website with near-zero preparation.\n\n## Examples\n\nA collection of examples can be found in the [`./examples`](./examples) folder.\n\nTo run examples:\n\n```bash\n$ git clone git@github.com:bcomnes/domstack.git\n$ cd domstack\n# install the top level deps\n$ npm i\n$ cd example:{example-name}\n# install the example deps\n$ npm i\n# start the example\n$ npm start\n```\n\n### Additional examples\n\nHere are some additional external examples of larger domstack projects.\nIf you have a project that uses domstack and could act as a nice example, please PR it to the list!\n\n- [Blog Example](https://github.com/bcomnes/bret.io/) - A personal blog written with DOMStack\n- [Isomorphic Static/Client App](https://github.com/hifiwi-fi/breadcrum.net/tree/master/packages/web/client) - Pages build from client templates and hydrate on load.\n- [Zero-Conf Markdown Docs](https://github.com/bcomnes/deploy-to-neocities/blob/70b264bcb37fca5b21e45d6cba9265f97f6bfa6f/package.json#L38) - A npm package with markdown docs, transformed into a website without any any configuration\n\n## Pages\n\nPages are a named directories inside of `src`, with **one of** the following page files inside of it.\n\n- `md` pages are [CommonMark](https://commonmark.org) markdown pages, with an optional [YAML](https://yaml.org) front-matter block.\n- `html` pages are an inner [html](https://developer.mozilla.org/en-US/docs/Web/HTML) fragment that get inserted into the page layout.\n- `ts`/`js` pages are a [ts](https://developer.mozilla.org/en-US/docs/Glossary/TypeScript)/[js](https://developer.mozilla.org/en-US/docs/Web/JavaScript) file that exports a default function that resolves into an inner-html fragment that is inserted into the page layout.\n\nVariables are available in all pages. `md` and `html` pages support variable access via [handlebars][hb] template blocks. `ts`/`js` pages receive variables as part of the argument passed to them. See the [Variables](#variables) section for more info.\n\nPages can define a special variable called `layout` determines which layout the page is rendered into.\n\nBecause pages are just directories, they nest and structure naturally as a filesystem router. Directories in the `src` folder that lack one of these special page files can exist along side page directories and can be used to store co-located code or static assets without conflict.\n\n### `md` pages\n\nA `md` page looks like this on the filesystem:\n\n```bash\nsrc/page-name/page.md\n# or\nsrc/page-name/README.md\n# or\nsrc/page-name/loose-md.md\n```\n\n- `md` pages have three types: a `page.md`, a `README.md`, or a loose `whatever-name-you-want.md` file.\n- `page.md` and `README.md` files transform to an `index.html` at the same path. When both exist in the same directory, `page.md` takes precedence over `README.md`. `whatever-name-you-want.md` loose markdown files transform into `whatever-name-you-want.html` files at the same path in the `dest` directory.\n- `md` pages can have YAML frontmatter, with variables that are accessible to the page layout and handlebars template blocks when building.\n- You can include html in markdown files, so long as you adhere to the allowable markdown syntax around html tags.\n- `md` pages support [handlebars][hb] template placeholders.\n- You can disable `md` page [handlebars][hb] processing by setting the `handlebars` variable to `false`.\n- `md` pages support many [github flavored markdown features](https://github.com/bcomnes/siteup/blob/6481bd01e59e5d8a4bfcb33008f44a1405bf622b/lib/build-pages/page-builders/md/get-md.js#L25-L36).\n\nAn example of a `md` page:\n\n```md\n---\ntitle: A title for a markdown page\nfavoriteColor: 'Blue'\n---\n\nJust writing about web development.\n\n## Favorite colors\n\nMy favorite color is {{ vars.favoriteColor }}.\n```\n\n### `html` pages\n\nA `html` page looks like this:\n\n```bash\nsrc/page-name/page.html\n```\n\n- `html` pages are named `page.html` inside an associated page folder.\n- `html` pages are the simplest page type in `domstack`. They let you build with raw html for when you don't want that page to have access to markdown features. Some pages are better off with just raw `html`, and the rules with building `html` in a real `html` file are much more flexible than inside of a `md` file.\n- `html` page variables can only be set in a `page.vars.js` file inside the page directory.\n- `html` pages support [handlebars][hb] template placeholders.\n- You can disable `html` page [handlebars][hb] processing by setting the `handlebars` variable to `false`.\n\nAn example `html` page:\n\n```html\n<h2>Favorite frameworks</h2>\n<ul>\n  <li>React</li>\n  <li>Vue</li>\n  <li>Svelte</li>\n  <!-- favoriteFramework defined in page.vars.js -->\n  <li>{{ vars.favoriteFramework }}</li>\n</ul>\n```\n\n### `ts`/`js` pages\n\nA `ts`/`js` page looks like this:\n\n```bash\nsrc/page-name/page.ts\n# or\nsrc/page-name/page.js\n```\n\n- `js`/`ts` pages consist of a named directory with a `page.js` or `page.ts` inside of it, that exports a default function that returns the contents of the inner page.\n- a `js`/`ts` page needs to `export default` a function (async or sync) that accepts a variables argument and returns a string of the inner html of the page, or any other type that your layout can accept.\n- You can specify the return type using `PageFunction<T, U>` where `T` is the variables type and `U` is the return type (defaults to `any`).\n- A `js`/`ts` page can export a `vars` object or function (async or sync) that takes highest variable precedence when rendering the page. `export vars` is similar to a `md` page's front matter.\n- A `js`/`ts` page receives the standard `domstack` [Variables](#variables) set.\n- There is no built in handlebars support in `js`/`ts` pages, however you are free to use any template library that you can import.\n- `js`/`ts` pages are run in a Node.js context only.\n\nAn example TypeScript page:\n\n```typescript\nimport type { PageFunction } from '@domstack/static'\n\nexport const vars = {\n  favoriteCookie: 'Chocolate Chip with Sea Salt'\n}\n\nconst page: PageFunction<typeof vars}> = async ({\n  vars\n}) => {\n  return /* html */`<div>\n    <p>This is just some html.</p>\n    <p>My favorite cookie: ${vars.favoriteCookie}</p>\n  </div>`\n}\n\nexport default page\n```\n\nIt is recommended to use some level of template processing over raw string templates so that HTML is well-formed and variable values are properly escaped. Here is a more realistic TypeScript example that uses [`preact`](https://preactjs.com/) with [`htm`](https://github.com/developit/htm) and `domstack` page introspection.\n\n\n```typescript\nimport { html } from 'htm/preact'\nimport { dirname, basename } from 'node:path'\nimport type { PageFunction } from '@domstack/static'\n\ntype BlogVars = {\n  favoriteCake: string\n}\n\nexport const vars = {\n  favoriteCake: 'Chocolate Cloud Cake'\n}\n\nconst blogIndex: PageFunction<BlogVars> = async ({\n  vars: { favoriteCake },\n  pages\n}) => {\n  const yearPages = pages.filter(page => dirname(page.pageInfo.path) === 'blog')\n  return html`<div>\n    <p>I love ${favoriteCake}!!</p>\n    <ul>\n      ${yearPages.map(yearPage => html`<li><a href=\"${`/${yearPage.pageInfo.path}/`}\">${basename(yearPage.pageInfo.path)}</a></li>`)}\n    </ul>\n  </div>`\n}\n\nexport default blogIndex\n```\n\n### Page Styles\n\nYou can create a `style.css` file in any page folder.\nPage styles are loaded on just that one page.\nYou can import common use styles into a `style.css` page style using css [`@import`](https://developer.mozilla.org/en-US/docs/Web/CSS/@import) statements to re-use common css.\nYou can `@import` paths to other css files, or out of `npm` modules you have installed in your projects `node_modues` folder.\n`css` page bundles are bundled using [`esbuild`][esbuild].\n\nAn example of a page `style.css` file:\n\n```css\n/* /some-page/style.css */\n@import \"some-npm-module/style.css\";\n@import \"../common-styles/button.css\";\n\n.some-page-class {\n  color: blue;\n\n  & .button {\n    color: purple;\n  }\n}\n```\n\n### Page JS Bundles\n\nYou can create a `client.ts` or `client.js` file in any page folder.\nPage bundles are client side JS bundles that are loaded on that one page only.\nYou can import common code and modules from relative paths, or `npm` modules out of `node_modules`.\nThe `client.js` page bundles are bundle-split with every other client-side js/ts entry-point, so importing common chunks of code are loaded in a maximally efficient way.\nPage bundles are run in a browser context only, however they can share carefully crafted code that also runs in a Node.js or layout context.\n`ts`/`js` page bundles are bundled using [`esbuild`][esbuild].\n\nAn example of a page `client.js` file:\n\n```typescript\n/* /some-page/client.ts */\nimport { funnyLibrary } from 'funny-library'\nimport { someHelper } from '../helpers/foo.js'\n\nawait someHelper()\nawait funnyLibrary()\n```\n\n#### .tsx/.jsx\n\nClient bundles support .jsx and .tsx. They default to preact, so if you want mainlain react, customize your esbuild settings to load that instead.\nSee the [react](./examples/react/) example for more details.\n\n### Page variable files\n\nEach page can also have a `page.vars.ts` or `page.vars.js` file that exports a `default` sync/async function or object that contains page specific variables.\n\n```typescript\n// export an object\nexport default {\n  my: 'vars'\n}\n\n// OR export a default function\nexport default () => {\n  return { my: 'vars' }\n}\n\n// OR export a default async function\nexport default async () => {\n  return { my: 'vars' }\n}\n```\n\nPage variable files have higher precedent than `global.vars.ts` variables, but lower precedent than frontmatter or `vars` ts/js page exports.\n\n### Draft pages\n\nIf you add a `.draft.{md,html,ts,js}` to any of the page types, the page is considered a draft page.\nDraft pages are not built by default.\nIf you pass the `--drafts` flag when building or watching, the draft pages will be built.\nWhen draft pages are omitted, they are completely ignored.\n\nDraft pages can be detected in layouts using the `page.draft === true` or `pages[n].draft === true` variable.\nIt is a good idea to display something indicating the page is a draft in your templates so you don't get confused when working with the `--drafts` flag.\n\nAny static assets near draft pages will still be copied because static assets are processed in parallel from page generation (to keep things fast).\nIf you have an idea on how to relate static assets to a draft page for omission, please open a discussion issue.\n\nDraft pages let you work on pages before they are ready and easily omit them from a build when deploying pages that are ready.\n\n## Web Workers\n\nYou can easily write [web workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) for a page by adding a file called `${name}.worker.ts` or `${name}.worker.js` where `name` becomes the name of the worker filename in the `workers.json` file.\nDOMStack will build these similarly to page `client.ts` bundles, and will even bundle split their contents with the rest of your site.\n\n```\npage-directory/\n  ├── page.js\n  ├── client.js\n  ├── counter.worker.js  # Worker with counter functionality\n  └── data.worker.js     # Worker for data processing\n```\n\nTo use a woker, load in a `./workers.json` file that is generated along with the worker bundle to get the final name of the worker entrypoint and then create a worker with that filename.\n\n```typescript\n// First, fetch the workers.json to get worker paths in your client.ts\nasync function initializeWorkers() {\n  const response = await fetch('./workers.json');\n  const workersData = await response.json();\n\n  // Initialize workers with the correct hashed filenames\n  const counterWorker = new Worker(\n    new URL(`./${workersData.counter}`, import.meta.url),\n    { type: 'module' }\n  );\n\n  // Use the worker\n  counterWorker.postMessage({ action: 'increment' });\n\n  counterWorker.onmessage = (e) => {\n    console.log(e.data);\n  };\n\n  return counterWorker;\n}\n\nconst worker = await initializeWorkers();\n```\n\nSee the [Web Workers Example](https://github.com/domstack/domstack/tree/master/examples/worker-example) for a complete implementation.\n\n## Layouts\n\nLayouts are \"outer page templates\" that pages get rendered into.\nYou can define as many as you want, and they can live anywhere in the `src` directory.\n\nLayouts are named `${layout-name}.layout.js` where `${layout-name}` becomes the name of the layout.\nLayouts should have a unique name, and layouts with duplicate name will result in a build error.\n\nLayouts can be typed using `LayoutFunction<T, U, V>` where:\n- `T` is the variables type\n- `U` is the type of content received from pages (defaults to `any`)\n- `V` is the layout's return type (defaults to `string` for HTML output)\n\nExample layout file names:\n\n```bash\nsrc/layouts/root.layout.js # this layout is references as 'root'\nsrc/other-layouts/article.layout.js # this layout is references as 'article'\n```\n\nAt a minimum, your site requires a `root` layout (a file named `root.layout.js`), though `domstack` ships a default `root` layout so defining one in your `src` directory is optional, though recommended.\n\nAll pages have a `layout` variable that defaults to `root`. If you set the `layout` variable to a different name, pages will build with a layout matching the name you set to that variable.\n\nThe following markdown page would be rendered using the `article` layout.\n\n```md\n---\nlayout: 'article'\ntitle: 'My Article Title'\n---\n\nThanks for reading my article\n```\n\nA page referencing a layout name that doesn't have a matching layout file will result in a build error.\n\n### The default `root.layout.js`\n\nA layout is a `ts`/`js` file that `export default`'s an async or sync function that implements an outer-wrapper html template that will house the inner content from the page (`children`) being rendered. Think of the frame around a picture. That's a layout. 🖼️\n\nIt is always passed a single object argument with the following entries:\n\n- `vars`: An object of global, page folder, and page variables merged together. Pages can customize layouts by providing or overriding global defaults.\n- `scripts`: array of paths that should be included onto the page in a script tag src with type `module`.\n- `styles`: array of paths that should be included onto the page in a `link rel=\"stylesheet\"` tag with the `href` pointing to the paths in the array.\n- `children`: A string of the inner content of the page, or whatever type your js page functions returns. `md` and `html` page types always return strings.\n- `pages`: An array of page data that you can use to generate index pages with, or any other page-introspection based content that you desire.\n- `page`: An object with metadata and other facts about the current page being rendered into the template. This will also be found somewhere in the `pages` array.\n\nThe default `root.layout.ts` is featured below, and is implemented with [`preact`](https://preactjs.com/) and [`htm`](https://github.com/developit/htm), though it could just be done with a template literal or any other template system that runs in Node.js.\n\n`root.layout.ts` can live anywhere in the `src` directory.\n\n```typescript\nimport { html } from 'htm/preact'\nimport { render } from 'preact-render-to-string'\nimport type { LayoutFunction } from '@domstack/static'\n\ntype RootLayoutVars = {\n  title: string,\n  siteName: string,\n  defaultStyle: boolean,\n  basePath?: string\n}\n\nconst defaultRootLayout: LayoutFunction<RootLayoutVars> = ({\n  vars: {\n    title,\n    siteName = 'Domstack',\n    basePath,\n    /* defaultStyle = true  Set this to false in global or page vars to disable the default style in the default layout */\n  },\n  scripts,\n  styles,\n  children,\n  pages,\n  page,\n}) => {\n  return /* html */`\n    <!DOCTYPE html>\n    <html>\n      ${render(html`\n        <head>\n          <meta charset=\"utf-8\" />\n          <title>${title ? `${title}` : ''}${title && siteName ? ' | ' : ''}${siteName}</title>\n          <meta name=\"viewport\" content=\"width=device-width, user-scalable=no\" />\n          ${scripts\n            ? scripts.map(script => html`<script type='module' src=\"${script.startsWith('/') ? `${basePath ?? ''}${script}` : script}\" />`)\n            : null}\n          ${styles\n            ? styles.map(style => html`<link rel=\"stylesheet\" href=\"${style.startsWith('/') ? `${basePath ?? ''}${style}` : style}\" />`)\n            : null}\n        </head>\n      `)}\n      ${render(html`\n        <body className=\"safe-area-inset\">\n        ${typeof children === 'string'\n            ? html`<main className=\"mine-layout app-main\" dangerouslySetInnerHTML=${{ __html: children }}></main>`\n            : html`<main className=\"mine-layout app-main\">${children}</main>`\n        }\n        </body>\n      `)}\n    </html>\n  `\n}\n\nexport default defaultRootLayout\n```\n\nIf your `src` folder doesn't have a `root.layout.js` file somewhere in it, `domstack` will use the default [`default.root.layout.js`](./lib/defaults/default.root.layout.js) file it ships. The default `root` layout includes a special boolean variable called `defaultStyle` that lets you disable a default page style (provided by [mine.css](http://github.com/bcomnes/mine.css)) that it ships with.\n\n### Nested layouts\n\nSince layouts are just functions™️, they nest naturally. If you define the majority of your html page meta detritus in a `root.layout.js`, you can define additional layouts that act as child wrappers, without having to re-define everything in `root.layout.ts`.\n\nFor example, you could define a `blog.layout.ts` that re-uses the `root.layout.ts`:\n\n```typescript\nimport defaultRootLayout from './root.layout.js'\nimport { html } from 'htm/preact'\nimport { render } from 'preact-render-to-string'\nimport type { LayoutFunction } from '@domstack/static'\n\n// Import the type from root layout\nimport type { RootLayoutVars } from './root.layout'\n\n// Extend the RootLayoutVars with blog-specific properties\ninterface BlogLayoutVars extends RootLayoutVars {\n  authorImgUrl?: string;\n  authorImgAlt?: string;\n  authorName?: string;\n  authorUrl?: string;\n  publishDate?: string;\n  updatedDate?: string;\n}\n\nconst blogLayout: LayoutFunction<BlogLayoutVars> = (layoutVars) => {\n  const { children: innerChildren, ...rest } = layoutVars\n  const vars = layoutVars.vars\n\n  const children = render(html`\n    <article className=\"article-layout h-entry\" itemscope itemtype=\"http://schema.org/NewsArticle\">\n      <header className=\"article-header\">\n        <h1 className=\"p-name article-title\" itemprop=\"headline\">${vars.title}</h1>\n        <div className=\"metadata\">\n          <address className=\"author-info\" itemprop=\"author\" itemscope itemtype=\"http://schema.org/Person\">\n            ${vars.authorImgUrl\n              ? html`<img height=\"40\" width=\"40\" src=\"${vars.authorImgUrl}\" alt=\"${vars.authorImgAlt}\" className=\"u-photo\" itemprop=\"image\" />`\n              : null\n            }\n            ${vars.authorName && vars.authorUrl\n              ? html`\n                  <a href=\"${vars.authorUrl}\" className=\"p-author h-card\" itemprop=\"url\">\n                    <span itemprop=\"name\">${vars.authorName}</span>\n                  </a>`\n              : null\n            }\n          </address>\n          ${vars.publishDate\n            ? html`\n              <time className=\"dt-published\" itemprop=\"datePublished\" datetime=\"${vars.publishDate}\">\n                <a href=\"#\" className=\"u-url\">\n                  ${(new Date(vars.publishDate)).toLocaleString()}\n                </a>\n              </time>`\n            : null\n          }\n          ${vars.updatedDate\n            ? html`<time className=\"dt-updated\" itemprop=\"dateModified\" datetime=\"${vars.updatedDate}\">Updated ${(new Date(vars.updatedDate)).toLocaleString()}</time>`\n            : null\n          }\n        </div>\n      </header>\n\n      <section className=\"e-content\" itemprop=\"articleBody\">\n        ${typeof innerChildren === 'string'\n          ? html`<div dangerouslySetInnerHTML=${{ __html: innerChildren }}></div>`\n          : innerChildren\n        }\n      </section>\n    </article>\n  `)\n\n  const rootArgs = { ...rest, children }\n  return defaultRootLayout(rootArgs)\n}\n\nexport default blogLayout\n```\n\nNow the `blog.layout.js` becomes a nested layout of `root.layout.js`. No magic, just functions.\n\nAlternatively, you could compose your layouts from re-usable template functions and strings.\nIf you find your layouts nesting more than one or two levels, perhaps composition would be a better strategy.\n\n### Layout styles\n\nYou can create a `${layout-name}.layout.css` next to any layout file.\nWhile the layout file can live anywhere in `src`, the layout style must live next to the associated layout file.\n\n```css\n/* /layouts/article.layout.css */\n.layout-specific-class {\n  color: blue;\n\n  & .button {\n    color: purple;\n  }\n}\n\n/* This layout style is included in every page rendered with the 'article' layout */\n```\nLayout styles are loaded on all pages that use that layout.\nLayout styles are bundled with [`esbuild`][esbuild] and can bundle relative and `npm` css using css `@import` statements.\n\n### Layout TS/JS Bundles\n\nYou can create a `${layout-name}.layout.client.ts` or `${layout-name}.layout.client.js` next to any layout file.\nWhile the layout file can live anywhere in `src`, the layout client bundles must live next to the associated layout file.\n\n```typescript\n/* /layouts/article.layout.client.ts */\n\nconsole.log('I run on every page rendered with the \\'article\\' layout')\n\n/* This layout client is included in every page rendered with the 'article' layout */\n```\n\nLayout ts/js bundles are loaded on all pages that use that layout.\nLayout ts/js bundles are bundled with [`esbuild`][esbuild] and can bundle relative and `npm` modules using ESM `import` statements.\n\n### Nested layout TS/JS bundles and styles\n\nIf you create a nested layout that imports another layout file, **and** that imported layout has a layout style and/or layout js bundle, there is no magic that will include those layout styles and clients into the importing layout. To include those layout styles and clients into an additional layout, just import them into the additional layout client and style files. For example, if `article.layout.ts` wraps `root.layout.ts`, you must do the following:\n\n```css\n/* article.layout.css  */\n@import \"./root.layout.css\";\n```\n\nThis will include the layout style from the `root` layout in the `article` layout style.\n\n```typescript\n/* article.layout.client.ts  */\nimport './root.layout.client.ts'\n```\n\nAdding these imports will include the `root.layout.ts` layout assets into the `blog.layout.ts` asset files.\n\n## Static assets\n\nAll static assets in the `src` directory are copied 1:1 to the `public` directory. Any file in the `src` directory that doesn't end in `.ts`, `.js`, `.css`, `.html`, or `.md` is copied to the `dest` directory.\n\n### `--eject` flag\n\nThe `--eject` (or `-e`) flag extracts DOMStack's default layout, global CSS, and client-side JavaScript into your source directory. This allows you to fully customize these files while maintaining the same functionality.\n\nWhen you run `domstack --eject`, it will:\n\n1. Create a default root layout file at `layouts/root.layout.js` (or `.mjs` depending on your package.json type)\n2. Create a default global CSS file at `globals/global.css`\n3. Create a default client-side JavaScript file at `globals/global.client.js`\n4. Add the necessary dependencies to your package.json:\n   - mine.css\n   - preact\n   - htm\n   - preact-render-to-string\n   - highlight.js\n\nIt is recomended to eject early in your project so that you can customize the root layout as you see fit, and de-couple yourself from potential unwanted changes in the default layout as new versions of DOMStack are released.\n\n### `--copy` directories\n\nYou can specify directories to copy into your `dest` directory using the `--copy` flag. Everything in those directories will be copied as-is into the destination, including js, css, html and markdown, preserving the internal directory structure. Conflicting files are not detected or reported and will cause undefined behavior.\n\nCopy folders must live **outside** of the `dest` directory. Copy directories can be in the src directory allowing for nested builds. In this case they are added to the ignore glob and ignored by the rest of `domstack`.\n\nThis is useful when you have legacy or archived site content that you want to include in your site, but don't want `domstack` to process or modify it.\nIn general, static content should live in your primary `src` directory, however for merging in old static assets over your domstack build is sometimes easier to reason about when it's kept in a separate folder and isn't processed in any way.\n\nFor example:\n\n```\nsrc/...\noldsite/\n├── client.js\n├── hello.html\n└── styles/\n    └── globals.css\n```\n\nAfter build:\n\n```\nsrc/...\noldsite/...\npublic/\n├── client.js\n├── hello.html\n└── styles/\n    └── globals.css\n```\n\n## Templates\n\nTemplate files let you write any kind of file type to the `dest` folder while customizing the contents of that file with access to the site [Variables](#variables) object, or inject any other kind of data fetched at build time. Template files can be located anywhere and look like:\n\n```bash\nname-of-template.txt.template.ts\n${name-portion}.template.ts\n```\n\nTemplate files are a `ts`/`js` file that default exports one of the following sync/async functions:\n\n### Simple string template\n\nA function that returns a string. The `name-of-template.txt` portion of the template file name becomes the file name of the output file.\n\n```typescript\n// name-of-template.txt.template.ts\nimport type { TemplateFunction } from '@domstack/static'\n\ninterface TemplateVars {\n  foo: string;\n  testVar: string;\n}\n\nconst simpleTemplate: TemplateFunction<TemplateVars> = async ({\n  vars: {\n    foo,\n    testVar\n  }\n}) => {\n  return `Hello world\n\nThis is just a file with access to global vars: ${foo}`\n}\n\nexport default simpleTemplate\n```\n\n### Object template\n\nA function that returns a single object with a `content` and `outputName` entries. The `outputName` overrides the name portion of the template file name.\n\n```typescript\nimport type { TemplateFunction } from '@domstack/static'\n\ninterface TemplateVars {\n  foo: string;\n}\nexport default async ({\n  vars: { foo }\n}) => ({\n  content: `Hello world\n\nThis is just a file with access to global vars: ${foo}`,\n  outputName: './single-object-override.txt'\n})\n```\n\n### Object array template\n\nA function that returns an array of objects with a `content` and `outputName` entries. This template file generates more than one file from a single template file.\n\n```typescript\nimport type { TemplateFunction } from '@domstack/static'\n\ninterface TemplateVars {\n  foo: string;\n  testVar: string;\n}\n\nconst objectArrayTemplate: TemplateFunction<TemplateVars> = async ({\n  vars: {\n    foo,\n    testVar\n  }\n}) => {\n  return [\n    {\n      content: `Hello world\n\nThis is just a file with access to global vars: ${foo}`,\n      outputName: 'object-array-1.txt'\n    },\n    {\n      content: `Hello world again\n\nThis is just a file with access to global vars: ${testVar}`,\n      outputName: 'object-array-2.txt'\n    }\n  ]\n}\n\nexport default objectArrayTemplate\n```\n\n### AsyncIterator template\n\nAn [AsyncIterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncIterator) that `yields` objects with `content` and `outputName` entries.\n\n```typescript\nimport type { TemplateAsyncIterator } from '@domstack/static'\n\ninterface TemplateVars {\n  foo: string;\n  testVar: string;\n}\n\nconst templateIterator: TemplateAsyncIterator<TemplateVars> = async function * ({\n  vars: {\n    foo,\n    testVar\n  }\n}) {\n  // First item\n  yield {\n    content: `Hello world\n\nThis is just a file with access to global vars: ${foo}`,\n    outputName: 'yielded-1.txt'\n  }\n\n  // Second item\n  yield {\n    content: `Hello world again\n\nThis is just a file with access to global vars: ${testVar}`,\n    outputName: 'yielded-2.txt'\n  }\n}\n\nexport default templateIterator\n```\n\n### RSS Feed Template Example\n\nTemplates receive the standard variables available to pages, so its possible to perform page introspection and generate RSS feeds of website content.\n\nThe following example shows how to generate an [RSS](https://www.rssboard.org) and [JSON feed](https://www.jsonfeed.org) of the last 10 date sorted pages with the `blog` layout using the AsyncIterator template type.\n\n```typescript\nimport pMap from 'p-map'\nimport jsonfeedToAtom from 'jsonfeed-to-atom'\nimport type { TemplateAsyncIterator } from '@domstack/static'\n\ninterface TemplateVars {\n  title: string;\n  layout: string;\n  siteName: string;\n  homePageUrl: string;\n  authorName: string;\n  authorUrl: string;\n  authorImgUrl?: string;\n  siteDescription: string;\n  language: string;\n}\n\nconst feedsTemplate: TemplateAsyncIterator<TemplateVars> = async function * ({\n  vars: {\n    siteName,\n    siteDescription,\n    homePageUrl,\n    language = 'en-us',\n    authorName,\n    authorUrl,\n    authorImgUrl,\n  },\n  pages\n}) {\n  const blogPosts = pages\n    .filter(page => page.pageInfo.path.startsWith('blog/') && page.vars['layout'] === 'blog')\n    .sort((a, b) => new Date(b.vars.publishDate) - new Date(a.vars.publishDate))\n    .slice(0, 10)\n\n  const jsonFeed = {\n    version: 'https://jsonfeed.org/version/1',\n    title: siteName,\n    home_page_url: homePageUrl,\n    feed_url: `${homePageUrl}/feed.json`,\n    description: siteDescription,\n    author: {\n      name: authorName,\n      url: authorUrl,\n      avatar: authorImgUrl\n    },\n    items: await pMap(blogPosts, async (page) => {\n      return {\n        date_published: page.vars['publishDate'],\n        title: page.vars['title'],\n        url: `${homePageUrl}/${page.pageInfo.path}/`,\n        id: `${homePageUrl}/${page.pageInfo.path}/#${page.vars['publishDate']}`,\n        content_html: await page.renderInnerPage({ pages })\n      }\n    }, { concurrency: 4 })\n  }\n\n  yield {\n    content: JSON.stringify(jsonFeed, null, '  '),\n    outputName: './feeds/feed.json'\n  }\n\n  yield {\n    content: jsonfeedToAtom(jsonFeed),\n    outputName: './feeds/feed.xml'\n  }\n}\n\nexport default feedsTemplate\n```\n\n## Global Assets\n\nThere are a few important (and optional) global assets that live anywhere in the `src` directory. If duplicate named files that match the global asset file name pattern are found, a build error will occur until the duplicate file error is resolved.\n\n### `global.vars.ts`\n\nThe `global.vars.ts` or `global.vars.js` file should `export default` a variables object or a (sync or async) function that returns a variable object.\nThe variables in this file are available to all pages, unless the page sets a variable with the same key, taking a higher precedence.\n\n```typescript\nexport default {\n  siteName: 'The name of my website',\n  authorName: 'Mr. Wallace'\n}\n```\n\n#### `browser` variable\n\n`global.vars.ts` can uniquely export a `browser` object. These object variables are made available in all js bundles. The `browser` export can be an object, or a sync/async function that returns an object.\n\n```typescript\nexport const browser = {\n  'process.env.TRANSPORT': 'http',\n  'process.env.HOST': 'localhost'\n}\n```\n\nThe exported object is passed to esbuild's [`define`](https://esbuild.github.io/api/#define) options and is available to every js bundle.\n\n> [!WARNING]\n> Setting `define` in [`esbuild.settings.ts`](#esbuild-settingsts) while also using the `browser` export will throw an error. Use one or the other.\n\n### `global.client.ts`\n\nThis is a script bundle that is included on every page. It provides an easy way to inject analytics, or other small scripts that every page should have. Try to minimize what you put in here.\n\n```typescript\nconsole.log('I run on every page in the site!')\n```\n\n### `global.css`\n\nThis is a global stylesheet that every page will use.\nAny styles that need to be on every single page should live here.\nImporting css from `npm` modules work well here.\n\n### `global.data.js`\n\nThe `global.data.js` (or `.ts`, `.mjs`, etc.) file is an optional file that can live anywhere in your `src` tree — like all global assets, the first one found wins and duplicates warn. It runs **once per build**, after all pages are initialized and before rendering begins.\n\nIt receives a fully resolved `PageData[]` array and returns an object that is stamped onto every page's vars — making the derived data available to every page, layout, and template.\n\n```typescript\nimport type { AsyncGlobalDataFunction } from '@domstack/static'\nimport { html } from 'htm/preact'\nimport { render } from 'preact-render-to-string'\n\ntype GlobalData = {\n  blogPostsHtml: string\n}\n\nconst buildGlobalData: AsyncGlobalDataFunction<GlobalData> = async ({ pages }) => {\n  const blogPosts = pages\n    .filter(p => p.vars?.layout === 'blog' && p.vars?.publishDate)\n    .sort((a, b) => new Date(b.vars.publishDate) - new Date(a.vars.publishDate))\n    .slice(0, 5)\n\n  const blogPostsHtml = render(html`\n    <ul className=\"blog-index-list\">\n      ${blogPosts.map(p => html`\n        <li className=\"blog-entry h-entry\">\n          <a className=\"blog-entry-link u-url u-uid p-name\" href=\"/${p.pageInfo.path}/\">\n            ${p.vars?.title}\n          </a>\n        </li>\n      `)}\n    </ul>\n  `)\n\n  return { blogPostsHtml }\n}\n\nexport default buildGlobalData\n```\n\nThe returned object is stamped onto every page's vars before rendering, so any page or layout can read the derived data via `vars`:\n\n```md\n## [Blog](./blog/)\n\n{{{ vars.blogPostsHtml }}}\n```\n\n**Key properties of `global.data.js`:**\n\n- Receives fully resolved `PageData[]` — every page has `.vars` (merged global + page + builder vars), `.pageInfo` (path, type, etc.), `.styles`, `.scripts`, and more.\n- Runs inside the worker process (same as all other dynamic imports) to avoid ESM caching issues.\n- Skipped entirely if no `global.data.*` file exists — zero overhead.\n- Changes to `global.data.*` trigger a full page rebuild (same as `global.vars.*`), since the output is stamped onto every page's vars.\n\nUse `GlobalDataFunction<T>` or `AsyncGlobalDataFunction<T>` to type the function where `T` is the shape of the object you return.\n\n### `esbuild.settings.ts`\n\nThis is an optional file you can create anywhere.\nIt should export a default sync or async function that accepts a single argument (the esbuild settings object generated by domstack) and returns a modified build object.\nUse this to customize the esbuild settings directly.\nYou can break domstack with this, so be careful.\nHere is an example of using this file to polyfill node builtins in the browser bundle:\n\n```typescript\nimport { polyfillNode } from 'esbuild-plugin-polyfill-node'\n// BuildOptions re-exported from esbuild\nimport type { BuildOptions } from '@domstack/static'\n\nconst esbuildSettingsOverride = async (esbuildSettings: BuildOptions): Promise<BuildOptions> => {\n  esbuildSettings.plugins = [polyfillNode()]\n  return esbuildSettings\n}\n\nexport default esbuildSettingsOverride\n```\n\nImportant esbuild settings you may want to set here are:\n\n- [target](https://esbuild.github.io/api/#target) - Set the `target` to make `esbuild` run a few small transforms on your CSS and JS code.\n- [jsx](https://esbuild.github.io/api/#jsx) - Unset this if you want default react transform.\n- [jsxImportSource](https://esbuild.github.io/api/#jsx-import-source)  - Unset this if you want default react transform.\n- [define](https://esbuild.github.io/api/#define) - Define compile-time constants for js bundles. Note: setting `define` here conflicts with the [`browser` export](#browser-variable) in `global.vars.ts` and will throw an error if both are set.\n\n### `markdown-it.settings.ts`\n\nThis is an optional file you can create anywhere.\nIt should export a default sync or async function that accepts a single argument (the markdown-it instance configured by domstack) and returns a modified markdown-it instance.\nUse this to add custom markdown-it plugins or modify the parser configuration.\nHere are some examples:\n\n```typescript\nimport markdownItContainer from 'markdown-it-container'\nimport markdownItPlantuml from 'markdown-it-plantuml'\nimport type { MarkdownIt } from 'markdown-it'\n\nconst markdownItSettingsOverride = async (md: MarkdownIt) => {\n  // Add custom plugins\n  md.use(markdownItContainer, 'spoiler', {\n    validate: (params: string) => {\n      return params.trim().match(/^spoiler\\s+(.*)$/) !== null\n    },\n    render: (tokens: any[], idx: number) => {\n      const m = tokens[idx].info.trim().match(/^spoiler\\s+(.*)$/)\n      if (tokens[idx].nesting === 1) {\n        return '<details><summary>' + md.utils.escapeHtml(m[1]) + '</summary>\\n'\n      } else {\n        return '</details>\\n'\n      }\n    }\n  })\n\n  md.use(markdownItPlantuml)\n\n  return md\n}\n\nexport default markdownItSettingsOverride\n```\n\n```typescript\nimport markdownIt, { MarkdownIt } from 'markdown-it'\nimport myCustomPlugin from './my-custom-plugin'\n\nconst markdownItSettingsOverride = async (md: MarkdownIt) => {\n  // Create a new instance with different settings\n  const newMd = markdownIt({\n    html: false,        // Disable HTML tags in source\n    breaks: true,       // Convert \\n to <br>\n    linkify: false,     // Disable auto-linking\n  })\n\n  // Add only the plugins you want\n  newMd.use(myCustomPlugin)\n\n  return newMd\n}\n\nexport default markdownItSettingsOverride\n```\n\nBy default, DOMStack ships with the following markdown-it plugins enabled:\n\n- [markdown-it](https://github.com/markdown-it/markdown-it)\n- [markdown-it-footnote](https://github.com/markdown-it/markdown-it-footnote)\n- [markdown-it-highlightjs](https://github.com/valeriangalliat/markdown-it-highlightjs)\n- [markdown-it-emoji](https://github.com/markdown-it/markdown-it-emoji)\n- [markdown-it-sub](https://github.com/markdown-it/markdown-it-sub)\n- [markdown-it-sup](https://github.com/markdown-it/markdown-it-sup)\n- [markdown-it-deflist](https://github.com/markdown-it/markdown-it-deflist)\n- [markdown-it-ins](https://github.com/markdown-it/markdown-it-ins)\n- [markdown-it-mark](https://github.com/markdown-it/markdown-it-mark)\n- [markdown-it-abbr](https://github.com/markdown-it/markdown-it-abbr)\n- [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists)\n- [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor)\n- [markdown-it-attrs](https://github.com/arve0/markdown-it-attrs)\n- [markdown-it-table-of-contents](https://github.com/cmaas/markdown-it-table-of-contents)\n\n## Variables\n\nPages and Layouts receive an object with the following parameters:\n\n- `vars`: An object with the variables of `global.vars.ts`, `global.data.js`, `page.vars.ts`, and any front-matter or `vars` exports from the page merged together.\n- `pages`: An array of [`PageData`](https://github.com/bcomnes/d omstack/blob/master/lib/build-pages/page-data.js) instances for every page in the site build. Use this array to introspect pages to generate feeds and index pages.\n- `page`: An object of the page being rendered with the following parameters:\n  - `type`: The type of page (`md`, `html`, or `js`)\n  - `path`: The directory path for the page.\n  - `outputName`: The output name of the final file.\n  - `outputRelname`: The relative output name/path of the output file.\n  - `pageFile`: Raw `src` path details of the page file\n  - `pageStyle`: file info if the page has a page style\n  - `clientBundle`: file info if the page has a page js bundle\n  - `pageVars`: file info if the page has a page vars\n\nTemplate files receive a similar set of variables:\n\n- `vars`: An object with the variables of `global.vars.ts`\n- `pages`: An array of [`PageData`](https://github.com/bcomnes/domstack/blob/master/lib/build-pages/page-data.js) instances for every page in the site build. Use this array to introspect pages to generate feeds and index pages.\n- `template`: An object of the template file data being rendered.\n\n### Derived global data (Advanced)\n\nFor data that aggregates across multiple pages — like blog indexes, sitemaps, or RSS feed content — use [`global.data.js`](#globaldatajs). That file runs once per build, receives the raw page list, and merges its return value into `globalVars` so every page, layout, and template can read it via `vars`.\n\nSee the [`global.data.js`](#globaldatajs) section under [Global Assets](#global-assets) for a full example.\n\n## TypeScript Support\n\n`domstack` supports **TypeScript** via native type-stripping in Node.js.\n\n- **Requires Node.js ≥23** *(built-in)* or **Node.js 22** with the `NODE_OPTIONS=\"--experimental-strip-types\" domstack` env variable.\n- Seamlessly mix `.ts`, `.mts`, `.cts` files alongside `.js`, `.mjs`, `.cjs`.\n- No explicit compilation step needed—Node.js handles type stripping at runtime.\n- Fully compatible with existing `domstack` file naming conventions.\n- Anywhere DOMStack loads JS files, it can now load TS files.\n\n### Supported File Types\n\nAnywhere you can use  a `.js`, `.mjs` or `.cjs` file in domstack, you can now use `.ts`, `.mts`, `.cts`.\nWhen running in a Node.js context, [type-stripping](https://nodejs.org/api/typescript.html#type-stripping) is used.\nWhen running in a web client context, [esbuild](https://esbuild.github.io/content-types/#typescript) type stripping is used.\nType stripping provides 0 type checking, so be sure to set up `tsc` and `tsconfig.json` so you can catch type errors while editing or in CI.\n\n### Recommended `tsconfig.json`\n\nInstall [@voxpelli/tsconfig](https://ghub.io/@voxpelli/tsconfig) which provides type checking in `.js` and `.ts` files and preconfigured for `--no-emit` and extend with type stripping friendly rules:\n\n```json\n{\n  \"extends\": \"@voxpelli/tsconfig/node20.json\",\n  \"compilerOptions\": {\n    \"skipLibCheck\": true,\n    \"erasableSyntaxOnly\": true,\n    \"allowImportingTsExtensions\": true,\n    \"rewriteRelativeImportExtensions\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\n    \"**/*\",\n  ],\n  \"exclude\": [\n    \"**/*.js\",\n    \"node_modules\",\n    \"coverage\",\n    \".github\"\n  ]\n}\n```\n\n### Using TypeScript with domstack Types\n\nYou can use `domstack`'s built-in types to strongly type your layout, page, and template functions. The following types are available:\n\n```ts\nimport type {\n  LayoutFunction,\n  AsyncLayoutFunction,\n  GlobalDataFunction,\n  AsyncGlobalDataFunction,\n  PageFunction,\n  AsyncPageFunction,\n  TemplateFunction,\n  TemplateAsyncIterator\n} from '@domstack/static'\n```\n\n> **Note:** All function types have both synchronous and asynchronous variants (e.g., `LayoutFunction` and `AsyncLayoutFunction`). Use the async variants when your function is an `async` function.\n\nThey are all generic and accept a variable template that you can develop and share between files.\n\n#### Advanced Type Parameters for PageFunction and LayoutFunction\n\n`PageFunction` and `LayoutFunction` support additional template parameters for precise return type control:\n\n**PageFunction<T, U>**\n- `T` - The type of variables passed to the page (required)\n- `U` - The return type of the page function (optional, defaults to `any`)\n\n**LayoutFunction<T, U, V>**\n- `T` - The type of variables passed to the layout (required)\n- `U` - The type of content received from pages as `children` (optional, defaults to `any`)\n- `V` - The return type of the layout function (optional, defaults to `string`)\n\nThis allows pages to return custom types (like VDOM or JSON) while ensuring layouts produce HTML strings:\n\n```ts\n// Define custom types\ntype VDOMNode = {\n  type: string\n  props: Record<string, any>\n  children: Array<VDOMNode | string>\n}\n\n// Page returns VDOM\nconst page: PageFunction<{title: string}, VDOMNode> = ({ vars }) => ({\n  type: 'h1',\n  props: {},\n  children: [vars.title]\n})\n\n// Layout accepts VDOM, returns HTML string\nconst layout: LayoutFunction<{site: string}, VDOMNode, string> = ({ children }) => {\n  const html = renderVDOM(children) // Convert VDOM to HTML\n  return `<html><body>${html}</body></html>`\n}\n```\n\n## Design Goals\n\n- Convention over configuration. All configuration should be optional, and at most it should be minimal.\n- Align with the `index.html`/`README.md` pattern.\n- The HTML is the source of truth.\n- Don't re-implement what the browser already provides!\n  - No magic `<link>` or `<a>` tag magic.\n  - Don't facilitate client side routing. The browser supports routing by default.s\n  - Accept the nature of the medium. Browsers browse html documents. Don't facilitate shared state between pages.\n- Library agnostic. Strings are the interchange format.\n- Pages are shallow apps. New page, new blank canvas.\n- Just a program. `js` pages and layouts are just JavaScript programs. This provides an escape hatch to do anything. Use any template language want, but probably just use tagged template literals.\n- Steps remain orthogonal. Static file copying, css and js bundling, are mere optimizations on top of the `src` folder. The `src` folder should essentially run in the browser. Each step in a `domstack` build should work independent of the others. This allows for maximal parallelism when building.\n- Standardized entrypoints. Every page in a `domstack` site has a natural and obvious entrypoint. There is no magic redirection to learn about.\n- Pages build into `index.html` files inside of named directories. This allows for naturally colocated assets next to the page, pretty URLs and full support for relative URLs.\n- No parallel directory structures. You should never be forced to have two directories with identical layouts to put files next to each other. Everything should be colocatable.\n- Markdown entrypoints are named `page.md` or `README.md`. `README.md` allows for the `src` folder to be fully navigable in GitHub and other git repo hosting providing a natural hosted CMS UI. `page.md` is preferred when GitHub navigability is not a concern.\n- Real TC39 ESM from the start.\n- Garbage in, garbage out. Don't over-correct bad input.\n- Conventions + standards. Vanilla file types. No new file extensions. No weird syntax to learn. Language tools should just work because you aren't doing anything weird or out of band.\n- Encourage directly runnable source files. Direct run is an incredible, undervalued feature more people should learn to use.\n- Support typescript, via ts-in-js and type stripping features. Leave type checking to tsc.\n- Embrace the now. Limit support on features that let one pretend they are working with future ecosystem features e.g. pseudo esm (technology predictions nearly always are wrong!)\n\n## FAQ\n\nWhy DOMStack?\n\n:   DOMStack is named after the DOM (Document Object Model) and the concept of stacking technologies together to build websites. It represents the layering of HTML, CSS, and JavaScript in a cohesive build system.\n\nHow does `domstack` relate to [`sitedown`](https://ghub.io/sitedown)\n\n:   `domstack` used to be called `siteup` which is sort of like \"markup\", which is related to \"markdown\", which inspired the project `sitedown` to which `domstack` is a spiritual off-shoot of. Put a folder of web documents in your `domstack` build system, and generate a website.\n\n## Examples\n\nLook at [examples](./examples/) and `domstack` [dependents](https://github.com/bcomnes/domstack/network/dependents) for some examples how `domstack` can work.\n\n## Implementation\n\n`domstack` bundles the best tools for every technology in the stack:\n\n- `js` and `css` is bundled with [`esbuild`](https://github.com/evanw/esbuild).\n- `md` is processed with [markdown-it](https://github.com/markdown-it/markdown-it).\n- static files are processed with [cpx2](https://github.com/bcomnes/cpx2).\n- `ts` support via native typestripping in Node.js and esbuild.\n- `jsx/tsx` support via esbuild.\n\nThese tools are treated as implementation details, but they may be exposed more in the future. The idea is that they can be swapped out for better tools in the future if they don't make it.\n\n### Build Process Flow\n\nThe following diagram illustrates the DomStack build process:\n\n```\n                    ┌─────────────┐\n                    │    START    │\n                    └──────┬──────┘\n                           │\n                           ▼\n                 ┌──────────────────┐\n                 │ identifyPages()  │\n                 │                  │\n                 │ • Find pages     │\n                 │ • Find layouts   │\n                 │ • Find templates │\n                 │ • Find globals   │\n                 │ • Find settings  │\n                 └────────┬─────────┘\n                          │\n                          │\n      ┌───────────────────┼───────────────────┐\n      │                   │                   │\n      ▼                   ▼                   ▼\n┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐\n│ buildEsbuild()  │ │ buildStatic()   │ │  buildCopy()    │\n│                 │ │                 │ │                 │\n│ • Bundle JS/CSS │ │ • Copy static   │ │ • Copy extra    │\n│ • Generate      │ │   files         │ │   directories   │\n│   metafile      │ │ (if enabled)    │ │   from opts     │\n└────────┬────────┘ └────────┬────────┘ └────────┬────────┘\n         │                   │                   │\n         └───────────────────┼───────────────────┘\n                             │\n                             ▼\n                    ┌──────────────────┐\n                    │  buildPages()    │\n                    │                  │\n                    │ • Process HTML   │\n                    │ • Process MD     │\n                    │ • Process JS     │\n                    │ • Apply layouts  │\n                    └────────┬─────────┘\n                             │\n                             ▼\n                    ┌──────────────────┐\n                    │  Return Results  │\n                    │                  │\n                    │ • siteData       │\n                    │ • esbuildResults │\n                    │ • staticResults  │\n                    │ • copyResults    │\n                    │ • pageResults    │\n                    │ • warnings       │\n                    └──────────────────┘\n```\n\nThe build process follows these key steps:\n\n1. **Page identification** - Scans the source directory to identify all pages, layouts, templates, and global assets\n2. **Destination preparation** - Ensures the destination directory is ready for the build output\n3. **Parallel asset processing** - Three operations run concurrently:\n   - JavaScript and CSS bundling via esbuild\n   - Static file copying (when enabled)\n   - Additional directory copying (from `--copy` options)\n4. **Page building** - Processes all pages, applying layouts and generating final HTML\n\nThis architecture allows for efficient parallel processing of independent tasks while maintaining the correct build order dependencies.\n\n#### buildPages() Detail\n\nThe `buildPages()` step processes pages in parallel with a concurrency limit:\n\n```\n                    ┌──────────────────┐\n                    │  buildPages()    │\n                    └────────┬─────────┘\n                             │\n                    ┌────────▼─────────┐\n                    │ Resolve Once:    │\n                    │ • Global vars    │\n                    │ • All layouts    │\n                    └────────┬─────────┘\n                             │\n                ┌────────────▼───────────────┐\n                │  Parallel Page Init        │\n                │(Concurrency: min(CPUs, 24))│\n                └────────────┬───────────────┘\n                             │\n        ┌────────────────────┼────────────────────┐\n        │                    │                    │\n        ▼                    ▼                    ▼\n┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐\n│  MD Page Task   │    │ HTML Page Task  │    │  JS Page Task   │\n├─────────────────┤    ├─────────────────┤    ├─────────────────┤\n│ ┌─────────────┐ │    │ ┌─────────────┐ │    │ ┌─────────────┐ │\n│ │1. Parse MD  │ │    │ │1. Read .html│ │    │ │1. Import .js│ │\n│ │ frontmatter │ │    │ │   file      │ │    │ │   module    │ │\n│ └──────┬──────┘ │    │ └──────┬──────┘ │    │ └──────┬──────┘ │\n│        ▼        │    │        ▼        │    │        ▼        │\n│ ┌─────────────┐ │    │ ┌─────────────┐ │    │ ┌─────────────┐ │\n│ │2. Variable  │ │    │ │2. Variable  │ │    │ │2. Variable  │ │\n│ │  Resolution │ │    │ │  Resolution │ │    │ │  Resolution │ │\n│ └──────┬──────┘ │    │ └──────┬──────┘ │    │ └──────┬──────┘ │\n│        ▼        │    │        ▼        │    │        ▼        │\n│ ┌─────────────┐ │    │ ┌─────────────┐ │    │ ┌─────────────┐ │\n│ │ builder +   │ │    │ │page.vars.js │ │    │ │  Exported   │ │\n│ │ page.vars.js│ │    │ │             │ │    │ │  + page.vars│ │\n│ └─────────────┘ │    │ └─────────────┘ │    │ └─────────────┘ │\n└─────────────────┘    └─────────────────┘    └─────────────────┘\n         │                      │                      │\n         └──────────────────────┼──────────────────────┘\n                                │\n                                ▼\n                    ┌───────────────────────┐\n                    │  global.data.js runs  │\n                    │  (receives PageData[])│\n                    │  stamps vars on pages │\n                    └───────────┬───────────┘\n                                │\n                                ▼\n                ┌───────────────────────────────┐\n                │  Parallel Render + Write      │\n                │ (Concurrency: min(CPUs, 24))  │\n                └───────────────────────────────┘\n```\n\nVariable Resolution Layers:\n- **Global vars** - Site-wide variables from `global.vars.js` (resolved once)\n- **Layout vars** - Layout-specific variables from layout functions (resolved once)\n- **Page-specific vars** vary by type:\n  - **MD pages**: page.vars.js + builder vars (from frontmatter)\n  - **HTML pages**: page.vars.js\n  - **JS pages**: exported vars → page.vars.js\n- **Global data** - Derived variables from `global.data.js`, stamped onto every page after all pages initialize (resolved once, after page init)\n\n### Watch Mode\n\nWhen you run `domstack --watch` (or `domstack -w`), domstack performs an initial build and then watches for changes, rebuilding only what's necessary. Watch mode uses two independent watch loops:\n\n**esbuild watch** — JS and CSS bundles are handled by esbuild's native `context.watch()`. In watch mode, output filenames are stable (no content hashes), so bundle changes never require a page HTML rebuild. Browser-sync detects the updated files on disk and reloads the browser directly.\n\n**chokidar watch** — Page files, layouts, templates, and config files are watched by chokidar. When a file changes, domstack determines the minimal set of pages to rebuild using dependency tracking maps built at startup.\n\n#### What triggers what\n\n| Change | Rebuild scope |\n|---|---|\n| `page.js`, `page.ts`, `page.html`, `page.md`, or `page.vars.*` | Only that page |\n| A file imported by a `page.js` or `page.vars.*` | Only the pages that import it (transitively) |\n| A layout file (`*.layout.js`) | Only the pages using that layout |\n| A file imported by a layout | Only the pages using the affected layout(s) |\n| A template file (`*.template.js`) | Only that template |\n| A file imported by a template | Only the affected template(s) |\n| `markdown-it.settings.*` | All `.md` pages |\n| `global.data.*` | All pages and templates |\n| `global.vars.*` or `esbuild.settings.*` | Full rebuild (esbuild restart + all pages) |\n| `client.js`, `style.css`, `*.layout.css`, `*.layout.client.*`, `global.client.*`, `global.css`, `*.worker.*` | esbuild handles it — no page rebuild |\n| Adding or removing an esbuild entry point (e.g. creating a new `client.js`) | esbuild restart + only the affected page(s) |\n| Adding or removing any other file | Full rebuild |\n\n#### Dependency tracking\n\ndomstack uses [`@11ty/dependency-tree-typescript`](https://github.com/11ty/dependency-tree-typescript) to statically analyze ESM imports in page files, layout files, and template files. This means if your `page.js` imports a shared utility module, changing that module will only rebuild the pages that depend on it — not the entire site.\n\nesbuild tracks its own entry point dependencies independently. Changing a file imported by `client.js` will trigger an esbuild rebundle but will not trigger a page rebuild, since watch mode uses stable filenames.\n\n#### Stable filenames\n\nIn watch mode, esbuild uses `[dir]/[name]` output patterns instead of `[dir]/[name]-[hash]`. This means the `<script>` and `<link>` tags in page HTML always point to the same filenames. When esbuild rebundles, the file contents change but the filenames don't, so page HTML never needs to be re-rendered just because a bundle changed.\n\n#### Build serialization\n\nChokidar events are serialized through a promise chain, so rapid saves don't cause","readmeFilename":"README.md"}