@pagesmith/docs 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -31
- package/REFERENCE.md +494 -0
- package/dist/cli/bin.mjs +197 -10
- package/dist/cli/bin.mjs.map +1 -1
- package/dist/index.d.mts +120 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/preset.mjs +1 -1
- package/dist/schemas/index.d.mts +2 -1615
- package/dist/schemas/index.mjs +2 -263
- package/dist/site-dJ3MiiW3.mjs +1756 -0
- package/dist/site-dJ3MiiW3.mjs.map +1 -0
- package/package.json +14 -23
- package/theme/components/Html.tsx +67 -1
- package/theme/layouts/DocHome.tsx +8 -1
- package/theme/layouts/DocPage.tsx +80 -2
- package/theme/styles/content/page-meta.css +65 -0
- package/theme/styles/main.css +1 -0
- package/dist/abap-DriO5VG6.mjs +0 -5
- package/dist/abap-DriO5VG6.mjs.map +0 -1
- package/dist/actionscript-3-G6toewHp.mjs +0 -5
- package/dist/actionscript-3-G6toewHp.mjs.map +0 -1
- package/dist/ada-C_QiJ0Pq.mjs +0 -5
- package/dist/ada-C_QiJ0Pq.mjs.map +0 -1
- package/dist/andromeeda-CoIEPgYR.mjs +0 -6
- package/dist/andromeeda-CoIEPgYR.mjs.map +0 -1
- package/dist/angular-html-D9wIlok7.mjs +0 -35
- package/dist/angular-html-D9wIlok7.mjs.map +0 -1
- package/dist/angular-ts-Dxk7hl9Z.mjs +0 -29
- package/dist/angular-ts-Dxk7hl9Z.mjs.map +0 -1
- package/dist/apache-B1aRGcgY.mjs +0 -5
- package/dist/apache-B1aRGcgY.mjs.map +0 -1
- package/dist/apex-FoK4UgwA.mjs +0 -5
- package/dist/apex-FoK4UgwA.mjs.map +0 -1
- package/dist/apl-DwmTqCJs.mjs +0 -19
- package/dist/apl-DwmTqCJs.mjs.map +0 -1
- package/dist/applescript-eBeY0Hp4.mjs +0 -5
- package/dist/applescript-eBeY0Hp4.mjs.map +0 -1
- package/dist/ara-CkIucGv1.mjs +0 -5
- package/dist/ara-CkIucGv1.mjs.map +0 -1
- package/dist/asciidoc-AIdrECCR.mjs +0 -5
- package/dist/asciidoc-AIdrECCR.mjs.map +0 -1
- package/dist/asm-CflFLM6a.mjs +0 -5
- package/dist/asm-CflFLM6a.mjs.map +0 -1
- package/dist/astro-DLt5gl0n.mjs +0 -21
- package/dist/astro-DLt5gl0n.mjs.map +0 -1
- package/dist/aurora-x-DbqEqkUT.mjs +0 -6
- package/dist/aurora-x-DbqEqkUT.mjs.map +0 -1
- package/dist/awk-Br_61sCS.mjs +0 -5
- package/dist/awk-Br_61sCS.mjs.map +0 -1
- package/dist/ayu-dark-DdJXJf7U.mjs +0 -6
- package/dist/ayu-dark-DdJXJf7U.mjs.map +0 -1
- package/dist/ayu-light-Bg-9Hujp.mjs +0 -6
- package/dist/ayu-light-Bg-9Hujp.mjs.map +0 -1
- package/dist/ayu-mirage-7v6-qMvl.mjs +0 -6
- package/dist/ayu-mirage-7v6-qMvl.mjs.map +0 -1
- package/dist/ballerina-D-8GYl8R.mjs +0 -5
- package/dist/ballerina-D-8GYl8R.mjs.map +0 -1
- package/dist/bat-CJ4nIaxw.mjs +0 -5
- package/dist/bat-CJ4nIaxw.mjs.map +0 -1
- package/dist/beancount-DFPOglwN.mjs +0 -5
- package/dist/beancount-DFPOglwN.mjs.map +0 -1
- package/dist/berry-DiM_rwEt.mjs +0 -5
- package/dist/berry-DiM_rwEt.mjs.map +0 -1
- package/dist/bibtex-ryU9pJLB.mjs +0 -5
- package/dist/bibtex-ryU9pJLB.mjs.map +0 -1
- package/dist/bicep-DFoNCrG3.mjs +0 -5
- package/dist/bicep-DFoNCrG3.mjs.map +0 -1
- package/dist/bird2-C3EaFiUY.mjs +0 -5
- package/dist/bird2-C3EaFiUY.mjs.map +0 -1
- package/dist/blade-Cwq7FVfH.mjs +0 -23
- package/dist/blade-Cwq7FVfH.mjs.map +0 -1
- package/dist/bsl-Ci4vkNj8.mjs +0 -8
- package/dist/bsl-Ci4vkNj8.mjs.map +0 -1
- package/dist/c-D7oHDxxD.mjs +0 -8
- package/dist/c-D7oHDxxD.mjs.map +0 -1
- package/dist/c3-D5hU-x2t.mjs +0 -5
- package/dist/c3-D5hU-x2t.mjs.map +0 -1
- package/dist/cadence-B-Z42oTz.mjs +0 -5
- package/dist/cadence-B-Z42oTz.mjs.map +0 -1
- package/dist/cairo-BpET0YK1.mjs +0 -8
- package/dist/cairo-BpET0YK1.mjs.map +0 -1
- package/dist/catppuccin-frappe-0BRWFMtJ.mjs +0 -6
- package/dist/catppuccin-frappe-0BRWFMtJ.mjs.map +0 -1
- package/dist/catppuccin-latte-VaqpfzxV.mjs +0 -6
- package/dist/catppuccin-latte-VaqpfzxV.mjs.map +0 -1
- package/dist/catppuccin-macchiato-qrypRbXk.mjs +0 -6
- package/dist/catppuccin-macchiato-qrypRbXk.mjs.map +0 -1
- package/dist/catppuccin-mocha-Dvb6gv4O.mjs +0 -6
- package/dist/catppuccin-mocha-Dvb6gv4O.mjs.map +0 -1
- package/dist/clarity-egx-5RLz.mjs +0 -5
- package/dist/clarity-egx-5RLz.mjs.map +0 -1
- package/dist/clojure-N5xIuTbG.mjs +0 -5
- package/dist/clojure-N5xIuTbG.mjs.map +0 -1
- package/dist/cmake-CYzXNVI_.mjs +0 -5
- package/dist/cmake-CYzXNVI_.mjs.map +0 -1
- package/dist/cobol-DuznKErk.mjs +0 -13
- package/dist/cobol-DuznKErk.mjs.map +0 -1
- package/dist/codeowners-BaallJaj.mjs +0 -5
- package/dist/codeowners-BaallJaj.mjs.map +0 -1
- package/dist/codeql-BIahF8Ga.mjs +0 -5
- package/dist/codeql-BIahF8Ga.mjs.map +0 -1
- package/dist/coffee-t6lXzaXy.mjs +0 -8
- package/dist/coffee-t6lXzaXy.mjs.map +0 -1
- package/dist/common-lisp-bLMBDFt9.mjs +0 -5
- package/dist/common-lisp-bLMBDFt9.mjs.map +0 -1
- package/dist/coq-h9z5p2Ui.mjs +0 -5
- package/dist/coq-h9z5p2Ui.mjs.map +0 -1
- package/dist/cpp-D6_V2gI1.mjs +0 -27
- package/dist/cpp-D6_V2gI1.mjs.map +0 -1
- package/dist/crystal-BH-Qv6Rl.mjs +0 -21
- package/dist/crystal-BH-Qv6Rl.mjs.map +0 -1
- package/dist/csharp-BbHR3YVQ.mjs +0 -5
- package/dist/csharp-BbHR3YVQ.mjs.map +0 -1
- package/dist/css-Wu--EEs5.mjs +0 -8
- package/dist/css-Wu--EEs5.mjs.map +0 -1
- package/dist/csv-CRvIpAc5.mjs +0 -5
- package/dist/csv-CRvIpAc5.mjs.map +0 -1
- package/dist/cue-B8A_h-kS.mjs +0 -5
- package/dist/cue-B8A_h-kS.mjs.map +0 -1
- package/dist/cypher-B8mmimml.mjs +0 -5
- package/dist/cypher-B8mmimml.mjs.map +0 -1
- package/dist/d-Ddz3GmKc.mjs +0 -5
- package/dist/d-Ddz3GmKc.mjs.map +0 -1
- package/dist/dark-plus-BjClkp3W.mjs +0 -6
- package/dist/dark-plus-BjClkp3W.mjs.map +0 -1
- package/dist/dart-BOQAkR91.mjs +0 -5
- package/dist/dart-BOQAkR91.mjs.map +0 -1
- package/dist/dax-D3YKmfop.mjs +0 -5
- package/dist/dax-D3YKmfop.mjs.map +0 -1
- package/dist/desktop-wo52vLHj.mjs +0 -5
- package/dist/desktop-wo52vLHj.mjs.map +0 -1
- package/dist/diff-nA9OrLiI.mjs +0 -5
- package/dist/diff-nA9OrLiI.mjs.map +0 -1
- package/dist/docker-BgWkJ5L9.mjs +0 -5
- package/dist/docker-BgWkJ5L9.mjs.map +0 -1
- package/dist/dotenv-90bAk1yC.mjs +0 -5
- package/dist/dotenv-90bAk1yC.mjs.map +0 -1
- package/dist/dracula-EYPvHKFq.mjs +0 -6
- package/dist/dracula-EYPvHKFq.mjs.map +0 -1
- package/dist/dracula-soft-Bb4JppaT.mjs +0 -6
- package/dist/dracula-soft-Bb4JppaT.mjs.map +0 -1
- package/dist/dream-maker-DbEH6ABX.mjs +0 -5
- package/dist/dream-maker-DbEH6ABX.mjs.map +0 -1
- package/dist/edge-CiNxTnJq.mjs +0 -15
- package/dist/edge-CiNxTnJq.mjs.map +0 -1
- package/dist/elixir-M-tyUuPQ.mjs +0 -8
- package/dist/elixir-M-tyUuPQ.mjs.map +0 -1
- package/dist/elm-CPy7ntV_.mjs +0 -8
- package/dist/elm-CPy7ntV_.mjs.map +0 -1
- package/dist/emacs-lisp-Brxx0Sbt.mjs +0 -5
- package/dist/emacs-lisp-Brxx0Sbt.mjs.map +0 -1
- package/dist/engine-javascript-CjxD84Z_.mjs +0 -3058
- package/dist/engine-javascript-CjxD84Z_.mjs.map +0 -1
- package/dist/engine-oniguruma-B2buYh9y.mjs +0 -389
- package/dist/engine-oniguruma-B2buYh9y.mjs.map +0 -1
- package/dist/erb-CP0kP8S1.mjs +0 -13
- package/dist/erb-CP0kP8S1.mjs.map +0 -1
- package/dist/erlang-Ji96SB8L.mjs +0 -8
- package/dist/erlang-Ji96SB8L.mjs.map +0 -1
- package/dist/everforest-dark-mXu75VmU.mjs +0 -6
- package/dist/everforest-dark-mXu75VmU.mjs.map +0 -1
- package/dist/everforest-light-B0xAPlUp.mjs +0 -6
- package/dist/everforest-light-B0xAPlUp.mjs.map +0 -1
- package/dist/fennel-DZeZiT-Z.mjs +0 -5
- package/dist/fennel-DZeZiT-Z.mjs.map +0 -1
- package/dist/fish-BW_XyVWl.mjs +0 -5
- package/dist/fish-BW_XyVWl.mjs.map +0 -1
- package/dist/fluent-D5wjIx4S.mjs +0 -5
- package/dist/fluent-D5wjIx4S.mjs.map +0 -1
- package/dist/fortran-fixed-form-pFDq8aul.mjs +0 -8
- package/dist/fortran-fixed-form-pFDq8aul.mjs.map +0 -1
- package/dist/fortran-free-form-B6T0euh-.mjs +0 -5
- package/dist/fortran-free-form-B6T0euh-.mjs.map +0 -1
- package/dist/fsharp-DFzfL_uZ.mjs +0 -8
- package/dist/fsharp-DFzfL_uZ.mjs.map +0 -1
- package/dist/gdresource-DZkMKM9Q.mjs +0 -13
- package/dist/gdresource-DZkMKM9Q.mjs.map +0 -1
- package/dist/gdscript-DwtQqEcX.mjs +0 -5
- package/dist/gdscript-DwtQqEcX.mjs.map +0 -1
- package/dist/gdshader-rDwkUCaa.mjs +0 -5
- package/dist/gdshader-rDwkUCaa.mjs.map +0 -1
- package/dist/genie-BfhM6kGv.mjs +0 -5
- package/dist/genie-BfhM6kGv.mjs.map +0 -1
- package/dist/gherkin-G-JA03FJ.mjs +0 -5
- package/dist/gherkin-G-JA03FJ.mjs.map +0 -1
- package/dist/git-commit-drj2jjWh.mjs +0 -8
- package/dist/git-commit-drj2jjWh.mjs.map +0 -1
- package/dist/git-rebase-CaohyQnS.mjs +0 -8
- package/dist/git-rebase-CaohyQnS.mjs.map +0 -1
- package/dist/github-dark-CTenoRQ8.mjs +0 -6
- package/dist/github-dark-CTenoRQ8.mjs.map +0 -1
- package/dist/github-dark-default-Con6b1h-.mjs +0 -6
- package/dist/github-dark-default-Con6b1h-.mjs.map +0 -1
- package/dist/github-dark-dimmed-CaAnvWw3.mjs +0 -6
- package/dist/github-dark-dimmed-CaAnvWw3.mjs.map +0 -1
- package/dist/github-dark-high-contrast-COm7y1Rv.mjs +0 -6
- package/dist/github-dark-high-contrast-COm7y1Rv.mjs.map +0 -1
- package/dist/github-light-D74aa4dO.mjs +0 -6
- package/dist/github-light-D74aa4dO.mjs.map +0 -1
- package/dist/github-light-default-BBVzuVUz.mjs +0 -6
- package/dist/github-light-default-BBVzuVUz.mjs.map +0 -1
- package/dist/github-light-high-contrast-CqxSzsLD.mjs +0 -6
- package/dist/github-light-high-contrast-CqxSzsLD.mjs.map +0 -1
- package/dist/gleam-DzWkrReo.mjs +0 -5
- package/dist/gleam-DzWkrReo.mjs.map +0 -1
- package/dist/glimmer-js-BNQY0kPX.mjs +0 -17
- package/dist/glimmer-js-BNQY0kPX.mjs.map +0 -1
- package/dist/glimmer-ts-DO-qafJY.mjs +0 -17
- package/dist/glimmer-ts-DO-qafJY.mjs.map +0 -1
- package/dist/glsl-wU4MxvvQ.mjs +0 -10
- package/dist/glsl-wU4MxvvQ.mjs.map +0 -1
- package/dist/gn-DVz3m6tN.mjs +0 -5
- package/dist/gn-DVz3m6tN.mjs.map +0 -1
- package/dist/gnuplot-D4teOAbn.mjs +0 -5
- package/dist/gnuplot-D4teOAbn.mjs.map +0 -1
- package/dist/go-DcqYXZDE.mjs +0 -5
- package/dist/go-DcqYXZDE.mjs.map +0 -1
- package/dist/graphql-CAmmtGyG.mjs +0 -19
- package/dist/graphql-CAmmtGyG.mjs.map +0 -1
- package/dist/groovy-BdsJaZey.mjs +0 -5
- package/dist/groovy-BdsJaZey.mjs.map +0 -1
- package/dist/gruvbox-dark-hard-CGsJkBU-.mjs +0 -6
- package/dist/gruvbox-dark-hard-CGsJkBU-.mjs.map +0 -1
- package/dist/gruvbox-dark-medium-uVadnpDA.mjs +0 -6
- package/dist/gruvbox-dark-medium-uVadnpDA.mjs.map +0 -1
- package/dist/gruvbox-dark-soft-CGpZgcKq.mjs +0 -6
- package/dist/gruvbox-dark-soft-CGpZgcKq.mjs.map +0 -1
- package/dist/gruvbox-light-hard-BXZeSfoD.mjs +0 -6
- package/dist/gruvbox-light-hard-BXZeSfoD.mjs.map +0 -1
- package/dist/gruvbox-light-medium-D7mAxe90.mjs +0 -6
- package/dist/gruvbox-light-medium-D7mAxe90.mjs.map +0 -1
- package/dist/gruvbox-light-soft-enFNSJ1V.mjs +0 -6
- package/dist/gruvbox-light-soft-enFNSJ1V.mjs.map +0 -1
- package/dist/hack-DgaC5QUw.mjs +0 -13
- package/dist/hack-DgaC5QUw.mjs.map +0 -1
- package/dist/haml-1vrxYPQe.mjs +0 -15
- package/dist/haml-1vrxYPQe.mjs.map +0 -1
- package/dist/handlebars-BOf036w9.mjs +0 -17
- package/dist/handlebars-BOf036w9.mjs.map +0 -1
- package/dist/haskell-BgXObw3Z.mjs +0 -5
- package/dist/haskell-BgXObw3Z.mjs.map +0 -1
- package/dist/haxe-SN6gQnv7.mjs +0 -5
- package/dist/haxe-SN6gQnv7.mjs.map +0 -1
- package/dist/hcl-DfQ78ybU.mjs +0 -5
- package/dist/hcl-DfQ78ybU.mjs.map +0 -1
- package/dist/hjson-DsbHj1Vu.mjs +0 -5
- package/dist/hjson-DsbHj1Vu.mjs.map +0 -1
- package/dist/hlsl-DErhWTj4.mjs +0 -5
- package/dist/hlsl-DErhWTj4.mjs.map +0 -1
- package/dist/horizon-bright-BLpSmqnO.mjs +0 -6
- package/dist/horizon-bright-BLpSmqnO.mjs.map +0 -1
- package/dist/horizon-mHk0xSKw.mjs +0 -6
- package/dist/horizon-mHk0xSKw.mjs.map +0 -1
- package/dist/houston-CJWIjsF-.mjs +0 -6
- package/dist/houston-CJWIjsF-.mjs.map +0 -1
- package/dist/html-derivative-CoKpUZPA.mjs +0 -8
- package/dist/html-derivative-CoKpUZPA.mjs.map +0 -1
- package/dist/html-hLCdjm8s.mjs +0 -15
- package/dist/html-hLCdjm8s.mjs.map +0 -1
- package/dist/http-Cu2vb2m1.mjs +0 -17
- package/dist/http-Cu2vb2m1.mjs.map +0 -1
- package/dist/hurl-DXLUiPe9.mjs +0 -15
- package/dist/hurl-DXLUiPe9.mjs.map +0 -1
- package/dist/hxml-D53ff3CT.mjs +0 -8
- package/dist/hxml-D53ff3CT.mjs.map +0 -1
- package/dist/hy-V5YDnsp0.mjs +0 -5
- package/dist/hy-V5YDnsp0.mjs.map +0 -1
- package/dist/imba-Dj8CXVx-.mjs +0 -5
- package/dist/imba-Dj8CXVx-.mjs.map +0 -1
- package/dist/ini-BBJUwrOG.mjs +0 -5
- package/dist/ini-BBJUwrOG.mjs.map +0 -1
- package/dist/java-YvKbK6tX.mjs +0 -8
- package/dist/java-YvKbK6tX.mjs.map +0 -1
- package/dist/javascript-YIAaXWRu.mjs +0 -8
- package/dist/javascript-YIAaXWRu.mjs.map +0 -1
- package/dist/jinja-ENyZ39OR.mjs +0 -12
- package/dist/jinja-ENyZ39OR.mjs.map +0 -1
- package/dist/jison-a-QW5GR4.mjs +0 -8
- package/dist/jison-a-QW5GR4.mjs.map +0 -1
- package/dist/json-D_p_sVuw.mjs +0 -8
- package/dist/json-D_p_sVuw.mjs.map +0 -1
- package/dist/json5-DC6Kkd4p.mjs +0 -5
- package/dist/json5-DC6Kkd4p.mjs.map +0 -1
- package/dist/jsonc-CXqrxP7Z.mjs +0 -5
- package/dist/jsonc-CXqrxP7Z.mjs.map +0 -1
- package/dist/jsonl-CzqgMhZd.mjs +0 -5
- package/dist/jsonl-CzqgMhZd.mjs.map +0 -1
- package/dist/jsonnet-Hvy31yDW.mjs +0 -5
- package/dist/jsonnet-Hvy31yDW.mjs.map +0 -1
- package/dist/jssm-CKXXM0Nd.mjs +0 -5
- package/dist/jssm-CKXXM0Nd.mjs.map +0 -1
- package/dist/jsx-Cmr67-nO.mjs +0 -8
- package/dist/jsx-Cmr67-nO.mjs.map +0 -1
- package/dist/julia-apY6-EoT.mjs +0 -19
- package/dist/julia-apY6-EoT.mjs.map +0 -1
- package/dist/just-DPxowZX-.mjs +0 -21
- package/dist/just-DPxowZX-.mjs.map +0 -1
- package/dist/kanagawa-dragon-bgbtpXkX.mjs +0 -6
- package/dist/kanagawa-dragon-bgbtpXkX.mjs.map +0 -1
- package/dist/kanagawa-lotus-CAjM2aBD.mjs +0 -6
- package/dist/kanagawa-lotus-CAjM2aBD.mjs.map +0 -1
- package/dist/kanagawa-wave-gUF-XydY.mjs +0 -6
- package/dist/kanagawa-wave-gUF-XydY.mjs.map +0 -1
- package/dist/kdl-DakeRkny.mjs +0 -5
- package/dist/kdl-DakeRkny.mjs.map +0 -1
- package/dist/kotlin-Cy2z7uIJ.mjs +0 -5
- package/dist/kotlin-Cy2z7uIJ.mjs.map +0 -1
- package/dist/kusto-8vFexomq.mjs +0 -5
- package/dist/kusto-8vFexomq.mjs.map +0 -1
- package/dist/laserwave-afq0Xxwk.mjs +0 -6
- package/dist/laserwave-afq0Xxwk.mjs.map +0 -1
- package/dist/latex-D_F2h8-H.mjs +0 -8
- package/dist/latex-D_F2h8-H.mjs.map +0 -1
- package/dist/lean-IHm98qhW.mjs +0 -5
- package/dist/lean-IHm98qhW.mjs.map +0 -1
- package/dist/less-D6RfQ6-S.mjs +0 -5
- package/dist/less-D6RfQ6-S.mjs.map +0 -1
- package/dist/light-plus-Dwa6Dmsm.mjs +0 -6
- package/dist/light-plus-Dwa6Dmsm.mjs.map +0 -1
- package/dist/liquid-DK7BdQ-d.mjs +0 -17
- package/dist/liquid-DK7BdQ-d.mjs.map +0 -1
- package/dist/llvm-CbsqsAF1.mjs +0 -5
- package/dist/llvm-CbsqsAF1.mjs.map +0 -1
- package/dist/log-CutLVNLV.mjs +0 -5
- package/dist/log-CutLVNLV.mjs.map +0 -1
- package/dist/logo-DNTC5lxi.mjs +0 -5
- package/dist/logo-DNTC5lxi.mjs.map +0 -1
- package/dist/lua-NCVDi2Y_.mjs +0 -10
- package/dist/lua-NCVDi2Y_.mjs.map +0 -1
- package/dist/luau-Z-b9t2YR.mjs +0 -5
- package/dist/luau-Z-b9t2YR.mjs.map +0 -1
- package/dist/make-D7o-TjTO.mjs +0 -5
- package/dist/make-D7o-TjTO.mjs.map +0 -1
- package/dist/markdown-CEvLuIE_.mjs +0 -5
- package/dist/markdown-CEvLuIE_.mjs.map +0 -1
- package/dist/markdown-config-BGDiDMhB.d.mts +0 -2094
- package/dist/markdown-config-BGDiDMhB.d.mts.map +0 -1
- package/dist/marko-DyPWMVoi.mjs +0 -17
- package/dist/marko-DyPWMVoi.mjs.map +0 -1
- package/dist/material-theme-BMSwLkhz.mjs +0 -6
- package/dist/material-theme-BMSwLkhz.mjs.map +0 -1
- package/dist/material-theme-darker-DREhSOvw.mjs +0 -6
- package/dist/material-theme-darker-DREhSOvw.mjs.map +0 -1
- package/dist/material-theme-lighter-egkNOF68.mjs +0 -6
- package/dist/material-theme-lighter-egkNOF68.mjs.map +0 -1
- package/dist/material-theme-ocean-CNqBAXQm.mjs +0 -6
- package/dist/material-theme-ocean-CNqBAXQm.mjs.map +0 -1
- package/dist/material-theme-palenight-DtcONgpr.mjs +0 -6
- package/dist/material-theme-palenight-DtcONgpr.mjs.map +0 -1
- package/dist/matlab-DHZHeFXY.mjs +0 -5
- package/dist/matlab-DHZHeFXY.mjs.map +0 -1
- package/dist/mdc-MKPEEsGA.mjs +0 -15
- package/dist/mdc-MKPEEsGA.mjs.map +0 -1
- package/dist/mdx-ClLOyMcG.mjs +0 -5
- package/dist/mdx-ClLOyMcG.mjs.map +0 -1
- package/dist/mermaid-CfX58h2h.mjs +0 -5
- package/dist/mermaid-CfX58h2h.mjs.map +0 -1
- package/dist/min-dark-CvIB8xOx.mjs +0 -6
- package/dist/min-dark-CvIB8xOx.mjs.map +0 -1
- package/dist/min-light-DnoFQoeu.mjs +0 -6
- package/dist/min-light-DnoFQoeu.mjs.map +0 -1
- package/dist/mipsasm-BPlrYcYb.mjs +0 -5
- package/dist/mipsasm-BPlrYcYb.mjs.map +0 -1
- package/dist/mojo-C5Qzk_lA.mjs +0 -5
- package/dist/mojo-C5Qzk_lA.mjs.map +0 -1
- package/dist/monokai-CmoRmG4x.mjs +0 -6
- package/dist/monokai-CmoRmG4x.mjs.map +0 -1
- package/dist/moonbit-BzaO7bLo.mjs +0 -5
- package/dist/moonbit-BzaO7bLo.mjs.map +0 -1
- package/dist/move-CAZmkwHx.mjs +0 -5
- package/dist/move-CAZmkwHx.mjs.map +0 -1
- package/dist/narrat-DN2gLj7A.mjs +0 -5
- package/dist/narrat-DN2gLj7A.mjs.map +0 -1
- package/dist/nextflow-DhVPPjdW.mjs +0 -8
- package/dist/nextflow-DhVPPjdW.mjs.map +0 -1
- package/dist/nextflow-groovy-DJq82mRo.mjs +0 -5
- package/dist/nextflow-groovy-DJq82mRo.mjs.map +0 -1
- package/dist/nginx-CU-DGOv1.mjs +0 -8
- package/dist/nginx-CU-DGOv1.mjs.map +0 -1
- package/dist/night-owl-Cs13ScSs.mjs +0 -6
- package/dist/night-owl-Cs13ScSs.mjs.map +0 -1
- package/dist/night-owl-light--HbEFF7Y.mjs +0 -6
- package/dist/night-owl-light--HbEFF7Y.mjs.map +0 -1
- package/dist/nim-3UbGj8cc.mjs +0 -23
- package/dist/nim-3UbGj8cc.mjs.map +0 -1
- package/dist/nix-CjXcUl9k.mjs +0 -9
- package/dist/nix-CjXcUl9k.mjs.map +0 -1
- package/dist/nord-C9GqXk2p.mjs +0 -6
- package/dist/nord-C9GqXk2p.mjs.map +0 -1
- package/dist/nushell-C4iFdrTc.mjs +0 -5
- package/dist/nushell-C4iFdrTc.mjs.map +0 -1
- package/dist/objective-c-CXuDGuMm.mjs +0 -5
- package/dist/objective-c-CXuDGuMm.mjs.map +0 -1
- package/dist/objective-cpp-V9yvCIRm.mjs +0 -5
- package/dist/objective-cpp-V9yvCIRm.mjs.map +0 -1
- package/dist/ocaml-D9fCj6sT.mjs +0 -5
- package/dist/ocaml-D9fCj6sT.mjs.map +0 -1
- package/dist/odin-CAKGLqrj.mjs +0 -5
- package/dist/odin-CAKGLqrj.mjs.map +0 -1
- package/dist/one-dark-pro-DW7BmY6Q.mjs +0 -6
- package/dist/one-dark-pro-DW7BmY6Q.mjs.map +0 -1
- package/dist/one-light-DCu0Wv9N.mjs +0 -6
- package/dist/one-light-DCu0Wv9N.mjs.map +0 -1
- package/dist/openscad-BdLZBBab.mjs +0 -5
- package/dist/openscad-BdLZBBab.mjs.map +0 -1
- package/dist/pascal-nsk9MKFb.mjs +0 -5
- package/dist/pascal-nsk9MKFb.mjs.map +0 -1
- package/dist/perl-DI9oLKmv.mjs +0 -19
- package/dist/perl-DI9oLKmv.mjs.map +0 -1
- package/dist/php-DJjzFdsM.mjs +0 -21
- package/dist/php-DJjzFdsM.mjs.map +0 -1
- package/dist/pkl-BVtC2QFe.mjs +0 -5
- package/dist/pkl-BVtC2QFe.mjs.map +0 -1
- package/dist/plastic-qUgYNoeW.mjs +0 -6
- package/dist/plastic-qUgYNoeW.mjs.map +0 -1
- package/dist/plsql-BwM0DOLE.mjs +0 -5
- package/dist/plsql-BwM0DOLE.mjs.map +0 -1
- package/dist/po-D39EqRsl.mjs +0 -5
- package/dist/po-D39EqRsl.mjs.map +0 -1
- package/dist/poimandres-DPRzGPvx.mjs +0 -6
- package/dist/poimandres-DPRzGPvx.mjs.map +0 -1
- package/dist/polar-DCBzWT3J.mjs +0 -5
- package/dist/polar-DCBzWT3J.mjs.map +0 -1
- package/dist/postcss-L6y-bzEw.mjs +0 -5
- package/dist/postcss-L6y-bzEw.mjs.map +0 -1
- package/dist/powerquery-BHkUTyux.mjs +0 -5
- package/dist/powerquery-BHkUTyux.mjs.map +0 -1
- package/dist/powershell-C80dlfD8.mjs +0 -5
- package/dist/powershell-C80dlfD8.mjs.map +0 -1
- package/dist/prisma-D407qtUw.mjs +0 -5
- package/dist/prisma-D407qtUw.mjs.map +0 -1
- package/dist/prolog-CSrn8-6K.mjs +0 -5
- package/dist/prolog-CSrn8-6K.mjs.map +0 -1
- package/dist/proto-ClvDy0H0.mjs +0 -5
- package/dist/proto-ClvDy0H0.mjs.map +0 -1
- package/dist/pug-Cyyu0V2y.mjs +0 -15
- package/dist/pug-Cyyu0V2y.mjs.map +0 -1
- package/dist/puppet-D5ZQtSNi.mjs +0 -5
- package/dist/puppet-D5ZQtSNi.mjs.map +0 -1
- package/dist/purescript-30PxZSjT.mjs +0 -5
- package/dist/purescript-30PxZSjT.mjs.map +0 -1
- package/dist/python-CpiNX4Ip.mjs +0 -5
- package/dist/python-CpiNX4Ip.mjs.map +0 -1
- package/dist/qml-PuKhTmY-.mjs +0 -8
- package/dist/qml-PuKhTmY-.mjs.map +0 -1
- package/dist/qmldir-BTwcIF6g.mjs +0 -5
- package/dist/qmldir-BTwcIF6g.mjs.map +0 -1
- package/dist/qss-DcpQyHuk.mjs +0 -5
- package/dist/qss-DcpQyHuk.mjs.map +0 -1
- package/dist/r-DcW8EcF5.mjs +0 -8
- package/dist/r-DcW8EcF5.mjs.map +0 -1
- package/dist/racket-D-BwrG5z.mjs +0 -5
- package/dist/racket-D-BwrG5z.mjs.map +0 -1
- package/dist/raku-CM1N1WTp.mjs +0 -5
- package/dist/raku-CM1N1WTp.mjs.map +0 -1
- package/dist/razor-C912Hs6M.mjs +0 -13
- package/dist/razor-C912Hs6M.mjs.map +0 -1
- package/dist/red-DhGHw_i_.mjs +0 -6
- package/dist/red-DhGHw_i_.mjs.map +0 -1
- package/dist/reg-MlBfIgTN.mjs +0 -5
- package/dist/reg-MlBfIgTN.mjs.map +0 -1
- package/dist/regexp-CEVpExph.mjs +0 -8
- package/dist/regexp-CEVpExph.mjs.map +0 -1
- package/dist/rel-Dg_W2E_N.mjs +0 -5
- package/dist/rel-Dg_W2E_N.mjs.map +0 -1
- package/dist/riscv-BoH7mqNI.mjs +0 -5
- package/dist/riscv-BoH7mqNI.mjs.map +0 -1
- package/dist/ron-DbOWX1T7.mjs +0 -5
- package/dist/ron-DbOWX1T7.mjs.map +0 -1
- package/dist/rose-pine-78rugKGO.mjs +0 -6
- package/dist/rose-pine-78rugKGO.mjs.map +0 -1
- package/dist/rose-pine-dawn-C_mYSEtu.mjs +0 -6
- package/dist/rose-pine-dawn-C_mYSEtu.mjs.map +0 -1
- package/dist/rose-pine-moon-Cz7-JQvG.mjs +0 -6
- package/dist/rose-pine-moon-Cz7-JQvG.mjs.map +0 -1
- package/dist/rosmsg-Ca1BpyBh.mjs +0 -5
- package/dist/rosmsg-Ca1BpyBh.mjs.map +0 -1
- package/dist/rst-DbIJV67W.mjs +0 -25
- package/dist/rst-DbIJV67W.mjs.map +0 -1
- package/dist/ruby-D-Lps7Dp.mjs +0 -33
- package/dist/ruby-D-Lps7Dp.mjs.map +0 -1
- package/dist/rust-Dk6HN1uF.mjs +0 -5
- package/dist/rust-Dk6HN1uF.mjs.map +0 -1
- package/dist/sas-QckC_qvJ.mjs +0 -8
- package/dist/sas-QckC_qvJ.mjs.map +0 -1
- package/dist/sass-BWOQVuIy.mjs +0 -5
- package/dist/sass-BWOQVuIy.mjs.map +0 -1
- package/dist/scala-BoffQEnY.mjs +0 -5
- package/dist/scala-BoffQEnY.mjs.map +0 -1
- package/dist/schemas/index.d.mts.map +0 -1
- package/dist/schemas/index.mjs.map +0 -1
- package/dist/schemas-By1qE0sQ.mjs +0 -3881
- package/dist/schemas-By1qE0sQ.mjs.map +0 -1
- package/dist/scheme-C2D8wvUe.mjs +0 -5
- package/dist/scheme-C2D8wvUe.mjs.map +0 -1
- package/dist/scss-D1vWunvk.mjs +0 -10
- package/dist/scss-D1vWunvk.mjs.map +0 -1
- package/dist/sdbl-DkThjfrg.mjs +0 -5
- package/dist/sdbl-DkThjfrg.mjs.map +0 -1
- package/dist/shaderlab-D0NLokaw.mjs +0 -8
- package/dist/shaderlab-D0NLokaw.mjs.map +0 -1
- package/dist/shellscript-BHpEag8P.mjs +0 -8
- package/dist/shellscript-BHpEag8P.mjs.map +0 -1
- package/dist/shellsession-CSdmCfg4.mjs +0 -8
- package/dist/shellsession-CSdmCfg4.mjs.map +0 -1
- package/dist/site-D8l4ghX0.mjs +0 -71441
- package/dist/site-D8l4ghX0.mjs.map +0 -1
- package/dist/slack-dark-Cj8kL6BM.mjs +0 -6
- package/dist/slack-dark-Cj8kL6BM.mjs.map +0 -1
- package/dist/slack-ochin-B4Rna-gD.mjs +0 -6
- package/dist/slack-ochin-B4Rna-gD.mjs.map +0 -1
- package/dist/smalltalk-ZNQAnLNC.mjs +0 -5
- package/dist/smalltalk-ZNQAnLNC.mjs.map +0 -1
- package/dist/snazzy-light-CF7MTUt6.mjs +0 -6
- package/dist/snazzy-light-CF7MTUt6.mjs.map +0 -1
- package/dist/solarized-dark-DBFHIE1d.mjs +0 -6
- package/dist/solarized-dark-DBFHIE1d.mjs.map +0 -1
- package/dist/solarized-light-Del516-O.mjs +0 -6
- package/dist/solarized-light-Del516-O.mjs.map +0 -1
- package/dist/solidity-Ddf3MOD2.mjs +0 -5
- package/dist/solidity-Ddf3MOD2.mjs.map +0 -1
- package/dist/soy-PW0jpJKW.mjs +0 -8
- package/dist/soy-PW0jpJKW.mjs.map +0 -1
- package/dist/sparql-rX-q1CB9.mjs +0 -8
- package/dist/sparql-rX-q1CB9.mjs.map +0 -1
- package/dist/splunk-DcREbx5k.mjs +0 -5
- package/dist/splunk-DcREbx5k.mjs.map +0 -1
- package/dist/sql-Cq_hpY16.mjs +0 -8
- package/dist/sql-Cq_hpY16.mjs.map +0 -1
- package/dist/ssh-config-DIv0Kb8E.mjs +0 -5
- package/dist/ssh-config-DIv0Kb8E.mjs.map +0 -1
- package/dist/stata-rEmfzZT7.mjs +0 -8
- package/dist/stata-rEmfzZT7.mjs.map +0 -1
- package/dist/stylus-DHanz1Kd.mjs +0 -5
- package/dist/stylus-DHanz1Kd.mjs.map +0 -1
- package/dist/surrealql-BdfgI90j.mjs +0 -8
- package/dist/surrealql-BdfgI90j.mjs.map +0 -1
- package/dist/svelte-DFFWgqCr.mjs +0 -17
- package/dist/svelte-DFFWgqCr.mjs.map +0 -1
- package/dist/swift-Ci7klDIa.mjs +0 -5
- package/dist/swift-Ci7klDIa.mjs.map +0 -1
- package/dist/synthwave-84-T5fF9-Op.mjs +0 -6
- package/dist/synthwave-84-T5fF9-Op.mjs.map +0 -1
- package/dist/system-verilog-tLSd9PYh.mjs +0 -5
- package/dist/system-verilog-tLSd9PYh.mjs.map +0 -1
- package/dist/systemd-C_LIvN4y.mjs +0 -5
- package/dist/systemd-C_LIvN4y.mjs.map +0 -1
- package/dist/talonscript-2cIfb9F4.mjs +0 -5
- package/dist/talonscript-2cIfb9F4.mjs.map +0 -1
- package/dist/tasl-iwLzpKVu.mjs +0 -5
- package/dist/tasl-iwLzpKVu.mjs.map +0 -1
- package/dist/tcl-DR2zhegR.mjs +0 -5
- package/dist/tcl-DR2zhegR.mjs.map +0 -1
- package/dist/templ-BDCp727o.mjs +0 -15
- package/dist/templ-BDCp727o.mjs.map +0 -1
- package/dist/terraform-BH4YC6Zk.mjs +0 -5
- package/dist/terraform-BH4YC6Zk.mjs.map +0 -1
- package/dist/tex-DGRDr7pd.mjs +0 -8
- package/dist/tex-DGRDr7pd.mjs.map +0 -1
- package/dist/tokyo-night-YpyXNs_N.mjs +0 -6
- package/dist/tokyo-night-YpyXNs_N.mjs.map +0 -1
- package/dist/toml-CECsyL8x.mjs +0 -5
- package/dist/toml-CECsyL8x.mjs.map +0 -1
- package/dist/ts-tags-BsG9I5cd.mjs +0 -61
- package/dist/ts-tags-BsG9I5cd.mjs.map +0 -1
- package/dist/tsv-BwwAUdIn.mjs +0 -5
- package/dist/tsv-BwwAUdIn.mjs.map +0 -1
- package/dist/tsx-qx39NaGS.mjs +0 -8
- package/dist/tsx-qx39NaGS.mjs.map +0 -1
- package/dist/turtle-D8n7HFvE.mjs +0 -5
- package/dist/turtle-D8n7HFvE.mjs.map +0 -1
- package/dist/twig-DsMUiWk8.mjs +0 -21
- package/dist/twig-DsMUiWk8.mjs.map +0 -1
- package/dist/typescript-BZXFn-rd.mjs +0 -8
- package/dist/typescript-BZXFn-rd.mjs.map +0 -1
- package/dist/typespec-ClgDzShT.mjs +0 -5
- package/dist/typespec-ClgDzShT.mjs.map +0 -1
- package/dist/typst-CMN2lhh3.mjs +0 -5
- package/dist/typst-CMN2lhh3.mjs.map +0 -1
- package/dist/v-CA1cYsER.mjs +0 -5
- package/dist/v-CA1cYsER.mjs.map +0 -1
- package/dist/vala-DuBY1WKl.mjs +0 -5
- package/dist/vala-DuBY1WKl.mjs.map +0 -1
- package/dist/vb-XQBHWfW8.mjs +0 -5
- package/dist/vb-XQBHWfW8.mjs.map +0 -1
- package/dist/verilog-CWqhvrSz.mjs +0 -5
- package/dist/verilog-CWqhvrSz.mjs.map +0 -1
- package/dist/vesper-CigfTEKg.mjs +0 -6
- package/dist/vesper-CigfTEKg.mjs.map +0 -1
- package/dist/vhdl-C67Bhzjr.mjs +0 -5
- package/dist/vhdl-C67Bhzjr.mjs.map +0 -1
- package/dist/viml-C26cD_wa.mjs +0 -5
- package/dist/viml-C26cD_wa.mjs.map +0 -1
- package/dist/vitesse-black-DYCj3nJd.mjs +0 -6
- package/dist/vitesse-black-DYCj3nJd.mjs.map +0 -1
- package/dist/vitesse-dark-BMGIMsRz.mjs +0 -6
- package/dist/vitesse-dark-BMGIMsRz.mjs.map +0 -1
- package/dist/vitesse-light-SKJOp9ZR.mjs +0 -6
- package/dist/vitesse-light-SKJOp9ZR.mjs.map +0 -1
- package/dist/vue-bb5YUHg6.mjs +0 -33
- package/dist/vue-bb5YUHg6.mjs.map +0 -1
- package/dist/vue-html-ypB-H6rb.mjs +0 -8
- package/dist/vue-html-ypB-H6rb.mjs.map +0 -1
- package/dist/vue-vine-Cl_j-Bb5.mjs +0 -21
- package/dist/vue-vine-Cl_j-Bb5.mjs.map +0 -1
- package/dist/vyper-gBkdcGC5.mjs +0 -5
- package/dist/vyper-gBkdcGC5.mjs.map +0 -1
- package/dist/wasm-B1KmdQo5.mjs +0 -9
- package/dist/wasm-B1KmdQo5.mjs.map +0 -1
- package/dist/wasm-D4mFcPzE.mjs +0 -5
- package/dist/wasm-D4mFcPzE.mjs.map +0 -1
- package/dist/wenyan-D1TI9OZw.mjs +0 -5
- package/dist/wenyan-D1TI9OZw.mjs.map +0 -1
- package/dist/wgsl-DzVADIua.mjs +0 -5
- package/dist/wgsl-DzVADIua.mjs.map +0 -1
- package/dist/wikitext-DPnM1XoL.mjs +0 -5
- package/dist/wikitext-DPnM1XoL.mjs.map +0 -1
- package/dist/wit-Bewokpy8.mjs +0 -5
- package/dist/wit-Bewokpy8.mjs.map +0 -1
- package/dist/wolfram-DVQXO29Z.mjs +0 -5
- package/dist/wolfram-DVQXO29Z.mjs.map +0 -1
- package/dist/xml-TYYGqgP3.mjs +0 -10
- package/dist/xml-TYYGqgP3.mjs.map +0 -1
- package/dist/xsl-BOev1i40.mjs +0 -8
- package/dist/xsl-BOev1i40.mjs.map +0 -1
- package/dist/yaml-Xue9e-YO.mjs +0 -8
- package/dist/yaml-Xue9e-YO.mjs.map +0 -1
- package/dist/zenscript-CwrU69w6.mjs +0 -5
- package/dist/zenscript-CwrU69w6.mjs.map +0 -1
- package/dist/zig-NT9tMYQ2.mjs +0 -5
- package/dist/zig-NT9tMYQ2.mjs.map +0 -1
|
@@ -0,0 +1,1756 @@
|
|
|
1
|
+
import { exec, execFileSync, execSync } from "child_process";
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "fs";
|
|
3
|
+
import JSON5 from "json5";
|
|
4
|
+
import { basename, dirname, extname, join, relative, resolve } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { copyPublicFiles } from "@pagesmith/core/assets";
|
|
7
|
+
import { buildCss } from "@pagesmith/core/css";
|
|
8
|
+
import { processMarkdown } from "@pagesmith/core/markdown";
|
|
9
|
+
import { availableParallelism } from "os";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { SKIP, visit } from "unist-util-visit";
|
|
12
|
+
import { createHash } from "crypto";
|
|
13
|
+
import { Fragment, h } from "@pagesmith/core/jsx-runtime";
|
|
14
|
+
import { createServer } from "http";
|
|
15
|
+
import { createServer as createServer$1 } from "net";
|
|
16
|
+
import { watch } from "chokidar";
|
|
17
|
+
import { WebSocketServer } from "ws";
|
|
18
|
+
//#region src/config.ts
|
|
19
|
+
function defineDocsConfig(config) {
|
|
20
|
+
return config;
|
|
21
|
+
}
|
|
22
|
+
function loadDocsConfig(configPath) {
|
|
23
|
+
const resolvedConfigPath = resolve(configPath ?? join(process.cwd(), "pagesmith.config.json5"));
|
|
24
|
+
if (!existsSync(resolvedConfigPath)) return {};
|
|
25
|
+
return JSON5.parse(readFileSync(resolvedConfigPath, "utf-8"));
|
|
26
|
+
}
|
|
27
|
+
/** Prefix a path with a base path, avoiding double slashes. */
|
|
28
|
+
function withBase(basePath, path) {
|
|
29
|
+
const base = basePath.replace(/\/+$/, "");
|
|
30
|
+
if (!base) return path;
|
|
31
|
+
if (path.startsWith(base)) return path;
|
|
32
|
+
return `${base}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
33
|
+
}
|
|
34
|
+
/** Detect basePath and origin from git remote URL. */
|
|
35
|
+
function detectGitOrigin(rootDir) {
|
|
36
|
+
try {
|
|
37
|
+
const remoteUrl = execSync("git remote get-url origin", {
|
|
38
|
+
cwd: rootDir,
|
|
39
|
+
stdio: [
|
|
40
|
+
"pipe",
|
|
41
|
+
"pipe",
|
|
42
|
+
"pipe"
|
|
43
|
+
],
|
|
44
|
+
encoding: "utf-8"
|
|
45
|
+
}).trim();
|
|
46
|
+
let match = remoteUrl.match(/github\.com[:/]([^/]+)\/([^/.]+?)(?:\.git)?$/);
|
|
47
|
+
if (match) {
|
|
48
|
+
const [, owner, repo] = match;
|
|
49
|
+
return {
|
|
50
|
+
basePath: `/${repo}`,
|
|
51
|
+
origin: `https://${owner}.github.io`,
|
|
52
|
+
repoName: repo,
|
|
53
|
+
editLinkHost: "github"
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
match = remoteUrl.match(/gitlab\.com[:/]([^/]+)\/([^/.]+?)(?:\.git)?$/);
|
|
57
|
+
if (match) {
|
|
58
|
+
const [, owner, repo] = match;
|
|
59
|
+
return {
|
|
60
|
+
basePath: `/${repo}`,
|
|
61
|
+
origin: `https://${owner}.gitlab.io`,
|
|
62
|
+
repoName: repo,
|
|
63
|
+
editLinkHost: "gitlab"
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
match = remoteUrl.match(/bitbucket\.org[:/]([^/]+)\/([^/.]+?)(?:\.git)?$/);
|
|
67
|
+
if (match) {
|
|
68
|
+
const [, , repo] = match;
|
|
69
|
+
return {
|
|
70
|
+
basePath: `/${repo}`,
|
|
71
|
+
repoName: repo,
|
|
72
|
+
editLinkHost: "bitbucket"
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
} catch {}
|
|
76
|
+
}
|
|
77
|
+
function readPackageJson(rootDir) {
|
|
78
|
+
const pkgPath = join(rootDir, "package.json");
|
|
79
|
+
if (!existsSync(pkgPath)) return void 0;
|
|
80
|
+
try {
|
|
81
|
+
return JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
82
|
+
} catch {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function resolveContentDir(rootDir, explicit) {
|
|
87
|
+
if (explicit) return resolve(rootDir, explicit);
|
|
88
|
+
const docsDir = resolve(rootDir, "docs");
|
|
89
|
+
if (existsSync(docsDir)) return docsDir;
|
|
90
|
+
return resolve(rootDir, "content");
|
|
91
|
+
}
|
|
92
|
+
function resolveDocsConfig(configPath, overrides) {
|
|
93
|
+
const resolvedConfigPath = resolve(configPath ?? join(process.cwd(), "pagesmith.config.json5"));
|
|
94
|
+
const rootDir = dirname(resolvedConfigPath);
|
|
95
|
+
const userConfig = loadDocsConfig(resolvedConfigPath);
|
|
96
|
+
const packageName = basename(rootDir);
|
|
97
|
+
const pkg = readPackageJson(rootDir);
|
|
98
|
+
const pkgDisplayName = pkg?.name?.replace(/^@[^/]+\//, "");
|
|
99
|
+
const gitInfo = detectGitOrigin(rootDir);
|
|
100
|
+
const basePath = (overrides?.basePath ?? process.env.BASE_URL ?? userConfig.basePath ?? gitInfo?.basePath ?? "/").replace(/\/+$/, "");
|
|
101
|
+
const contentDir = resolveContentDir(rootDir, userConfig.contentDir);
|
|
102
|
+
const publicDir = resolve(rootDir, userConfig.publicDir ?? "public");
|
|
103
|
+
let resolvedFavicon;
|
|
104
|
+
let resolvedFaviconFallback = false;
|
|
105
|
+
if (userConfig.favicon === false) resolvedFavicon = false;
|
|
106
|
+
else if (typeof userConfig.favicon === "string") resolvedFavicon = resolve(rootDir, userConfig.favicon);
|
|
107
|
+
else {
|
|
108
|
+
const svgPath = join(publicDir, "favicon.svg");
|
|
109
|
+
const icoPath = join(publicDir, "favicon.ico");
|
|
110
|
+
if (existsSync(svgPath)) {
|
|
111
|
+
resolvedFavicon = svgPath;
|
|
112
|
+
if (existsSync(icoPath)) resolvedFaviconFallback = icoPath;
|
|
113
|
+
} else if (existsSync(icoPath)) resolvedFavicon = icoPath;
|
|
114
|
+
else resolvedFavicon = join(dirname(fileURLToPath(import.meta.resolve("@pagesmith/core/package.json"))), "assets", "favicon.svg");
|
|
115
|
+
}
|
|
116
|
+
const appleTouchIconPath = join(publicDir, "apple-touch-icon.png");
|
|
117
|
+
const resolvedAppleTouchIcon = existsSync(appleTouchIconPath) ? appleTouchIconPath : false;
|
|
118
|
+
const assets = /* @__PURE__ */ new Map();
|
|
119
|
+
if (userConfig.assets) for (const [outputPath, sources] of Object.entries(userConfig.assets)) {
|
|
120
|
+
const resolved = sources.map((source) => resolve(rootDir, source));
|
|
121
|
+
assets.set(outputPath, resolved);
|
|
122
|
+
}
|
|
123
|
+
let socialImage;
|
|
124
|
+
if (userConfig.theme?.socialImage) socialImage = userConfig.theme.socialImage;
|
|
125
|
+
else for (const ext of [
|
|
126
|
+
"png",
|
|
127
|
+
"jpg",
|
|
128
|
+
"jpeg"
|
|
129
|
+
]) if (existsSync(join(publicDir, `og-image.${ext}`))) {
|
|
130
|
+
socialImage = `og-image.${ext}`;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
let editLink;
|
|
134
|
+
if (userConfig.editLink) {
|
|
135
|
+
const repo = userConfig.editLink.repo.replace(/\/+$/, "");
|
|
136
|
+
const branch = userConfig.editLink.branch ?? "main";
|
|
137
|
+
const label = userConfig.editLink.label ?? "Edit this page";
|
|
138
|
+
let editPattern;
|
|
139
|
+
if (repo.includes("gitlab.com") || repo.includes("gitlab.")) editPattern = `${repo}/-/edit/${branch}`;
|
|
140
|
+
else if (repo.includes("bitbucket.org") || repo.includes("bitbucket.")) editPattern = `${repo}/src/${branch}`;
|
|
141
|
+
else editPattern = `${repo}/edit/${branch}`;
|
|
142
|
+
editLink = {
|
|
143
|
+
repo,
|
|
144
|
+
branch,
|
|
145
|
+
label,
|
|
146
|
+
editPattern
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
rootDir,
|
|
151
|
+
contentDir,
|
|
152
|
+
outDir: overrides?.outDir ?? resolve(rootDir, userConfig.outDir ?? "gh-pages"),
|
|
153
|
+
publicDir,
|
|
154
|
+
basePath,
|
|
155
|
+
homeLink: userConfig.homeLink,
|
|
156
|
+
name: userConfig.name ?? userConfig.title ?? pkgDisplayName ?? packageName,
|
|
157
|
+
title: userConfig.title ?? userConfig.name ?? pkgDisplayName ?? packageName,
|
|
158
|
+
description: userConfig.description ?? pkg?.description ?? "Documentation site powered by @pagesmith/docs",
|
|
159
|
+
origin: userConfig.origin ?? pkg?.homepage ?? gitInfo?.origin ?? "https://example.com",
|
|
160
|
+
language: userConfig.language ?? "en",
|
|
161
|
+
footerLinks: userConfig.footerLinks ?? [],
|
|
162
|
+
search: {
|
|
163
|
+
enabled: userConfig.search?.enabled ?? true,
|
|
164
|
+
showImages: userConfig.search?.showImages ?? false,
|
|
165
|
+
showSubResults: userConfig.search?.showSubResults ?? true,
|
|
166
|
+
pagefindFlags: userConfig.search?.pagefindFlags ?? []
|
|
167
|
+
},
|
|
168
|
+
sidebar: { collapsible: userConfig.sidebar?.collapsible ?? true },
|
|
169
|
+
favicon: resolvedFavicon,
|
|
170
|
+
faviconFallback: resolvedFaviconFallback,
|
|
171
|
+
appleTouchIcon: resolvedAppleTouchIcon,
|
|
172
|
+
editLink,
|
|
173
|
+
lastUpdated: userConfig.lastUpdated ?? false,
|
|
174
|
+
sitemap: userConfig.sitemap ?? true,
|
|
175
|
+
socialImage,
|
|
176
|
+
theme: userConfig.theme,
|
|
177
|
+
analytics: userConfig.analytics,
|
|
178
|
+
markdown: userConfig.markdown,
|
|
179
|
+
homeConfigFile: userConfig.home?.configFile ? resolve(rootDir, userConfig.home.configFile) : resolve(rootDir, contentDir, "home.json5"),
|
|
180
|
+
packages: userConfig.packages,
|
|
181
|
+
server: {
|
|
182
|
+
devPort: userConfig.server?.devPort ?? 3e3,
|
|
183
|
+
previewPort: userConfig.server?.previewPort ?? 4e3,
|
|
184
|
+
strictPort: userConfig.server?.strictPort ?? false
|
|
185
|
+
},
|
|
186
|
+
assets,
|
|
187
|
+
_userConfig: userConfig
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function readJson5File(filePath) {
|
|
191
|
+
if (!existsSync(filePath)) return void 0;
|
|
192
|
+
return JSON5.parse(readFileSync(filePath, "utf-8"));
|
|
193
|
+
}
|
|
194
|
+
function toTitleCase(value) {
|
|
195
|
+
return value.replace(/[-_]/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
196
|
+
}
|
|
197
|
+
function getPackageDir() {
|
|
198
|
+
return resolve(import.meta.dirname, "..");
|
|
199
|
+
}
|
|
200
|
+
function getThemeRoot() {
|
|
201
|
+
return resolve(getPackageDir(), "theme");
|
|
202
|
+
}
|
|
203
|
+
function getThemeStylesEntry() {
|
|
204
|
+
return resolve(getThemeRoot(), "styles/main.css");
|
|
205
|
+
}
|
|
206
|
+
function getThemeRuntimeEntry() {
|
|
207
|
+
return resolve(getThemeRoot(), "runtime/main.ts");
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Validate a resolved docs config. Returns issues found.
|
|
211
|
+
* Checks required fields, verifies referenced directories and asset files exist.
|
|
212
|
+
*/
|
|
213
|
+
function validateConfig(config) {
|
|
214
|
+
const issues = [];
|
|
215
|
+
const uc = config._userConfig;
|
|
216
|
+
const hasExplicitName = uc ? !!(uc.name || uc.title) : config.name !== basename(config.rootDir);
|
|
217
|
+
const hasExplicitTitle = uc ? !!(uc.title || uc.name) : config.title !== basename(config.rootDir);
|
|
218
|
+
if (!hasExplicitName) issues.push({
|
|
219
|
+
field: "name",
|
|
220
|
+
message: "Missing \"name\" in pagesmith.config.json5 — using directory name as fallback.",
|
|
221
|
+
severity: "warn"
|
|
222
|
+
});
|
|
223
|
+
if (!hasExplicitTitle) issues.push({
|
|
224
|
+
field: "title",
|
|
225
|
+
message: "Missing \"title\" in pagesmith.config.json5 — using directory name as fallback.",
|
|
226
|
+
severity: "warn"
|
|
227
|
+
});
|
|
228
|
+
if (config.description === "Documentation site powered by @pagesmith/docs") issues.push({
|
|
229
|
+
field: "description",
|
|
230
|
+
message: "Missing \"description\" in pagesmith.config.json5 — using default placeholder.",
|
|
231
|
+
severity: "warn"
|
|
232
|
+
});
|
|
233
|
+
if (config.origin === "https://example.com") issues.push({
|
|
234
|
+
field: "origin",
|
|
235
|
+
message: "Missing \"origin\" in pagesmith.config.json5 — canonical URLs will use https://example.com. Set this to your production URL.",
|
|
236
|
+
severity: "warn"
|
|
237
|
+
});
|
|
238
|
+
if (!existsSync(config.contentDir)) issues.push({
|
|
239
|
+
field: "contentDir",
|
|
240
|
+
message: `Content directory does not exist: ${config.contentDir}`,
|
|
241
|
+
severity: "error"
|
|
242
|
+
});
|
|
243
|
+
if (!existsSync(config.publicDir)) {}
|
|
244
|
+
for (const [outputPath, sources] of config.assets) for (const sourcePath of sources) if (!existsSync(sourcePath)) issues.push({
|
|
245
|
+
field: `assets["${outputPath}"]`,
|
|
246
|
+
message: `Asset source does not exist: ${sourcePath}`,
|
|
247
|
+
severity: "error"
|
|
248
|
+
});
|
|
249
|
+
if (typeof config.favicon === "string" && !existsSync(config.favicon)) issues.push({
|
|
250
|
+
field: "favicon",
|
|
251
|
+
message: `Favicon file does not exist: ${config.favicon}`,
|
|
252
|
+
severity: "warn"
|
|
253
|
+
});
|
|
254
|
+
if (config.theme?.layouts) for (const [layoutName, layoutPath] of Object.entries(config.theme.layouts)) {
|
|
255
|
+
const resolvedLayout = resolve(config.rootDir, layoutPath);
|
|
256
|
+
if (!existsSync(resolvedLayout)) issues.push({
|
|
257
|
+
field: `theme.layouts.${layoutName}`,
|
|
258
|
+
message: `Layout file does not exist: ${resolvedLayout}`,
|
|
259
|
+
severity: "error"
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
return issues;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Log validation issues to console. Returns true if there are any errors (severity: 'error').
|
|
266
|
+
*/
|
|
267
|
+
function reportConfigIssues(issues) {
|
|
268
|
+
let hasErrors = false;
|
|
269
|
+
for (const issue of issues) if (issue.severity === "error") {
|
|
270
|
+
console.error(`\x1b[31m✗ [${issue.field}]\x1b[0m ${issue.message}`);
|
|
271
|
+
hasErrors = true;
|
|
272
|
+
} else console.warn(`\x1b[33m⚠ [${issue.field}]\x1b[0m ${issue.message}`);
|
|
273
|
+
return hasErrors;
|
|
274
|
+
}
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region src/markdown/plugins/rehype-asset-transform.ts
|
|
277
|
+
/**
|
|
278
|
+
* Rehype plugin: transform relative asset references to /assets/ URLs.
|
|
279
|
+
*
|
|
280
|
+
* Converts references like `./image.png` or `./assets/image.png`
|
|
281
|
+
* into site-relative URLs like `/assets/image.png`.
|
|
282
|
+
*
|
|
283
|
+
* Special handling:
|
|
284
|
+
* - `.inline.svg` files: read from disk and embed as inline SVG (supports currentColor)
|
|
285
|
+
* - `.invert.` files: add `invert-on-dark` class for CSS dark-mode inversion
|
|
286
|
+
*
|
|
287
|
+
* Handles <img src="...">, <source srcset="...">, and <a href="..."> for asset files.
|
|
288
|
+
*/
|
|
289
|
+
const ASSET_EXTS = /\.(svg|png|jpg|jpeg|gif|webp|avif|ico)$/i;
|
|
290
|
+
function rehypeAssetTransform(options = {}) {
|
|
291
|
+
return (tree) => {
|
|
292
|
+
visit(tree, "element", (node, index, parent) => {
|
|
293
|
+
if (node.tagName === "img") {
|
|
294
|
+
const src = node.properties?.src;
|
|
295
|
+
if (typeof src !== "string" || !src.startsWith("./") || !ASSET_EXTS.test(src)) return;
|
|
296
|
+
if (src.endsWith(".inline.svg") && options.contentDir) {
|
|
297
|
+
const filePath = join(options.contentDir, src.replace("./", ""));
|
|
298
|
+
if (existsSync(filePath)) {
|
|
299
|
+
let svgContent = readFileSync(filePath, "utf-8");
|
|
300
|
+
svgContent = svgContent.replace(/<\?xml[^?]*\?>\s*/g, "");
|
|
301
|
+
svgContent = svgContent.replace(/<!DOCTYPE[^>]*>\s*/g, "");
|
|
302
|
+
const alt = node.properties?.alt || "";
|
|
303
|
+
svgContent = svgContent.replace("<svg", `<svg role="img" aria-label="${String(alt).replace(/"/g, """)}" class="inline-svg"`);
|
|
304
|
+
if (parent && index !== void 0) {
|
|
305
|
+
parent.children[index] = {
|
|
306
|
+
type: "raw",
|
|
307
|
+
value: svgContent
|
|
308
|
+
};
|
|
309
|
+
return SKIP;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
node.properties = node.properties || {};
|
|
314
|
+
node.properties.src = `/assets/${basename(src)}`;
|
|
315
|
+
if (basename(src).includes(".invert.")) {
|
|
316
|
+
const existing = node.properties.className;
|
|
317
|
+
node.properties.className = existing ? [...Array.isArray(existing) ? existing : [existing], "invert-on-dark"] : ["invert-on-dark"];
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (node.tagName === "source") {
|
|
321
|
+
const srcset = node.properties?.srcset;
|
|
322
|
+
if (typeof srcset === "string" && srcset.startsWith("./") && ASSET_EXTS.test(srcset)) {
|
|
323
|
+
node.properties = node.properties || {};
|
|
324
|
+
node.properties.srcset = `/assets/${basename(srcset)}`;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (node.tagName === "a") {
|
|
328
|
+
const href = node.properties?.href;
|
|
329
|
+
if (typeof href === "string" && href.startsWith("./") && ASSET_EXTS.test(href)) {
|
|
330
|
+
node.properties = node.properties || {};
|
|
331
|
+
node.properties.href = `/assets/${basename(href)}`;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region src/content.ts
|
|
339
|
+
const DocsFrontmatterSchema = z.object({
|
|
340
|
+
title: z.string().optional(),
|
|
341
|
+
description: z.string().optional(),
|
|
342
|
+
navLabel: z.string().optional(),
|
|
343
|
+
sidebarLabel: z.string().optional(),
|
|
344
|
+
order: z.number().optional(),
|
|
345
|
+
draft: z.boolean().optional(),
|
|
346
|
+
socialImage: z.string().optional(),
|
|
347
|
+
hero: z.record(z.string(), z.any()).optional(),
|
|
348
|
+
features: z.array(z.record(z.string(), z.any())).optional()
|
|
349
|
+
}).passthrough();
|
|
350
|
+
const CONTENT_ASSET_EXTS = new Set([
|
|
351
|
+
".svg",
|
|
352
|
+
".png",
|
|
353
|
+
".jpg",
|
|
354
|
+
".jpeg",
|
|
355
|
+
".gif",
|
|
356
|
+
".webp",
|
|
357
|
+
".avif",
|
|
358
|
+
".ico"
|
|
359
|
+
]);
|
|
360
|
+
function toContentSlug(filePath, contentDir) {
|
|
361
|
+
const ext = extname(filePath);
|
|
362
|
+
let slug = relative(contentDir, filePath).replace(/\\/g, "/");
|
|
363
|
+
if (ext) slug = slug.slice(0, -ext.length);
|
|
364
|
+
if (slug === "README" || slug === "index") return "/";
|
|
365
|
+
if (slug.endsWith("/README")) slug = slug.slice(0, -7);
|
|
366
|
+
if (slug.endsWith("/index")) slug = slug.slice(0, -6);
|
|
367
|
+
return slug;
|
|
368
|
+
}
|
|
369
|
+
function loadRootMeta(contentDir) {
|
|
370
|
+
return readJson5File(join(contentDir, "meta.json5"));
|
|
371
|
+
}
|
|
372
|
+
function loadSectionMetas(contentDir) {
|
|
373
|
+
const metas = /* @__PURE__ */ new Map();
|
|
374
|
+
if (!existsSync(contentDir)) return metas;
|
|
375
|
+
for (const entry of readdirSync(contentDir, { withFileTypes: true })) {
|
|
376
|
+
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
377
|
+
const meta = readJson5File(join(contentDir, entry.name, "meta.json5"));
|
|
378
|
+
if (meta) metas.set(entry.name, meta);
|
|
379
|
+
}
|
|
380
|
+
return metas;
|
|
381
|
+
}
|
|
382
|
+
function collectMarkdownFiles(contentDir) {
|
|
383
|
+
const files = [];
|
|
384
|
+
function walk(currentDir) {
|
|
385
|
+
for (const entry of readdirSync(currentDir, { withFileTypes: true })) {
|
|
386
|
+
if (entry.name.startsWith(".")) continue;
|
|
387
|
+
const fullPath = join(currentDir, entry.name);
|
|
388
|
+
if (entry.isDirectory()) {
|
|
389
|
+
walk(fullPath);
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
if (entry.name.endsWith(".md")) files.push(fullPath);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (existsSync(contentDir)) walk(contentDir);
|
|
396
|
+
return files.sort();
|
|
397
|
+
}
|
|
398
|
+
function createRelativeLinkTransform(filePath, contentDir, basePath) {
|
|
399
|
+
return () => (tree) => {
|
|
400
|
+
const visit = (node) => {
|
|
401
|
+
if (node?.type === "element" && node.tagName === "a") {
|
|
402
|
+
const href = node.properties?.href;
|
|
403
|
+
if (typeof href === "string" && href.includes(".md") && !href.startsWith("http")) {
|
|
404
|
+
const [rawPath, hash = ""] = href.split("#");
|
|
405
|
+
const slug = toContentSlug(join(dirname(filePath), rawPath), contentDir);
|
|
406
|
+
const fullPath = `${basePath}${slug === "/" ? "/" : `/${slug}/`}`;
|
|
407
|
+
node.properties = node.properties || {};
|
|
408
|
+
node.properties.href = hash ? `${fullPath}#${hash}` : fullPath;
|
|
409
|
+
} else if (basePath && typeof href === "string" && href.startsWith("/") && !href.startsWith("//") && !href.startsWith(basePath)) {
|
|
410
|
+
node.properties = node.properties || {};
|
|
411
|
+
node.properties.href = `${basePath}${href}`;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (Array.isArray(node?.children)) for (const child of node.children) visit(child);
|
|
415
|
+
};
|
|
416
|
+
visit(tree);
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Run async tasks with bounded concurrency.
|
|
421
|
+
* Prevents memory blowup when processing thousands of pages.
|
|
422
|
+
*/
|
|
423
|
+
async function mapWithConcurrency(items, concurrency, fn) {
|
|
424
|
+
const results = Array.from({ length: items.length });
|
|
425
|
+
let index = 0;
|
|
426
|
+
async function worker() {
|
|
427
|
+
while (index < items.length) {
|
|
428
|
+
const i = index++;
|
|
429
|
+
results[i] = await fn(items[i]);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
|
|
433
|
+
await Promise.all(workers);
|
|
434
|
+
return results;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Get the git last-modified date for a file.
|
|
438
|
+
* Returns ISO date string or undefined if git is unavailable or the file isn't tracked.
|
|
439
|
+
*/
|
|
440
|
+
function getGitLastUpdated(filePath) {
|
|
441
|
+
try {
|
|
442
|
+
return execFileSync("git", [
|
|
443
|
+
"log",
|
|
444
|
+
"-1",
|
|
445
|
+
"--format=%cI",
|
|
446
|
+
"--",
|
|
447
|
+
filePath
|
|
448
|
+
], {
|
|
449
|
+
encoding: "utf-8",
|
|
450
|
+
stdio: [
|
|
451
|
+
"pipe",
|
|
452
|
+
"pipe",
|
|
453
|
+
"pipe"
|
|
454
|
+
]
|
|
455
|
+
}).trim() || void 0;
|
|
456
|
+
} catch {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Generate breadcrumbs from a content slug.
|
|
462
|
+
* Returns array of { label, path } from root to current page.
|
|
463
|
+
*/
|
|
464
|
+
function buildBreadcrumbs(contentSlug, title, basePath) {
|
|
465
|
+
if (contentSlug === "/") return [];
|
|
466
|
+
const segments = contentSlug.split("/");
|
|
467
|
+
const crumbs = [];
|
|
468
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
469
|
+
const slug = segments.slice(0, i + 1).join("/");
|
|
470
|
+
crumbs.push({
|
|
471
|
+
label: toTitleCase(segments[i]),
|
|
472
|
+
path: `${basePath}/${slug}`
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
crumbs.push({
|
|
476
|
+
label: title,
|
|
477
|
+
path: ""
|
|
478
|
+
});
|
|
479
|
+
return crumbs;
|
|
480
|
+
}
|
|
481
|
+
async function loadDocsPages(config, sectionMetas) {
|
|
482
|
+
const homeConfig = config.homeConfigFile ? readJson5File(config.homeConfigFile) : void 0;
|
|
483
|
+
const results = await mapWithConcurrency(collectMarkdownFiles(config.contentDir), Math.max(1, availableParallelism() * 2), async (filePath) => {
|
|
484
|
+
const result = await processMarkdown(readFileSync(filePath, "utf-8"), {
|
|
485
|
+
...config.markdown ?? {},
|
|
486
|
+
shiki: {
|
|
487
|
+
themes: config.markdown?.shiki?.themes ?? {
|
|
488
|
+
light: "github-light",
|
|
489
|
+
dark: "github-dark"
|
|
490
|
+
},
|
|
491
|
+
defaultShowLineNumbers: config.markdown?.shiki?.defaultShowLineNumbers,
|
|
492
|
+
langAlias: config.markdown?.shiki?.langAlias
|
|
493
|
+
},
|
|
494
|
+
rehypePlugins: [
|
|
495
|
+
...config.markdown?.rehypePlugins ?? [],
|
|
496
|
+
[rehypeAssetTransform, { contentDir: dirname(filePath) }],
|
|
497
|
+
createRelativeLinkTransform(filePath, config.contentDir, config.basePath)
|
|
498
|
+
]
|
|
499
|
+
});
|
|
500
|
+
const parsedFrontmatter = DocsFrontmatterSchema.parse(result.frontmatter ?? {});
|
|
501
|
+
const contentSlug = toContentSlug(filePath, config.contentDir);
|
|
502
|
+
const isHome = contentSlug === "/";
|
|
503
|
+
const frontmatter = isHome && homeConfig ? {
|
|
504
|
+
...homeConfig,
|
|
505
|
+
...parsedFrontmatter
|
|
506
|
+
} : parsedFrontmatter;
|
|
507
|
+
if (frontmatter.draft) return null;
|
|
508
|
+
const routePath = isHome ? "/" : `/${contentSlug}`;
|
|
509
|
+
const section = isHome ? void 0 : contentSlug.split("/")[0];
|
|
510
|
+
const title = frontmatter.title ?? (isHome ? config.title : toTitleCase(contentSlug.split("/").at(-1) ?? section ?? "Home"));
|
|
511
|
+
const sectionMeta = section ? sectionMetas?.get(section) : void 0;
|
|
512
|
+
const isLanding = section != null && contentSlug === section;
|
|
513
|
+
let layoutName;
|
|
514
|
+
if (isHome) layoutName = "home";
|
|
515
|
+
else if (isLanding && sectionMeta?.layout) layoutName = sectionMeta.layout;
|
|
516
|
+
else if (!isLanding && sectionMeta?.itemLayout) layoutName = sectionMeta.itemLayout;
|
|
517
|
+
else layoutName = "page";
|
|
518
|
+
const lastUpdated = config.lastUpdated ? getGitLastUpdated(filePath) : void 0;
|
|
519
|
+
return {
|
|
520
|
+
title,
|
|
521
|
+
routePath,
|
|
522
|
+
contentSlug,
|
|
523
|
+
section,
|
|
524
|
+
frontmatter,
|
|
525
|
+
html: result.html,
|
|
526
|
+
headings: result.headings,
|
|
527
|
+
sourcePath: filePath,
|
|
528
|
+
isHome,
|
|
529
|
+
layoutName,
|
|
530
|
+
lastUpdated
|
|
531
|
+
};
|
|
532
|
+
});
|
|
533
|
+
const pages = [];
|
|
534
|
+
for (const result of results) if (result != null) pages.push(result);
|
|
535
|
+
return pages.sort((left, right) => left.routePath.localeCompare(right.routePath));
|
|
536
|
+
}
|
|
537
|
+
function collectContentAssets(contentDir) {
|
|
538
|
+
const assets = /* @__PURE__ */ new Map();
|
|
539
|
+
function walk(currentDir) {
|
|
540
|
+
if (!existsSync(currentDir)) return;
|
|
541
|
+
for (const entry of readdirSync(currentDir, { withFileTypes: true })) {
|
|
542
|
+
if (entry.name.startsWith(".")) continue;
|
|
543
|
+
const fullPath = join(currentDir, entry.name);
|
|
544
|
+
if (entry.isDirectory()) {
|
|
545
|
+
walk(fullPath);
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
if (!CONTENT_ASSET_EXTS.has(extname(entry.name).toLowerCase())) continue;
|
|
549
|
+
if (assets.has(entry.name) && assets.get(entry.name) !== fullPath) console.warn(`pagesmith:docs duplicate companion asset basename "${entry.name}" detected; using ${fullPath}`);
|
|
550
|
+
assets.set(entry.name, fullPath);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
walk(contentDir);
|
|
554
|
+
return assets;
|
|
555
|
+
}
|
|
556
|
+
//#endregion
|
|
557
|
+
//#region src/navigation.ts
|
|
558
|
+
function getOrder(page) {
|
|
559
|
+
return typeof page.frontmatter.order === "number" ? page.frontmatter.order : Number.MAX_SAFE_INTEGER;
|
|
560
|
+
}
|
|
561
|
+
function sortPages(pages) {
|
|
562
|
+
return [...pages].sort((left, right) => {
|
|
563
|
+
const orderDelta = getOrder(left) - getOrder(right);
|
|
564
|
+
if (orderDelta !== 0) return orderDelta;
|
|
565
|
+
return left.routePath.localeCompare(right.routePath);
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
function sortSectionPages(pages, meta) {
|
|
569
|
+
if (!meta?.orderBy) return sortPages(pages);
|
|
570
|
+
if (meta.orderBy === "publishedDate") {
|
|
571
|
+
const getPublishedTime = (value) => {
|
|
572
|
+
if (!value) return 0;
|
|
573
|
+
if (value instanceof Date) return value.getTime();
|
|
574
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value).getTime();
|
|
575
|
+
return 0;
|
|
576
|
+
};
|
|
577
|
+
return [...pages].sort((a, b) => {
|
|
578
|
+
const dateA = getPublishedTime(a.frontmatter.publishedDate);
|
|
579
|
+
return getPublishedTime(b.frontmatter.publishedDate) - dateA;
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
if (meta.orderBy === "manual" && meta.items) {
|
|
583
|
+
const order = new Map(meta.items.map((slug, i) => [slug, i]));
|
|
584
|
+
return [...pages].sort((a, b) => {
|
|
585
|
+
const slugA = a.contentSlug.split("/").pop() ?? "";
|
|
586
|
+
const slugB = b.contentSlug.split("/").pop() ?? "";
|
|
587
|
+
return (order.get(slugA) ?? Number.MAX_SAFE_INTEGER) - (order.get(slugB) ?? Number.MAX_SAFE_INTEGER);
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
return sortPages(pages);
|
|
591
|
+
}
|
|
592
|
+
function buildSidebarWithSeries(sectionSlug, sectionPages, meta, basePath) {
|
|
593
|
+
const sections = [];
|
|
594
|
+
const pageBySlug = new Map(sectionPages.map((p) => [p.contentSlug.split("/").pop(), p]));
|
|
595
|
+
const landing = sectionPages.find((p) => p.contentSlug === sectionSlug);
|
|
596
|
+
for (const series of meta.series) {
|
|
597
|
+
for (const slug of series.articles) if (!pageBySlug.has(slug)) console.warn(`\x1b[33m⚠ [${sectionSlug}]\x1b[0m Series "${series.displayName}" references article slug "${slug}" which does not match any loaded page.`);
|
|
598
|
+
const items = series.articles.map((slug) => pageBySlug.get(slug)).filter((p) => p != null).map((page) => ({
|
|
599
|
+
title: page.frontmatter.sidebarLabel ?? page.title,
|
|
600
|
+
path: `${basePath}${page.routePath}`
|
|
601
|
+
}));
|
|
602
|
+
if (items.length > 0) sections.push({
|
|
603
|
+
title: series.displayName,
|
|
604
|
+
slug: series.slug,
|
|
605
|
+
items
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
if (landing && sections.length > 0) sections[0].items.unshift({
|
|
609
|
+
title: landing.frontmatter.sidebarLabel ?? landing.title,
|
|
610
|
+
path: `${basePath}${landing.routePath}`
|
|
611
|
+
});
|
|
612
|
+
return sections;
|
|
613
|
+
}
|
|
614
|
+
function buildSidebarItems(sectionSlug, sectionPages, basePath, sectionMeta) {
|
|
615
|
+
const roots = /* @__PURE__ */ new Map();
|
|
616
|
+
const landingPage = sectionPages.find((page) => page.contentSlug === sectionSlug);
|
|
617
|
+
for (const page of sortSectionPages(sectionPages.filter((entry) => entry.contentSlug !== sectionSlug), sectionMeta)) {
|
|
618
|
+
const remainder = page.contentSlug.slice(sectionSlug.length + 1);
|
|
619
|
+
if (!remainder) continue;
|
|
620
|
+
const segments = remainder.split("/");
|
|
621
|
+
let level = roots;
|
|
622
|
+
let accumulated = sectionSlug;
|
|
623
|
+
for (const [index, segment] of segments.entries()) {
|
|
624
|
+
accumulated = `${accumulated}/${segment}`;
|
|
625
|
+
let node = level.get(segment);
|
|
626
|
+
if (!node) {
|
|
627
|
+
node = {
|
|
628
|
+
key: accumulated,
|
|
629
|
+
title: toTitleCase(segment),
|
|
630
|
+
path: `${basePath}${page.routePath}`,
|
|
631
|
+
order: getOrder(page),
|
|
632
|
+
children: /* @__PURE__ */ new Map()
|
|
633
|
+
};
|
|
634
|
+
level.set(segment, node);
|
|
635
|
+
}
|
|
636
|
+
if (index === segments.length - 1) {
|
|
637
|
+
node.title = page.frontmatter.sidebarLabel ?? page.title;
|
|
638
|
+
node.path = `${basePath}${page.routePath}`;
|
|
639
|
+
node.order = getOrder(page);
|
|
640
|
+
}
|
|
641
|
+
level = node.children;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
const toItems = (nodes) => Array.from(nodes.values()).sort((left, right) => {
|
|
645
|
+
const orderDelta = left.order - right.order;
|
|
646
|
+
if (orderDelta !== 0) return orderDelta;
|
|
647
|
+
return left.title.localeCompare(right.title);
|
|
648
|
+
}).map((node) => ({
|
|
649
|
+
title: node.title,
|
|
650
|
+
path: node.path,
|
|
651
|
+
...node.children.size > 0 ? { children: toItems(node.children) } : {}
|
|
652
|
+
}));
|
|
653
|
+
const items = toItems(roots);
|
|
654
|
+
if (!landingPage) return items;
|
|
655
|
+
return [{
|
|
656
|
+
title: landingPage.frontmatter.sidebarLabel ?? landingPage.title,
|
|
657
|
+
path: `${basePath}${landingPage.routePath}`
|
|
658
|
+
}, ...items];
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Find the first content page in a section, respecting meta ordering.
|
|
662
|
+
* Excludes the landing page (README.md) itself — returns the first "child" page.
|
|
663
|
+
*/
|
|
664
|
+
function findFirstSectionPage(sectionSlug, sectionPages, meta) {
|
|
665
|
+
const nonLanding = sectionPages.filter((p) => p.contentSlug !== sectionSlug);
|
|
666
|
+
if (nonLanding.length === 0) return void 0;
|
|
667
|
+
if (meta?.orderBy === "manual" && meta.series && meta.series.length > 0) {
|
|
668
|
+
const pageBySlug = new Map(nonLanding.map((p) => [p.contentSlug.split("/").pop(), p]));
|
|
669
|
+
for (const series of meta.series) for (const slug of series.articles) {
|
|
670
|
+
const page = pageBySlug.get(slug);
|
|
671
|
+
if (page) return page;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
if (meta?.orderBy === "manual" && meta.items && meta.items.length > 0) {
|
|
675
|
+
const pageBySlug = new Map(nonLanding.map((p) => [p.contentSlug.split("/").pop(), p]));
|
|
676
|
+
for (const slug of meta.items) {
|
|
677
|
+
const page = pageBySlug.get(slug);
|
|
678
|
+
if (page) return page;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return sortSectionPages(nonLanding, meta)[0];
|
|
682
|
+
}
|
|
683
|
+
function buildSiteModel(config, pages, rootMeta, sectionMetas) {
|
|
684
|
+
const pageByPath = new Map(pages.map((page) => [page.routePath, page]));
|
|
685
|
+
const sidebarBySection = /* @__PURE__ */ new Map();
|
|
686
|
+
const navItems = [];
|
|
687
|
+
const pagesBySection = /* @__PURE__ */ new Map();
|
|
688
|
+
for (const page of pages) {
|
|
689
|
+
if (!page.section) continue;
|
|
690
|
+
if (page.frontmatter.draft) continue;
|
|
691
|
+
if (!pagesBySection.has(page.section)) pagesBySection.set(page.section, []);
|
|
692
|
+
pagesBySection.get(page.section).push(page);
|
|
693
|
+
}
|
|
694
|
+
for (const [sectionSlug, sectionPages] of Array.from(pagesBySection.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
695
|
+
const sectionMeta = sectionMetas?.get(sectionSlug);
|
|
696
|
+
const landingPage = sectionPages.find((page) => page.contentSlug === sectionSlug);
|
|
697
|
+
const firstPage = findFirstSectionPage(sectionSlug, sectionPages, sectionMeta);
|
|
698
|
+
const label = sectionMeta?.displayName ?? config.packages?.[sectionSlug]?.label ?? landingPage?.frontmatter.navLabel ?? landingPage?.title ?? firstPage?.frontmatter.navLabel ?? toTitleCase(sectionSlug);
|
|
699
|
+
const sectionPath = landingPage?.routePath ?? firstPage?.routePath ?? `/${sectionSlug}`;
|
|
700
|
+
if (!rootMeta?.headerLinks || rootMeta.headerLinks.length === 0) navItems.push({
|
|
701
|
+
label,
|
|
702
|
+
path: `${config.basePath}${sectionPath}`
|
|
703
|
+
});
|
|
704
|
+
if (sectionMeta?.series && sectionMeta.series.length > 0) sidebarBySection.set(sectionSlug, buildSidebarWithSeries(sectionSlug, sectionPages, sectionMeta, config.basePath));
|
|
705
|
+
else sidebarBySection.set(sectionSlug, [{
|
|
706
|
+
title: label,
|
|
707
|
+
slug: sectionSlug,
|
|
708
|
+
collapsed: sectionMeta?.collapsed,
|
|
709
|
+
items: buildSidebarItems(sectionSlug, sectionPages, config.basePath, sectionMeta)
|
|
710
|
+
}]);
|
|
711
|
+
}
|
|
712
|
+
if (rootMeta?.headerLinks && rootMeta.headerLinks.length > 0) for (const link of rootMeta.headerLinks) {
|
|
713
|
+
const rawPath = link.path.startsWith("/") ? link.path : `/${link.path}`;
|
|
714
|
+
const sectionSlug = rawPath.replace(/^\//, "").replace(/\/.*$/, "");
|
|
715
|
+
const sectionPages = pagesBySection.get(sectionSlug);
|
|
716
|
+
let resolvedPath = rawPath;
|
|
717
|
+
if (sectionPages) {
|
|
718
|
+
const landing = sectionPages.find((p) => p.contentSlug === sectionSlug);
|
|
719
|
+
if (landing) resolvedPath = landing.routePath;
|
|
720
|
+
else {
|
|
721
|
+
const first = findFirstSectionPage(sectionSlug, sectionPages, sectionMetas?.get(sectionSlug));
|
|
722
|
+
if (first) resolvedPath = first.routePath;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
navItems.push({
|
|
726
|
+
label: link.label,
|
|
727
|
+
path: `${config.basePath}${resolvedPath}`
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
return {
|
|
731
|
+
navItems,
|
|
732
|
+
sidebarBySection,
|
|
733
|
+
pageByPath,
|
|
734
|
+
rootMeta,
|
|
735
|
+
sectionMetas: sectionMetas ?? /* @__PURE__ */ new Map()
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
function flattenSidebarItems(items) {
|
|
739
|
+
const flattened = [];
|
|
740
|
+
for (const item of items) {
|
|
741
|
+
flattened.push(item);
|
|
742
|
+
if (item.children) flattened.push(...flattenSidebarItems(item.children));
|
|
743
|
+
}
|
|
744
|
+
return flattened;
|
|
745
|
+
}
|
|
746
|
+
function getPrevNext(sidebarSections, routePath) {
|
|
747
|
+
if (!sidebarSections?.length) return {};
|
|
748
|
+
const flat = flattenSidebarItems(sidebarSections.flatMap((section) => section.items));
|
|
749
|
+
const index = flat.findIndex((item) => item.path === routePath);
|
|
750
|
+
if (index < 0) return {};
|
|
751
|
+
const prev = index > 0 ? flat[index - 1] : void 0;
|
|
752
|
+
const next = index < flat.length - 1 ? flat[index + 1] : void 0;
|
|
753
|
+
return {
|
|
754
|
+
prev: prev ? {
|
|
755
|
+
title: prev.title,
|
|
756
|
+
path: prev.path
|
|
757
|
+
} : void 0,
|
|
758
|
+
next: next ? {
|
|
759
|
+
title: next.title,
|
|
760
|
+
path: next.path
|
|
761
|
+
} : void 0
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
function getSitePayload(config, model) {
|
|
765
|
+
const base = config.basePath;
|
|
766
|
+
const rawFooterLinks = model.rootMeta?.footerLinks ?? config.footerLinks;
|
|
767
|
+
const footerLinks = base ? rawFooterLinks.map((link) => ({
|
|
768
|
+
...link,
|
|
769
|
+
path: link.path.startsWith("/") && !link.path.startsWith("//") && !link.path.startsWith(base) ? `${base}${link.path}` : link.path
|
|
770
|
+
})) : rawFooterLinks;
|
|
771
|
+
return {
|
|
772
|
+
origin: config.origin,
|
|
773
|
+
basePath: config.basePath,
|
|
774
|
+
homeLink: config.homeLink,
|
|
775
|
+
name: config.name,
|
|
776
|
+
title: config.title,
|
|
777
|
+
description: config.description,
|
|
778
|
+
language: config.language,
|
|
779
|
+
navItems: model.navItems,
|
|
780
|
+
footerLinks,
|
|
781
|
+
search: config.search,
|
|
782
|
+
sidebar: config.sidebar,
|
|
783
|
+
analytics: config.analytics,
|
|
784
|
+
theme: config.theme,
|
|
785
|
+
socialImage: config.socialImage ? config.socialImage.startsWith("http") ? config.socialImage : `${config.basePath}/${config.socialImage.replace(/^\//, "")}` : void 0,
|
|
786
|
+
favicon: config.favicon !== false ? `${config.basePath}/${basename(config.favicon)}` : false,
|
|
787
|
+
faviconFallback: config.faviconFallback ? `${config.basePath}/${basename(config.faviconFallback)}` : false,
|
|
788
|
+
appleTouchIcon: config.appleTouchIcon ? `${config.basePath}/apple-touch-icon.png` : false
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
//#endregion
|
|
792
|
+
//#region theme/components/DocFooter.tsx
|
|
793
|
+
function DocFooter({ prev, next, links, copyright }) {
|
|
794
|
+
const hasPrevNext = prev || next;
|
|
795
|
+
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
796
|
+
return /* @__PURE__ */ h("footer", { class: "doc-footer" }, hasPrevNext ? /* @__PURE__ */ h("nav", {
|
|
797
|
+
class: "doc-footer-nav",
|
|
798
|
+
"aria-label": "Page navigation"
|
|
799
|
+
}, prev ? /* @__PURE__ */ h("a", {
|
|
800
|
+
href: prev.path + "/",
|
|
801
|
+
class: "doc-footer-link doc-footer-prev"
|
|
802
|
+
}, /* @__PURE__ */ h("span", { class: "doc-footer-label" }, "Previous"), /* @__PURE__ */ h("span", { class: "doc-footer-title" }, prev.title)) : /* @__PURE__ */ h("span", null), next ? /* @__PURE__ */ h("a", {
|
|
803
|
+
href: next.path + "/",
|
|
804
|
+
class: "doc-footer-link doc-footer-next"
|
|
805
|
+
}, /* @__PURE__ */ h("span", { class: "doc-footer-label" }, "Next"), /* @__PURE__ */ h("span", { class: "doc-footer-title" }, next.title)) : /* @__PURE__ */ h("span", null)) : null, links && links.length > 0 ? /* @__PURE__ */ h("nav", {
|
|
806
|
+
class: "doc-footer-links",
|
|
807
|
+
"aria-label": "Footer links"
|
|
808
|
+
}, links.map((link) => /* @__PURE__ */ h("a", { href: link.path }, link.label))) : null, copyright ? /* @__PURE__ */ h("p", { class: "doc-footer-copyright" }, "© ", copyright.startYear < year ? `${copyright.startYear}–${year}` : `${year}`, " ", copyright.holder) : null);
|
|
809
|
+
}
|
|
810
|
+
//#endregion
|
|
811
|
+
//#region theme/components/DocHeader.tsx
|
|
812
|
+
const hamburgerIcon = "<svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><path d=\"M3 5h14M3 10h14M3 15h14\"/></svg>";
|
|
813
|
+
const searchIcon = "<svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><circle cx=\"8.5\" cy=\"8.5\" r=\"5.5\"/><path d=\"m13 13 4 4\"/></svg>";
|
|
814
|
+
function DocHeader({ siteName, basePath, homeLink, navItems, slug, searchEnabled }) {
|
|
815
|
+
const homePath = homeLink || (basePath ? `${basePath}/` : "/");
|
|
816
|
+
const hasNav = navItems && navItems.length > 0;
|
|
817
|
+
const base = (basePath || "").replace(/\/+$/, "");
|
|
818
|
+
function isNavActive(itemPath) {
|
|
819
|
+
const section = (itemPath.startsWith(base) ? itemPath.slice(base.length) : itemPath).replace(/^\//, "").split("/")[0];
|
|
820
|
+
return slug.startsWith(`${base}/${section}`);
|
|
821
|
+
}
|
|
822
|
+
return /* @__PURE__ */ h("header", { class: "doc-header" }, /* @__PURE__ */ h("div", { class: "doc-header-inner" }, /* @__PURE__ */ h("div", { class: "doc-header-left" }, hasNav ? /* @__PURE__ */ h("button", {
|
|
823
|
+
type: "button",
|
|
824
|
+
class: "doc-sidebar-toggle",
|
|
825
|
+
"aria-label": "Toggle navigation",
|
|
826
|
+
"data-sidebar-toggle": "",
|
|
827
|
+
innerHTML: hamburgerIcon
|
|
828
|
+
}) : null, /* @__PURE__ */ h("a", {
|
|
829
|
+
href: homePath,
|
|
830
|
+
class: "doc-logo"
|
|
831
|
+
}, siteName)), hasNav ? /* @__PURE__ */ h("nav", { class: "doc-nav" }, navItems.map((item) => /* @__PURE__ */ h("a", {
|
|
832
|
+
href: item.path,
|
|
833
|
+
class: isNavActive(item.path) ? "active" : ""
|
|
834
|
+
}, item.label))) : null, searchEnabled ? /* @__PURE__ */ h("button", {
|
|
835
|
+
type: "button",
|
|
836
|
+
class: "doc-search-trigger",
|
|
837
|
+
"aria-label": "Search",
|
|
838
|
+
"data-search-trigger": ""
|
|
839
|
+
}, /* @__PURE__ */ h("span", {
|
|
840
|
+
class: "doc-search-icon",
|
|
841
|
+
innerHTML: searchIcon
|
|
842
|
+
}), /* @__PURE__ */ h("kbd", { class: "doc-search-shortcut" }, /* @__PURE__ */ h("span", { class: "doc-search-shortcut-key" }, "⌘"), "K")) : null));
|
|
843
|
+
}
|
|
844
|
+
//#endregion
|
|
845
|
+
//#region theme/components/DocSidebar.tsx
|
|
846
|
+
function isSectionActive(items, currentSlug) {
|
|
847
|
+
for (const item of items) {
|
|
848
|
+
if (currentSlug === item.path || currentSlug.startsWith(item.path + "/")) return true;
|
|
849
|
+
if (item.children && isSectionActive(item.children, currentSlug)) return true;
|
|
850
|
+
}
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
853
|
+
function renderItems(items, currentSlug, depth = 0) {
|
|
854
|
+
return /* @__PURE__ */ h("ul", { class: `doc-sidebar-list ${depth > 0 ? "doc-sidebar-nested" : ""}` }, items.map((item) => {
|
|
855
|
+
const isActive = currentSlug === item.path;
|
|
856
|
+
const hasChildren = item.children && item.children.length > 0;
|
|
857
|
+
const isExpanded = hasChildren && item.children.some((child) => currentSlug === child.path || currentSlug.startsWith(child.path + "/"));
|
|
858
|
+
return /* @__PURE__ */ h("li", { class: `doc-sidebar-item ${isActive ? "active" : ""} ${isExpanded ? "expanded" : ""}` }, /* @__PURE__ */ h("a", {
|
|
859
|
+
href: item.path + "/",
|
|
860
|
+
class: "doc-sidebar-link"
|
|
861
|
+
}, item.title), hasChildren ? renderItems(item.children, currentSlug, depth + 1) : null);
|
|
862
|
+
}));
|
|
863
|
+
}
|
|
864
|
+
function DocSidebar({ sections, currentSlug = "/", collapsible = false }) {
|
|
865
|
+
if (!sections || sections.length === 0) return /* @__PURE__ */ h(Fragment, null);
|
|
866
|
+
return /* @__PURE__ */ h("aside", { class: "doc-sidebar" }, /* @__PURE__ */ h("nav", {
|
|
867
|
+
class: "doc-sidebar-nav",
|
|
868
|
+
"aria-label": "Documentation navigation"
|
|
869
|
+
}, sections.map((section) => {
|
|
870
|
+
const sectionActive = isSectionActive(section.items, currentSlug);
|
|
871
|
+
const isOpen = !section.collapsed || sectionActive;
|
|
872
|
+
if (collapsible) return /* @__PURE__ */ h("details", {
|
|
873
|
+
class: "doc-sidebar-section doc-sidebar-collapsible",
|
|
874
|
+
open: isOpen || void 0
|
|
875
|
+
}, /* @__PURE__ */ h("summary", { class: "doc-sidebar-heading" }, section.title), renderItems(section.items, currentSlug));
|
|
876
|
+
return /* @__PURE__ */ h("div", { class: "doc-sidebar-section" }, /* @__PURE__ */ h("p", { class: "doc-sidebar-heading" }, section.title), renderItems(section.items, currentSlug));
|
|
877
|
+
})));
|
|
878
|
+
}
|
|
879
|
+
//#endregion
|
|
880
|
+
//#region theme/components/Html.tsx
|
|
881
|
+
function buildCsp(gaId) {
|
|
882
|
+
const scriptSrc = ["'self'", "'unsafe-inline'"];
|
|
883
|
+
const connectSrc = ["'self'"];
|
|
884
|
+
if (gaId) {
|
|
885
|
+
scriptSrc.push("https://www.googletagmanager.com");
|
|
886
|
+
connectSrc.push("https://www.google-analytics.com", "https://analytics.google.com");
|
|
887
|
+
}
|
|
888
|
+
return [
|
|
889
|
+
"default-src 'self'",
|
|
890
|
+
`script-src ${scriptSrc.join(" ")}`,
|
|
891
|
+
"style-src 'self' 'unsafe-inline'",
|
|
892
|
+
"img-src 'self' data:",
|
|
893
|
+
"font-src 'self'",
|
|
894
|
+
`connect-src ${connectSrc.join(" ")}`,
|
|
895
|
+
"object-src 'none'",
|
|
896
|
+
"base-uri 'self'",
|
|
897
|
+
"form-action 'self'"
|
|
898
|
+
].join("; ");
|
|
899
|
+
}
|
|
900
|
+
function Html({ title, description, url, socialImage, site, children }) {
|
|
901
|
+
const origin = site.origin.replace(/\/$/, "");
|
|
902
|
+
const base = site.basePath || "";
|
|
903
|
+
const canonicalUrl = url ? `${origin}${url}` : void 0;
|
|
904
|
+
const locale = site.seo?.locale || "en_US";
|
|
905
|
+
const lightColor = site.theme?.lightColor || "#f8fafc";
|
|
906
|
+
const darkColor = site.theme?.darkColor || "#020617";
|
|
907
|
+
const gaId = site.analytics?.googleAnalytics;
|
|
908
|
+
const ogImage = socialImage ?? site.socialImage;
|
|
909
|
+
const searchEnabled = site.search?.enabled !== false;
|
|
910
|
+
const favicon = site.favicon;
|
|
911
|
+
const faviconFallback = site.faviconFallback;
|
|
912
|
+
const appleTouchIcon = site.appleTouchIcon;
|
|
913
|
+
return /* @__PURE__ */ h("html", {
|
|
914
|
+
lang: site.language || "en",
|
|
915
|
+
class: "no-js"
|
|
916
|
+
}, /* @__PURE__ */ h("head", null, /* @__PURE__ */ h("meta", { charset: "utf-8" }), /* @__PURE__ */ h("meta", {
|
|
917
|
+
name: "viewport",
|
|
918
|
+
content: "width=device-width, initial-scale=1"
|
|
919
|
+
}), /* @__PURE__ */ h("meta", {
|
|
920
|
+
name: "color-scheme",
|
|
921
|
+
content: "light dark"
|
|
922
|
+
}), /* @__PURE__ */ h("meta", {
|
|
923
|
+
"http-equiv": "Content-Security-Policy",
|
|
924
|
+
content: buildCsp(gaId)
|
|
925
|
+
}), /* @__PURE__ */ h("meta", {
|
|
926
|
+
name: "referrer",
|
|
927
|
+
content: "strict-origin-when-cross-origin"
|
|
928
|
+
}), /* @__PURE__ */ h("title", null, title), favicon !== false && favicon ? /* @__PURE__ */ h("link", {
|
|
929
|
+
rel: "icon",
|
|
930
|
+
href: favicon,
|
|
931
|
+
type: favicon.endsWith(".svg") ? "image/svg+xml" : "image/x-icon"
|
|
932
|
+
}) : null, faviconFallback ? /* @__PURE__ */ h("link", {
|
|
933
|
+
rel: "icon",
|
|
934
|
+
href: faviconFallback,
|
|
935
|
+
sizes: "32x32"
|
|
936
|
+
}) : null, appleTouchIcon ? /* @__PURE__ */ h("link", {
|
|
937
|
+
rel: "apple-touch-icon",
|
|
938
|
+
href: appleTouchIcon
|
|
939
|
+
}) : null, description ? /* @__PURE__ */ h("meta", {
|
|
940
|
+
name: "description",
|
|
941
|
+
content: description
|
|
942
|
+
}) : null, canonicalUrl ? /* @__PURE__ */ h("link", {
|
|
943
|
+
rel: "canonical",
|
|
944
|
+
href: canonicalUrl
|
|
945
|
+
}) : null, /* @__PURE__ */ h("meta", {
|
|
946
|
+
property: "og:type",
|
|
947
|
+
content: "website"
|
|
948
|
+
}), canonicalUrl ? /* @__PURE__ */ h("meta", {
|
|
949
|
+
property: "og:url",
|
|
950
|
+
content: canonicalUrl
|
|
951
|
+
}) : null, /* @__PURE__ */ h("meta", {
|
|
952
|
+
property: "og:title",
|
|
953
|
+
content: title
|
|
954
|
+
}), description ? /* @__PURE__ */ h("meta", {
|
|
955
|
+
property: "og:description",
|
|
956
|
+
content: description
|
|
957
|
+
}) : null, ogImage ? /* @__PURE__ */ h("meta", {
|
|
958
|
+
property: "og:image",
|
|
959
|
+
content: ogImage.startsWith("http") ? ogImage : `${origin}${ogImage}`
|
|
960
|
+
}) : null, /* @__PURE__ */ h("meta", {
|
|
961
|
+
property: "og:locale",
|
|
962
|
+
content: locale
|
|
963
|
+
}), /* @__PURE__ */ h("meta", {
|
|
964
|
+
property: "og:site_name",
|
|
965
|
+
content: site.name
|
|
966
|
+
}), /* @__PURE__ */ h("meta", {
|
|
967
|
+
name: "theme-color",
|
|
968
|
+
content: lightColor,
|
|
969
|
+
media: "(prefers-color-scheme: light)"
|
|
970
|
+
}), /* @__PURE__ */ h("meta", {
|
|
971
|
+
name: "theme-color",
|
|
972
|
+
content: darkColor,
|
|
973
|
+
media: "(prefers-color-scheme: dark)"
|
|
974
|
+
}), /* @__PURE__ */ h("link", {
|
|
975
|
+
rel: "preload",
|
|
976
|
+
href: `${base}/assets/fonts/open-sans-variable.woff2`,
|
|
977
|
+
as: "font",
|
|
978
|
+
type: "font/woff2",
|
|
979
|
+
crossorigin: ""
|
|
980
|
+
}), gaId ? /* @__PURE__ */ h("link", {
|
|
981
|
+
rel: "preconnect",
|
|
982
|
+
href: "https://www.googletagmanager.com",
|
|
983
|
+
crossorigin: ""
|
|
984
|
+
}) : null, /* @__PURE__ */ h("link", {
|
|
985
|
+
rel: "stylesheet",
|
|
986
|
+
href: `${base}/assets/style.css`
|
|
987
|
+
}), searchEnabled ? /* @__PURE__ */ h("link", {
|
|
988
|
+
rel: "stylesheet",
|
|
989
|
+
href: `${base}/pagefind/pagefind-ui.css`
|
|
990
|
+
}) : null, /* @__PURE__ */ h("script", { innerHTML: "document.documentElement.classList.remove('no-js')" }), searchEnabled ? /* @__PURE__ */ h("script", {
|
|
991
|
+
src: `${base}/pagefind/pagefind-ui.js`,
|
|
992
|
+
defer: true
|
|
993
|
+
}) : null, searchEnabled ? /* @__PURE__ */ h("noscript", null, /* @__PURE__ */ h("style", { innerHTML: ".doc-search-trigger{display:none!important}" })) : null, gaId ? /* @__PURE__ */ h(Fragment, null, /* @__PURE__ */ h("script", {
|
|
994
|
+
async: true,
|
|
995
|
+
src: `https://www.googletagmanager.com/gtag/js?id=${gaId}`
|
|
996
|
+
}), /* @__PURE__ */ h("script", { innerHTML: `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','${gaId}');` })) : null), /* @__PURE__ */ h("body", null, children, searchEnabled ? /* @__PURE__ */ h("dialog", {
|
|
997
|
+
class: "doc-search-modal",
|
|
998
|
+
id: "search-modal",
|
|
999
|
+
"aria-label": "Search documentation",
|
|
1000
|
+
"data-search-show-images": site.search?.showImages ? "true" : "false",
|
|
1001
|
+
"data-search-show-sub-results": site.search?.showSubResults !== false ? "true" : "false"
|
|
1002
|
+
}, /* @__PURE__ */ h("div", { class: "doc-search-modal-inner" }, /* @__PURE__ */ h("div", { class: "doc-search-modal-header" }, /* @__PURE__ */ h("span", { class: "doc-search-modal-title" }, "Search"), /* @__PURE__ */ h("button", {
|
|
1003
|
+
type: "button",
|
|
1004
|
+
class: "doc-search-modal-close",
|
|
1005
|
+
"aria-label": "Close search",
|
|
1006
|
+
"data-search-close": "",
|
|
1007
|
+
innerHTML: "<svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><path d=\"m5 5 10 10M15 5 5 15\"/></svg>"
|
|
1008
|
+
})), /* @__PURE__ */ h("div", {
|
|
1009
|
+
class: "doc-search-modal-body",
|
|
1010
|
+
"data-pagefind-search": ""
|
|
1011
|
+
}))) : null, /* @__PURE__ */ h("script", {
|
|
1012
|
+
src: `${base}/assets/main.js`,
|
|
1013
|
+
defer: true
|
|
1014
|
+
})));
|
|
1015
|
+
}
|
|
1016
|
+
//#endregion
|
|
1017
|
+
//#region theme/layouts/DocHome.tsx
|
|
1018
|
+
/**
|
|
1019
|
+
* DocHome layout.
|
|
1020
|
+
*
|
|
1021
|
+
* Documentation landing page with hero, install snippet, features grid,
|
|
1022
|
+
* packages grid, code example, and optional markdown content.
|
|
1023
|
+
*
|
|
1024
|
+
* All sections are optional — omit the frontmatter key and the section
|
|
1025
|
+
* is not rendered. Supports both single-package and monorepo projects.
|
|
1026
|
+
*/
|
|
1027
|
+
function DocHome(props) {
|
|
1028
|
+
const { content, frontmatter, slug, site } = props;
|
|
1029
|
+
const hero = frontmatter.hero ?? (frontmatter.title || frontmatter.tagline || frontmatter.actions ? {
|
|
1030
|
+
name: frontmatter.title || site.name,
|
|
1031
|
+
text: frontmatter.tagline || frontmatter.title,
|
|
1032
|
+
tagline: frontmatter.description,
|
|
1033
|
+
badge: frontmatter.badge,
|
|
1034
|
+
actions: frontmatter.actions
|
|
1035
|
+
} : void 0);
|
|
1036
|
+
const features = frontmatter.features;
|
|
1037
|
+
const install = frontmatter.install;
|
|
1038
|
+
const packages = frontmatter.packages;
|
|
1039
|
+
const codeExample = frontmatter.codeExample;
|
|
1040
|
+
const navItems = site.navItems;
|
|
1041
|
+
const sidebarSections = navItems && navItems.length > 0 ? [{
|
|
1042
|
+
title: "Navigation",
|
|
1043
|
+
items: navItems.map((item) => ({
|
|
1044
|
+
title: item.label,
|
|
1045
|
+
slug: item.path,
|
|
1046
|
+
path: item.path
|
|
1047
|
+
}))
|
|
1048
|
+
}] : void 0;
|
|
1049
|
+
return /* @__PURE__ */ h(Html, {
|
|
1050
|
+
title: hero?.name || frontmatter.title || site.title,
|
|
1051
|
+
description: hero?.tagline || frontmatter.description || site.description,
|
|
1052
|
+
url: slug,
|
|
1053
|
+
socialImage: frontmatter.socialImage ? frontmatter.socialImage.startsWith("http") ? frontmatter.socialImage : `${site.basePath || ""}/${frontmatter.socialImage.replace(/^\//, "")}` : void 0,
|
|
1054
|
+
site
|
|
1055
|
+
}, /* @__PURE__ */ h(DocHeader, {
|
|
1056
|
+
siteName: site.name,
|
|
1057
|
+
basePath: site.basePath,
|
|
1058
|
+
homeLink: site.homeLink,
|
|
1059
|
+
navItems: site.navItems,
|
|
1060
|
+
slug,
|
|
1061
|
+
searchEnabled: site.search?.enabled
|
|
1062
|
+
}), /* @__PURE__ */ h("main", {
|
|
1063
|
+
class: "doc-home",
|
|
1064
|
+
"data-pagefind-body": ""
|
|
1065
|
+
}, /* @__PURE__ */ h(DocSidebar, {
|
|
1066
|
+
sections: sidebarSections,
|
|
1067
|
+
currentSlug: slug
|
|
1068
|
+
}), hero ? /* @__PURE__ */ h("section", { class: "doc-home-section doc-hero" }, hero.badge ? /* @__PURE__ */ h("div", { class: "doc-hero-badge" }, /* @__PURE__ */ h("span", { class: "doc-hero-badge-dot" }), hero.badge) : null, hero.name ? /* @__PURE__ */ h("p", { class: "doc-hero-name" }, hero.name) : null, hero.text ? /* @__PURE__ */ h("h1", { class: "doc-hero-text" }, hero.text) : null, hero.tagline ? /* @__PURE__ */ h("p", { class: "doc-hero-tagline" }, hero.tagline) : null, hero.actions && hero.actions.length > 0 ? /* @__PURE__ */ h("div", { class: "doc-hero-actions" }, hero.actions.map((action) => /* @__PURE__ */ h("a", {
|
|
1069
|
+
href: action.link,
|
|
1070
|
+
class: `doc-hero-action doc-hero-action-${action.theme || "brand"}`
|
|
1071
|
+
}, action.icon ? /* @__PURE__ */ h("span", {
|
|
1072
|
+
class: "doc-hero-action-icon",
|
|
1073
|
+
innerHTML: action.icon
|
|
1074
|
+
}) : null, action.text))) : null) : null, install ? /* @__PURE__ */ h("div", { class: "doc-home-section doc-home-install" }, /* @__PURE__ */ h("div", { class: "doc-install-bar" }, /* @__PURE__ */ h("div", { class: "doc-install-header" }, /* @__PURE__ */ h("span", { class: "doc-install-dot doc-install-dot-r" }), /* @__PURE__ */ h("span", { class: "doc-install-dot doc-install-dot-y" }), /* @__PURE__ */ h("span", { class: "doc-install-dot doc-install-dot-g" }), /* @__PURE__ */ h("span", { class: "doc-install-title" }, "Terminal"), /* @__PURE__ */ h("span", { style: "width:36px" })), /* @__PURE__ */ h("div", { class: "doc-install-body" }, /* @__PURE__ */ h("code", null, /* @__PURE__ */ h("span", { class: "doc-install-prompt" }, "$ "), install), /* @__PURE__ */ h("button", {
|
|
1075
|
+
type: "button",
|
|
1076
|
+
class: "doc-install-copy",
|
|
1077
|
+
"data-copy-text": install,
|
|
1078
|
+
onclick: `navigator.clipboard.writeText(this.dataset.copyText);this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500)`
|
|
1079
|
+
}, "Copy")))) : null, features && features.length > 0 ? /* @__PURE__ */ h("section", { class: "doc-home-section" }, /* @__PURE__ */ h("p", { class: "doc-home-section-label" }, "Features"), /* @__PURE__ */ h("div", { class: "doc-features" }, features.map((feature) => /* @__PURE__ */ h("div", { class: "doc-feature-card" }, feature.icon ? /* @__PURE__ */ h("span", {
|
|
1080
|
+
class: "doc-feature-icon",
|
|
1081
|
+
innerHTML: feature.icon
|
|
1082
|
+
}) : null, /* @__PURE__ */ h("h3", { class: "doc-feature-title" }, feature.title), /* @__PURE__ */ h("p", { class: "doc-feature-details" }, feature.details))))) : null, packages && packages.length > 0 ? /* @__PURE__ */ h("section", { class: "doc-home-section" }, /* @__PURE__ */ h("p", { class: "doc-home-section-label" }, "Packages"), /* @__PURE__ */ h("div", { class: "doc-packages" }, packages.map((pkg) => {
|
|
1083
|
+
return /* @__PURE__ */ h(pkg.href ? "a" : "div", {
|
|
1084
|
+
class: "doc-package-card",
|
|
1085
|
+
href: pkg.href || void 0
|
|
1086
|
+
}, /* @__PURE__ */ h("div", { class: "doc-package-name" }, pkg.name), /* @__PURE__ */ h("p", { class: "doc-package-desc" }, pkg.description), pkg.version || pkg.tag ? /* @__PURE__ */ h("div", { class: "doc-package-meta" }, pkg.version ? /* @__PURE__ */ h("span", { class: "doc-package-version" }, pkg.version) : null, pkg.tag ? /* @__PURE__ */ h("span", { class: "doc-package-tag" }, pkg.tag) : null) : null);
|
|
1087
|
+
}))) : null, codeExample ? /* @__PURE__ */ h("section", { class: "doc-home-section" }, /* @__PURE__ */ h("p", { class: "doc-home-section-label" }, codeExample.label || "Quick Start"), /* @__PURE__ */ h("div", { class: "doc-home-code" }, /* @__PURE__ */ h("div", { class: "doc-home-code-header" }, /* @__PURE__ */ h("span", { class: "doc-install-dot doc-install-dot-r" }), /* @__PURE__ */ h("span", { class: "doc-install-dot doc-install-dot-y" }), /* @__PURE__ */ h("span", { class: "doc-install-dot doc-install-dot-g" }), /* @__PURE__ */ h("span", { class: "doc-home-code-title" }, codeExample.title || ""), /* @__PURE__ */ h("span", { style: "width:36px" })), /* @__PURE__ */ h("pre", { innerHTML: codeExample.code }))) : null, content ? /* @__PURE__ */ h("section", { class: "doc-home-content" }, /* @__PURE__ */ h("div", {
|
|
1088
|
+
class: "prose",
|
|
1089
|
+
innerHTML: content
|
|
1090
|
+
})) : null, /* @__PURE__ */ h("div", { class: "doc-home-footer" }, /* @__PURE__ */ h(DocFooter, {
|
|
1091
|
+
links: site.footerLinks,
|
|
1092
|
+
copyright: site.copyright
|
|
1093
|
+
}))));
|
|
1094
|
+
}
|
|
1095
|
+
//#endregion
|
|
1096
|
+
//#region theme/layouts/DocNotFound.tsx
|
|
1097
|
+
/**
|
|
1098
|
+
* DocNotFound layout.
|
|
1099
|
+
*
|
|
1100
|
+
* 404 page for documentation sites.
|
|
1101
|
+
*/
|
|
1102
|
+
function DocNotFound(props) {
|
|
1103
|
+
const { site, slug } = props;
|
|
1104
|
+
const homePath = site.homeLink || (site.basePath ? `${site.basePath}/` : "/");
|
|
1105
|
+
return /* @__PURE__ */ h(Html, {
|
|
1106
|
+
title: `Page Not Found — ${site.title}`,
|
|
1107
|
+
description: "The requested page could not be found.",
|
|
1108
|
+
url: `${slug}/`,
|
|
1109
|
+
site
|
|
1110
|
+
}, /* @__PURE__ */ h(DocHeader, {
|
|
1111
|
+
siteName: site.name,
|
|
1112
|
+
basePath: site.basePath,
|
|
1113
|
+
homeLink: site.homeLink,
|
|
1114
|
+
navItems: site.navItems,
|
|
1115
|
+
slug,
|
|
1116
|
+
searchEnabled: site.search?.enabled
|
|
1117
|
+
}), /* @__PURE__ */ h("main", { class: "doc-not-found" }, /* @__PURE__ */ h("div", { class: "doc-not-found-container" }, /* @__PURE__ */ h("p", { class: "doc-not-found-code" }, "404"), /* @__PURE__ */ h("h1", { class: "doc-not-found-title" }, "Page Not Found"), /* @__PURE__ */ h("p", { class: "doc-not-found-text" }, "The page you are looking for might have been moved or no longer exists."), /* @__PURE__ */ h("div", { class: "doc-not-found-actions" }, /* @__PURE__ */ h("a", {
|
|
1118
|
+
href: homePath,
|
|
1119
|
+
class: "doc-not-found-btn doc-not-found-btn-primary"
|
|
1120
|
+
}, "Go Home")))));
|
|
1121
|
+
}
|
|
1122
|
+
//#endregion
|
|
1123
|
+
//#region theme/components/DocTOC.tsx
|
|
1124
|
+
function DocTOC({ headings, title = "On this page" }) {
|
|
1125
|
+
const filtered = headings.filter((h) => h.depth >= 2 && h.depth <= 3);
|
|
1126
|
+
if (filtered.length === 0) return /* @__PURE__ */ h(Fragment, null);
|
|
1127
|
+
return /* @__PURE__ */ h("nav", {
|
|
1128
|
+
class: "doc-toc",
|
|
1129
|
+
"aria-label": "Table of contents"
|
|
1130
|
+
}, /* @__PURE__ */ h("p", { class: "doc-toc-title" }, title), /* @__PURE__ */ h("ul", { class: "doc-toc-list" }, filtered.map((heading) => /* @__PURE__ */ h("li", { class: `doc-toc-item depth-${heading.depth}` }, /* @__PURE__ */ h("a", { href: `#${heading.slug}` }, heading.text)))));
|
|
1131
|
+
}
|
|
1132
|
+
//#endregion
|
|
1133
|
+
//#region theme/layouts/DocPage.tsx
|
|
1134
|
+
/**
|
|
1135
|
+
* DocPage layout.
|
|
1136
|
+
*
|
|
1137
|
+
* Standard documentation page with 3-column grid:
|
|
1138
|
+
* left sidebar (navigation) | content | right TOC
|
|
1139
|
+
*/
|
|
1140
|
+
function formatDate(isoDate) {
|
|
1141
|
+
return new Date(isoDate).toLocaleDateString("en-US", {
|
|
1142
|
+
year: "numeric",
|
|
1143
|
+
month: "long",
|
|
1144
|
+
day: "numeric"
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
function DocPage(props) {
|
|
1148
|
+
const { content, frontmatter, headings, slug, site, next, prev, sidebarSections, breadcrumbs, editUrl, editLabel, lastUpdated } = props;
|
|
1149
|
+
const pageTitle = frontmatter.title ? `${frontmatter.title} — ${site.title}` : site.title;
|
|
1150
|
+
const ogImage = frontmatter.socialImage ? frontmatter.socialImage.startsWith("http") ? frontmatter.socialImage : `${site.basePath || ""}/${frontmatter.socialImage.replace(/^\//, "")}` : void 0;
|
|
1151
|
+
const hasPageMeta = editUrl || lastUpdated;
|
|
1152
|
+
return /* @__PURE__ */ h(Html, {
|
|
1153
|
+
title: pageTitle,
|
|
1154
|
+
description: frontmatter.description || site.description,
|
|
1155
|
+
url: `${slug}/`,
|
|
1156
|
+
socialImage: ogImage,
|
|
1157
|
+
site
|
|
1158
|
+
}, /* @__PURE__ */ h(DocHeader, {
|
|
1159
|
+
siteName: site.name,
|
|
1160
|
+
basePath: site.basePath,
|
|
1161
|
+
homeLink: site.homeLink,
|
|
1162
|
+
navItems: site.navItems,
|
|
1163
|
+
slug,
|
|
1164
|
+
searchEnabled: site.search?.enabled
|
|
1165
|
+
}), /* @__PURE__ */ h("div", { class: "doc-layout" }, /* @__PURE__ */ h(DocSidebar, {
|
|
1166
|
+
sections: sidebarSections,
|
|
1167
|
+
currentSlug: slug,
|
|
1168
|
+
collapsible: site.sidebar?.collapsible
|
|
1169
|
+
}), /* @__PURE__ */ h("main", {
|
|
1170
|
+
class: "doc-main",
|
|
1171
|
+
"data-pagefind-body": ""
|
|
1172
|
+
}, breadcrumbs && breadcrumbs.length > 1 ? /* @__PURE__ */ h("nav", {
|
|
1173
|
+
class: "doc-breadcrumbs",
|
|
1174
|
+
"aria-label": "Breadcrumbs"
|
|
1175
|
+
}, breadcrumbs.map((crumb, i) => crumb.path ? /* @__PURE__ */ h(Fragment, null, i > 0 ? /* @__PURE__ */ h("span", {
|
|
1176
|
+
class: "doc-breadcrumb-sep",
|
|
1177
|
+
"aria-hidden": "true"
|
|
1178
|
+
}, "/") : null, /* @__PURE__ */ h("a", { href: `${crumb.path}/` }, crumb.label)) : /* @__PURE__ */ h(Fragment, null, i > 0 ? /* @__PURE__ */ h("span", {
|
|
1179
|
+
class: "doc-breadcrumb-sep",
|
|
1180
|
+
"aria-hidden": "true"
|
|
1181
|
+
}, "/") : null, /* @__PURE__ */ h("span", { "aria-current": "page" }, crumb.label)))) : null, headings.length > 0 ? /* @__PURE__ */ h("details", { class: "doc-toc-mobile" }, /* @__PURE__ */ h("summary", null, "On this page"), /* @__PURE__ */ h(DocTOC, { headings })) : null, /* @__PURE__ */ h("article", null, /* @__PURE__ */ h("div", {
|
|
1182
|
+
class: "prose",
|
|
1183
|
+
innerHTML: content
|
|
1184
|
+
})), hasPageMeta ? /* @__PURE__ */ h("div", { class: "doc-page-meta" }, editUrl ? /* @__PURE__ */ h("a", {
|
|
1185
|
+
href: editUrl,
|
|
1186
|
+
class: "doc-edit-link",
|
|
1187
|
+
target: "_blank",
|
|
1188
|
+
rel: "noopener noreferrer"
|
|
1189
|
+
}, editLabel || "Edit this page") : null, lastUpdated ? /* @__PURE__ */ h("span", { class: "doc-last-updated" }, "Last updated: ", /* @__PURE__ */ h("time", { datetime: lastUpdated }, formatDate(lastUpdated))) : null) : null, /* @__PURE__ */ h(DocFooter, {
|
|
1190
|
+
prev,
|
|
1191
|
+
next,
|
|
1192
|
+
links: site.footerLinks,
|
|
1193
|
+
copyright: site.copyright
|
|
1194
|
+
})), /* @__PURE__ */ h("aside", { class: "doc-aside" }, /* @__PURE__ */ h(DocTOC, { headings }))));
|
|
1195
|
+
}
|
|
1196
|
+
//#endregion
|
|
1197
|
+
//#region src/render.ts
|
|
1198
|
+
async function loadUserThemeModule(entryPath, rootDir) {
|
|
1199
|
+
const { build } = await import("rolldown");
|
|
1200
|
+
const { pathToFileURL } = await import("url");
|
|
1201
|
+
const cacheDir = join(rootDir, "node_modules", ".cache", "pagesmith-docs-layouts");
|
|
1202
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
1203
|
+
for (const file of readdirSync(cacheDir)) if (file.endsWith(".mjs")) try {
|
|
1204
|
+
rmSync(join(cacheDir, file));
|
|
1205
|
+
} catch {}
|
|
1206
|
+
const entryContent = readFileSync(entryPath, "utf-8");
|
|
1207
|
+
const contentHash = createHash("md5").update(entryContent).digest("hex").slice(0, 12);
|
|
1208
|
+
const outFile = join(cacheDir, `${basename(entryPath).replace(/[^a-z0-9]+/gi, "-").toLowerCase()}-${contentHash}.mjs`);
|
|
1209
|
+
if (!existsSync(outFile)) await build({
|
|
1210
|
+
input: entryPath,
|
|
1211
|
+
output: {
|
|
1212
|
+
file: outFile,
|
|
1213
|
+
format: "esm"
|
|
1214
|
+
},
|
|
1215
|
+
platform: "node",
|
|
1216
|
+
logLevel: "warn",
|
|
1217
|
+
external: [/^node:/, /^@pagesmith\//],
|
|
1218
|
+
moduleTypes: {
|
|
1219
|
+
".ts": "ts",
|
|
1220
|
+
".tsx": "tsx"
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
return import(`${pathToFileURL(outFile).href}?t=${Date.now()}`);
|
|
1224
|
+
}
|
|
1225
|
+
async function resolveDocsLayout(name, config, fallback) {
|
|
1226
|
+
const overridePath = config.theme?.layouts?.[name];
|
|
1227
|
+
if (!overridePath) {
|
|
1228
|
+
if (fallback) return fallback;
|
|
1229
|
+
throw new Error(`Theme layout "${name}" is referenced in meta.json5 but not registered in theme.layouts config`);
|
|
1230
|
+
}
|
|
1231
|
+
const absolutePath = resolve(config.rootDir, overridePath);
|
|
1232
|
+
const module = await loadUserThemeModule(absolutePath, config.rootDir);
|
|
1233
|
+
const exportNames = {
|
|
1234
|
+
home: [
|
|
1235
|
+
"default",
|
|
1236
|
+
"DocHome",
|
|
1237
|
+
"Home"
|
|
1238
|
+
],
|
|
1239
|
+
page: [
|
|
1240
|
+
"default",
|
|
1241
|
+
"DocPage",
|
|
1242
|
+
"Page"
|
|
1243
|
+
],
|
|
1244
|
+
notFound: [
|
|
1245
|
+
"default",
|
|
1246
|
+
"DocNotFound",
|
|
1247
|
+
"NotFound"
|
|
1248
|
+
]
|
|
1249
|
+
}[name] ?? ["default", name];
|
|
1250
|
+
for (const exportName of exportNames) {
|
|
1251
|
+
const candidate = module[exportName];
|
|
1252
|
+
if (typeof candidate === "function") return candidate;
|
|
1253
|
+
}
|
|
1254
|
+
throw new Error(`Theme layout "${name}" at ${absolutePath} must export a component as default or one of: ${exportNames.join(", ")}`);
|
|
1255
|
+
}
|
|
1256
|
+
async function resolveDocsLayouts(config, sectionMetas) {
|
|
1257
|
+
const registry = {
|
|
1258
|
+
home: await resolveDocsLayout("home", config, DocHome),
|
|
1259
|
+
page: await resolveDocsLayout("page", config, DocPage),
|
|
1260
|
+
notFound: await resolveDocsLayout("notFound", config, DocNotFound)
|
|
1261
|
+
};
|
|
1262
|
+
if (sectionMetas) {
|
|
1263
|
+
const extraNames = /* @__PURE__ */ new Set();
|
|
1264
|
+
for (const meta of sectionMetas.values()) {
|
|
1265
|
+
if (meta.layout && !registry[meta.layout]) extraNames.add(meta.layout);
|
|
1266
|
+
if (meta.itemLayout && !registry[meta.itemLayout]) extraNames.add(meta.itemLayout);
|
|
1267
|
+
}
|
|
1268
|
+
for (const name of extraNames) registry[name] = await resolveDocsLayout(name, config);
|
|
1269
|
+
}
|
|
1270
|
+
return registry;
|
|
1271
|
+
}
|
|
1272
|
+
function writeHtml(outDir, routePath, html) {
|
|
1273
|
+
const outputPath = routePath === "/" ? join(outDir, "index.html") : join(outDir, routePath.slice(1), "index.html");
|
|
1274
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
1275
|
+
writeFileSync(outputPath, `<!DOCTYPE html>\n${html}`);
|
|
1276
|
+
}
|
|
1277
|
+
async function renderDocs(config) {
|
|
1278
|
+
const rootMeta = loadRootMeta(config.contentDir);
|
|
1279
|
+
const sectionMetas = loadSectionMetas(config.contentDir);
|
|
1280
|
+
const pages = await loadDocsPages(config, sectionMetas);
|
|
1281
|
+
const model = buildSiteModel(config, pages, rootMeta, sectionMetas);
|
|
1282
|
+
const site = getSitePayload(config, model);
|
|
1283
|
+
const layouts = await resolveDocsLayouts(config, sectionMetas);
|
|
1284
|
+
const base = config.basePath;
|
|
1285
|
+
const buildEditUrl = config.editLink ? (sourcePath) => {
|
|
1286
|
+
const relPath = relative(config.rootDir, sourcePath);
|
|
1287
|
+
return `${config.editLink.editPattern}/${relPath}`;
|
|
1288
|
+
} : void 0;
|
|
1289
|
+
for (const page of pages) {
|
|
1290
|
+
const urlPath = `${base}${page.routePath}`;
|
|
1291
|
+
if (page.isHome) {
|
|
1292
|
+
const frontmatter = { ...page.frontmatter };
|
|
1293
|
+
if (frontmatter.hero?.actions) frontmatter.hero = {
|
|
1294
|
+
...frontmatter.hero,
|
|
1295
|
+
actions: frontmatter.hero.actions.map((a) => ({
|
|
1296
|
+
...a,
|
|
1297
|
+
link: typeof a.link === "string" && a.link.startsWith("/") ? `${base}${a.link}` : a.link
|
|
1298
|
+
}))
|
|
1299
|
+
};
|
|
1300
|
+
const homeActions = Array.isArray(frontmatter.actions) ? frontmatter.actions : void 0;
|
|
1301
|
+
if (homeActions) frontmatter.actions = homeActions.map((a) => ({
|
|
1302
|
+
...a,
|
|
1303
|
+
link: typeof a.link === "string" && a.link.startsWith("/") ? `${base}${a.link}` : a.link
|
|
1304
|
+
}));
|
|
1305
|
+
const output = (layouts[page.layoutName] ?? layouts.home)({
|
|
1306
|
+
content: page.html,
|
|
1307
|
+
frontmatter,
|
|
1308
|
+
headings: page.headings,
|
|
1309
|
+
slug: urlPath,
|
|
1310
|
+
site
|
|
1311
|
+
});
|
|
1312
|
+
writeHtml(config.outDir, page.routePath, String(output));
|
|
1313
|
+
continue;
|
|
1314
|
+
}
|
|
1315
|
+
const sidebarSections = page.section ? model.sidebarBySection.get(page.section) : void 0;
|
|
1316
|
+
const { prev, next } = getPrevNext(sidebarSections, urlPath);
|
|
1317
|
+
const breadcrumbs = buildBreadcrumbs(page.contentSlug, page.title, base);
|
|
1318
|
+
const editUrl = buildEditUrl ? buildEditUrl(page.sourcePath) : void 0;
|
|
1319
|
+
const output = (layouts[page.layoutName] ?? layouts.page)({
|
|
1320
|
+
content: page.html,
|
|
1321
|
+
frontmatter: page.frontmatter,
|
|
1322
|
+
headings: page.headings,
|
|
1323
|
+
slug: urlPath,
|
|
1324
|
+
site,
|
|
1325
|
+
sidebarSections,
|
|
1326
|
+
prev,
|
|
1327
|
+
next,
|
|
1328
|
+
breadcrumbs,
|
|
1329
|
+
editUrl,
|
|
1330
|
+
editLabel: config.editLink?.label,
|
|
1331
|
+
lastUpdated: page.lastUpdated
|
|
1332
|
+
});
|
|
1333
|
+
writeHtml(config.outDir, page.routePath, String(output));
|
|
1334
|
+
}
|
|
1335
|
+
const notFound = layouts.notFound({
|
|
1336
|
+
content: "",
|
|
1337
|
+
frontmatter: {
|
|
1338
|
+
title: "Page not found",
|
|
1339
|
+
description: "The page you requested could not be found."
|
|
1340
|
+
},
|
|
1341
|
+
headings: [],
|
|
1342
|
+
slug: `${base}/404`,
|
|
1343
|
+
site
|
|
1344
|
+
});
|
|
1345
|
+
const notFoundHtml = `<!DOCTYPE html>\n${String(notFound)}`;
|
|
1346
|
+
writeHtml(config.outDir, "/404", String(notFound));
|
|
1347
|
+
writeFileSync(join(config.outDir, "404.html"), notFoundHtml);
|
|
1348
|
+
return {
|
|
1349
|
+
pages,
|
|
1350
|
+
model
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
1353
|
+
//#endregion
|
|
1354
|
+
//#region src/build.ts
|
|
1355
|
+
async function bundleThemeAssets(config) {
|
|
1356
|
+
const assetsDir = join(config.outDir, "assets");
|
|
1357
|
+
mkdirSync(assetsDir, { recursive: true });
|
|
1358
|
+
const css = buildCss(getThemeStylesEntry(), { minify: true });
|
|
1359
|
+
writeFileSync(join(assetsDir, "style.css"), css);
|
|
1360
|
+
const { build } = await import("rolldown");
|
|
1361
|
+
await build({
|
|
1362
|
+
input: getThemeRuntimeEntry(),
|
|
1363
|
+
output: {
|
|
1364
|
+
dir: assetsDir,
|
|
1365
|
+
entryFileNames: "main.js",
|
|
1366
|
+
format: "esm",
|
|
1367
|
+
minify: true
|
|
1368
|
+
},
|
|
1369
|
+
platform: "browser",
|
|
1370
|
+
logLevel: "warn"
|
|
1371
|
+
});
|
|
1372
|
+
const coreFontsDir = join(dirname(fileURLToPath(import.meta.resolve("@pagesmith/core/package.json"))), "assets", "fonts");
|
|
1373
|
+
const outFontsDir = join(assetsDir, "fonts");
|
|
1374
|
+
mkdirSync(outFontsDir, { recursive: true });
|
|
1375
|
+
for (const file of readdirSync(coreFontsDir)) if (file.endsWith(".woff2")) copyFileSync(join(coreFontsDir, file), join(outFontsDir, file));
|
|
1376
|
+
}
|
|
1377
|
+
function copyPublicAssets(config) {
|
|
1378
|
+
copyPublicFiles(config.publicDir, config.outDir);
|
|
1379
|
+
}
|
|
1380
|
+
function copyDirRecursive(srcDir, destDir) {
|
|
1381
|
+
mkdirSync(destDir, { recursive: true });
|
|
1382
|
+
for (const entry of readdirSync(srcDir, { withFileTypes: true })) {
|
|
1383
|
+
const srcPath = join(srcDir, entry.name);
|
|
1384
|
+
const destPath = join(destDir, entry.name);
|
|
1385
|
+
if (entry.isDirectory()) copyDirRecursive(srcPath, destPath);
|
|
1386
|
+
else copyFileSync(srcPath, destPath);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
function copyMappedAssets(config) {
|
|
1390
|
+
for (const [outputPath, sources] of config.assets) {
|
|
1391
|
+
const destDir = outputPath === "/" ? config.outDir : join(config.outDir, outputPath);
|
|
1392
|
+
mkdirSync(destDir, { recursive: true });
|
|
1393
|
+
for (const sourcePath of sources) {
|
|
1394
|
+
if (!existsSync(sourcePath)) continue;
|
|
1395
|
+
if (statSync(sourcePath).isDirectory()) copyDirRecursive(sourcePath, join(destDir, basename(sourcePath)));
|
|
1396
|
+
else copyFileSync(sourcePath, join(destDir, basename(sourcePath)));
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
function copyContentAssetsToOutput(outDir, assets) {
|
|
1401
|
+
if (assets.size === 0) return;
|
|
1402
|
+
const assetsDir = join(outDir, "assets");
|
|
1403
|
+
mkdirSync(assetsDir, { recursive: true });
|
|
1404
|
+
for (const [fileName, sourcePath] of assets) copyFileSync(sourcePath, join(assetsDir, fileName));
|
|
1405
|
+
}
|
|
1406
|
+
async function runPagefind(outDir, extraFlags = []) {
|
|
1407
|
+
const { fileURLToPath } = await import("url");
|
|
1408
|
+
const binaryPath = join(join(fileURLToPath(import.meta.resolve("pagefind")), "..", ".."), "lib", "runner", "bin.cjs");
|
|
1409
|
+
const { execFileSync } = await import("child_process");
|
|
1410
|
+
execFileSync(process.execPath, [
|
|
1411
|
+
binaryPath,
|
|
1412
|
+
"--site",
|
|
1413
|
+
outDir,
|
|
1414
|
+
...extraFlags
|
|
1415
|
+
], { stdio: "inherit" });
|
|
1416
|
+
}
|
|
1417
|
+
function generateSitemap(pages, config) {
|
|
1418
|
+
const base = `${config.origin}${config.basePath}`;
|
|
1419
|
+
return [
|
|
1420
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
|
1421
|
+
"<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">",
|
|
1422
|
+
...pages.filter((p) => !p.frontmatter.draft).map((p) => {
|
|
1423
|
+
return ` <url><loc>${p.isHome ? `${base}/` : `${base}${p.routePath}/`}</loc></url>`;
|
|
1424
|
+
}),
|
|
1425
|
+
"</urlset>"
|
|
1426
|
+
].join("\n");
|
|
1427
|
+
}
|
|
1428
|
+
const LLMS_FILES = ["llms.txt", "llms-full.txt"];
|
|
1429
|
+
function copyLlmsFiles(config) {
|
|
1430
|
+
for (const fileName of LLMS_FILES) {
|
|
1431
|
+
const sourcePath = join(config.rootDir, fileName);
|
|
1432
|
+
const destPath = join(config.outDir, fileName);
|
|
1433
|
+
if (existsSync(sourcePath) && !existsSync(destPath)) copyFileSync(sourcePath, destPath);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
async function build(options = {}) {
|
|
1437
|
+
const startTime = performance.now();
|
|
1438
|
+
const config = resolveDocsConfig(options.configPath, {
|
|
1439
|
+
outDir: options.outDir,
|
|
1440
|
+
basePath: options.basePath
|
|
1441
|
+
});
|
|
1442
|
+
const issues = validateConfig(config);
|
|
1443
|
+
if (issues.length > 0) {
|
|
1444
|
+
console.log();
|
|
1445
|
+
const hasErrors = reportConfigIssues(issues);
|
|
1446
|
+
console.log();
|
|
1447
|
+
if (hasErrors) throw new Error("Config validation failed — fix the errors above before building.");
|
|
1448
|
+
}
|
|
1449
|
+
if (existsSync(config.outDir)) rmSync(config.outDir, {
|
|
1450
|
+
recursive: true,
|
|
1451
|
+
force: true
|
|
1452
|
+
});
|
|
1453
|
+
mkdirSync(config.outDir, { recursive: true });
|
|
1454
|
+
const contentAssets = collectContentAssets(config.contentDir);
|
|
1455
|
+
await bundleThemeAssets(config);
|
|
1456
|
+
const { pages } = await renderDocs(config);
|
|
1457
|
+
copyPublicAssets(config);
|
|
1458
|
+
copyMappedAssets(config);
|
|
1459
|
+
copyContentAssetsToOutput(config.outDir, contentAssets);
|
|
1460
|
+
if (config.favicon) {
|
|
1461
|
+
const faviconDest = join(config.outDir, basename(config.favicon));
|
|
1462
|
+
if (!existsSync(faviconDest)) copyFileSync(config.favicon, faviconDest);
|
|
1463
|
+
}
|
|
1464
|
+
copyLlmsFiles(config);
|
|
1465
|
+
writeFileSync(join(config.outDir, ".nojekyll"), "");
|
|
1466
|
+
if (config.sitemap && config.origin !== "https://example.com") writeFileSync(join(config.outDir, "sitemap.xml"), generateSitemap(pages, config));
|
|
1467
|
+
const robotsPath = join(config.outDir, "robots.txt");
|
|
1468
|
+
if (!existsSync(robotsPath)) writeFileSync(robotsPath, `User-agent: *\nAllow: /${config.sitemap && config.origin !== "https://example.com" ? `\nSitemap: ${config.origin}${config.basePath}/sitemap.xml` : ""}\n`);
|
|
1469
|
+
const duration = ((performance.now() - startTime) / 1e3).toFixed(1);
|
|
1470
|
+
const sectionCount = new Set(pages.map((p) => p.section).filter(Boolean)).size;
|
|
1471
|
+
console.log();
|
|
1472
|
+
console.log(` Built ${pages.length} pages in ${sectionCount} sections (${duration}s)`);
|
|
1473
|
+
if (config.search.enabled) {
|
|
1474
|
+
console.log();
|
|
1475
|
+
try {
|
|
1476
|
+
await runPagefind(config.outDir, config.search.pagefindFlags);
|
|
1477
|
+
} catch (error) {
|
|
1478
|
+
console.warn(`\x1b[33m⚠ Pagefind indexing failed — search will not be available.\x1b[0m`);
|
|
1479
|
+
console.warn(` ${error instanceof Error ? error.message : String(error)}`);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* Rebuild content only — skips theme bundling and Pagefind indexing.
|
|
1485
|
+
* Used by the dev server for fast content-only rebuilds.
|
|
1486
|
+
*/
|
|
1487
|
+
async function rebuildContent(options = {}) {
|
|
1488
|
+
const config = resolveDocsConfig(options.configPath, {
|
|
1489
|
+
outDir: options.outDir,
|
|
1490
|
+
basePath: options.basePath
|
|
1491
|
+
});
|
|
1492
|
+
const contentAssets = collectContentAssets(config.contentDir);
|
|
1493
|
+
await renderDocs(config);
|
|
1494
|
+
copyPublicAssets(config);
|
|
1495
|
+
copyMappedAssets(config);
|
|
1496
|
+
copyContentAssetsToOutput(config.outDir, contentAssets);
|
|
1497
|
+
if (config.favicon) {
|
|
1498
|
+
const faviconDest = join(config.outDir, basename(config.favicon));
|
|
1499
|
+
if (!existsSync(faviconDest)) copyFileSync(config.favicon, faviconDest);
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
//#endregion
|
|
1503
|
+
//#region src/server.ts
|
|
1504
|
+
const MIME = {
|
|
1505
|
+
".html": "text/html; charset=utf-8",
|
|
1506
|
+
".css": "text/css; charset=utf-8",
|
|
1507
|
+
".js": "text/javascript; charset=utf-8",
|
|
1508
|
+
".json": "application/json",
|
|
1509
|
+
".png": "image/png",
|
|
1510
|
+
".jpg": "image/jpeg",
|
|
1511
|
+
".jpeg": "image/jpeg",
|
|
1512
|
+
".gif": "image/gif",
|
|
1513
|
+
".svg": "image/svg+xml",
|
|
1514
|
+
".webp": "image/webp",
|
|
1515
|
+
".ico": "image/x-icon",
|
|
1516
|
+
".woff": "font/woff",
|
|
1517
|
+
".woff2": "font/woff2",
|
|
1518
|
+
".xml": "application/xml",
|
|
1519
|
+
".txt": "text/plain; charset=utf-8"
|
|
1520
|
+
};
|
|
1521
|
+
const WS_CLIENT_SCRIPT = `<script>
|
|
1522
|
+
(function() {
|
|
1523
|
+
var ws = new WebSocket('ws://' + location.host + '/__ws');
|
|
1524
|
+
ws.onmessage = function(e) {
|
|
1525
|
+
var msg = JSON.parse(e.data);
|
|
1526
|
+
if (msg.type === 'reload') location.reload();
|
|
1527
|
+
};
|
|
1528
|
+
ws.onclose = function() {
|
|
1529
|
+
setTimeout(function() { location.reload(); }, 1000);
|
|
1530
|
+
};
|
|
1531
|
+
})();
|
|
1532
|
+
<\/script>`;
|
|
1533
|
+
function serveFile(filePath, res, injectReload = false, statusCode = 200) {
|
|
1534
|
+
const ext = extname(filePath);
|
|
1535
|
+
const contentType = MIME[ext] || "application/octet-stream";
|
|
1536
|
+
const body = readFileSync(filePath);
|
|
1537
|
+
if (ext === ".html" && injectReload) {
|
|
1538
|
+
const html = body.toString().replace("</body>", `${WS_CLIENT_SCRIPT}</body>`);
|
|
1539
|
+
res.writeHead(statusCode, { "Content-Type": contentType });
|
|
1540
|
+
res.end(html);
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
res.writeHead(statusCode, { "Content-Type": contentType });
|
|
1544
|
+
res.end(body);
|
|
1545
|
+
}
|
|
1546
|
+
async function loadSiteModel(config) {
|
|
1547
|
+
const rootMeta = loadRootMeta(config.contentDir);
|
|
1548
|
+
const sectionMetas = loadSectionMetas(config.contentDir);
|
|
1549
|
+
return buildSiteModel(config, await loadDocsPages(config, sectionMetas), rootMeta, sectionMetas);
|
|
1550
|
+
}
|
|
1551
|
+
function logStartupSummary(config, model, baseUrl) {
|
|
1552
|
+
const pageCount = model.pageByPath.size;
|
|
1553
|
+
const sectionCount = model.sidebarBySection.size;
|
|
1554
|
+
console.log(` ${pageCount} pages in ${sectionCount} sections`);
|
|
1555
|
+
console.log();
|
|
1556
|
+
for (const [, sections] of model.sidebarBySection) {
|
|
1557
|
+
const itemCount = sections.reduce((sum, s) => sum + s.items.length, 0);
|
|
1558
|
+
const title = sections[0]?.title ?? "(unknown)";
|
|
1559
|
+
const firstPath = sections[0]?.items[0]?.path ?? "";
|
|
1560
|
+
const url = firstPath ? `${baseUrl.replace(/\/$/, "")}${firstPath}/` : baseUrl;
|
|
1561
|
+
console.log(` ${title} (${itemCount} pages) ${url}`);
|
|
1562
|
+
}
|
|
1563
|
+
console.log();
|
|
1564
|
+
}
|
|
1565
|
+
function openBrowser(url) {
|
|
1566
|
+
exec(`${process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open"} ${url}`);
|
|
1567
|
+
}
|
|
1568
|
+
function isPortAvailable(port) {
|
|
1569
|
+
return new Promise((resolve) => {
|
|
1570
|
+
const server = createServer$1();
|
|
1571
|
+
server.once("error", () => resolve(false));
|
|
1572
|
+
server.once("listening", () => {
|
|
1573
|
+
server.close(() => resolve(true));
|
|
1574
|
+
});
|
|
1575
|
+
server.listen(port);
|
|
1576
|
+
});
|
|
1577
|
+
}
|
|
1578
|
+
async function findAvailablePort(startPort, strictPort, label) {
|
|
1579
|
+
if (await isPortAvailable(startPort)) return startPort;
|
|
1580
|
+
if (strictPort) throw new Error(`Port ${startPort} is already in use (${label}). Disable strictPort to auto-find an available port.`);
|
|
1581
|
+
const maxAttempts = 20;
|
|
1582
|
+
for (let port = startPort + 1; port < startPort + maxAttempts; port++) if (await isPortAvailable(port)) {
|
|
1583
|
+
console.log(` Port ${startPort} in use, using ${port}`);
|
|
1584
|
+
return port;
|
|
1585
|
+
}
|
|
1586
|
+
throw new Error(`No available port found in range ${startPort}–${startPort + maxAttempts - 1}`);
|
|
1587
|
+
}
|
|
1588
|
+
async function startDev(options = {}) {
|
|
1589
|
+
const configPath = resolve(options.configPath ?? join(process.cwd(), "pagesmith.config.json5"));
|
|
1590
|
+
await build({ configPath });
|
|
1591
|
+
const config = resolveDocsConfig(configPath);
|
|
1592
|
+
const port = await findAvailablePort(options.port ?? config.server.devPort, config.server.strictPort, "dev");
|
|
1593
|
+
const themeRoot = getThemeRoot();
|
|
1594
|
+
const watchTargets = [
|
|
1595
|
+
config.contentDir,
|
|
1596
|
+
configPath,
|
|
1597
|
+
themeRoot
|
|
1598
|
+
];
|
|
1599
|
+
if (existsSync(config.publicDir)) watchTargets.push(config.publicDir);
|
|
1600
|
+
let rebuilding = false;
|
|
1601
|
+
let pending = false;
|
|
1602
|
+
const clients = /* @__PURE__ */ new Set();
|
|
1603
|
+
const base = config.basePath.replace(/\/+$/, "");
|
|
1604
|
+
function log(status, method, pathname) {
|
|
1605
|
+
console.log(` ${status < 300 ? "\x1B[32m" : status < 400 ? "\x1B[36m" : "\x1B[33m"}${status}\x1b[0m ${method} ${pathname}`);
|
|
1606
|
+
}
|
|
1607
|
+
function notifyClients() {
|
|
1608
|
+
const payload = JSON.stringify({ type: "reload" });
|
|
1609
|
+
for (const client of clients) client.send(payload);
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Determine rebuild type based on changed file path.
|
|
1613
|
+
* Config/theme changes require full rebuild; content changes only need content rebuild.
|
|
1614
|
+
*/
|
|
1615
|
+
function getChangeType(changedPath) {
|
|
1616
|
+
const resolved = resolve(changedPath);
|
|
1617
|
+
if (resolved === resolve(configPath)) return "full";
|
|
1618
|
+
if (resolved.startsWith(resolve(themeRoot))) return "full";
|
|
1619
|
+
return "content";
|
|
1620
|
+
}
|
|
1621
|
+
async function doRebuild(type) {
|
|
1622
|
+
const start = performance.now();
|
|
1623
|
+
if (type === "full") await build({ configPath });
|
|
1624
|
+
else await rebuildContent({ configPath });
|
|
1625
|
+
const elapsed = Math.round(performance.now() - start);
|
|
1626
|
+
console.log(` \x1b[36m${type === "full" ? "Full rebuild" : "Content rebuild"} in ${elapsed}ms\x1b[0m`);
|
|
1627
|
+
}
|
|
1628
|
+
const server = createServer((req, res) => {
|
|
1629
|
+
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
1630
|
+
const method = req.method || "GET";
|
|
1631
|
+
let pathname = url.pathname;
|
|
1632
|
+
if (base && (pathname === "/" || pathname === "")) {
|
|
1633
|
+
log(302, method, pathname);
|
|
1634
|
+
res.writeHead(302, { Location: `${base}/` });
|
|
1635
|
+
res.end();
|
|
1636
|
+
return;
|
|
1637
|
+
}
|
|
1638
|
+
if (base && pathname.startsWith(base)) pathname = pathname.slice(base.length) || "/";
|
|
1639
|
+
if (pathname.startsWith("/assets/fonts/")) {
|
|
1640
|
+
const fontFile = pathname.replace("/assets/fonts/", "");
|
|
1641
|
+
const fontPath = join(dirname(fileURLToPath(import.meta.resolve("@pagesmith/core/package.json"))), "assets", "fonts", fontFile);
|
|
1642
|
+
if (existsSync(fontPath)) {
|
|
1643
|
+
log(200, method, url.pathname);
|
|
1644
|
+
res.writeHead(200, {
|
|
1645
|
+
"Content-Type": "font/woff2",
|
|
1646
|
+
"Cache-Control": "public, max-age=31536000"
|
|
1647
|
+
});
|
|
1648
|
+
res.end(readFileSync(fontPath));
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
let filePath = join(config.outDir, pathname);
|
|
1653
|
+
if (existsSync(filePath) && !extname(filePath)) filePath = join(filePath, "index.html");
|
|
1654
|
+
if (!existsSync(filePath)) {
|
|
1655
|
+
const notFoundDir = join(config.outDir, "404", "index.html");
|
|
1656
|
+
const notFoundFile = join(config.outDir, "404.html");
|
|
1657
|
+
const notFoundPath = existsSync(notFoundDir) ? notFoundDir : existsSync(notFoundFile) ? notFoundFile : null;
|
|
1658
|
+
if (notFoundPath) {
|
|
1659
|
+
log(404, method, url.pathname);
|
|
1660
|
+
serveFile(notFoundPath, res, true, 404);
|
|
1661
|
+
return;
|
|
1662
|
+
}
|
|
1663
|
+
log(404, method, url.pathname);
|
|
1664
|
+
res.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
|
|
1665
|
+
res.end("<h1>404</h1>");
|
|
1666
|
+
return;
|
|
1667
|
+
}
|
|
1668
|
+
log(200, method, url.pathname);
|
|
1669
|
+
serveFile(filePath, res, true);
|
|
1670
|
+
});
|
|
1671
|
+
new WebSocketServer({
|
|
1672
|
+
server,
|
|
1673
|
+
path: "/__ws"
|
|
1674
|
+
}).on("connection", (socket) => {
|
|
1675
|
+
clients.add(socket);
|
|
1676
|
+
socket.on("close", () => clients.delete(socket));
|
|
1677
|
+
});
|
|
1678
|
+
const devUrl = `http://localhost:${port}${base}/`;
|
|
1679
|
+
const model = await loadSiteModel(config);
|
|
1680
|
+
server.listen(port, () => {
|
|
1681
|
+
console.log();
|
|
1682
|
+
console.log(` Docs dev: ${devUrl}`);
|
|
1683
|
+
console.log();
|
|
1684
|
+
logStartupSummary(config, model, devUrl);
|
|
1685
|
+
if (options.open) openBrowser(devUrl);
|
|
1686
|
+
});
|
|
1687
|
+
watch(watchTargets, { ignoreInitial: true }).on("all", async (_event, changedPath) => {
|
|
1688
|
+
const changeType = getChangeType(changedPath);
|
|
1689
|
+
if (rebuilding) {
|
|
1690
|
+
pending = pending === "full" || changeType === "full" ? "full" : "content";
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
rebuilding = true;
|
|
1694
|
+
try {
|
|
1695
|
+
await doRebuild(changeType);
|
|
1696
|
+
notifyClients();
|
|
1697
|
+
} catch (err) {
|
|
1698
|
+
console.error("Rebuild failed:", err instanceof Error ? err.message : err);
|
|
1699
|
+
} finally {
|
|
1700
|
+
rebuilding = false;
|
|
1701
|
+
if (pending) {
|
|
1702
|
+
const nextType = pending;
|
|
1703
|
+
pending = false;
|
|
1704
|
+
rebuilding = true;
|
|
1705
|
+
try {
|
|
1706
|
+
await doRebuild(nextType);
|
|
1707
|
+
notifyClients();
|
|
1708
|
+
} catch (err) {
|
|
1709
|
+
console.error("Rebuild failed:", err instanceof Error ? err.message : err);
|
|
1710
|
+
} finally {
|
|
1711
|
+
rebuilding = false;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
});
|
|
1716
|
+
}
|
|
1717
|
+
async function preview(options = {}) {
|
|
1718
|
+
const config = resolveDocsConfig(options.configPath);
|
|
1719
|
+
const port = await findAvailablePort(options.port ?? config.server.previewPort, config.server.strictPort, "preview");
|
|
1720
|
+
const previewBase = config.basePath.replace(/\/+$/, "");
|
|
1721
|
+
const server = createServer((req, res) => {
|
|
1722
|
+
let pathname = new URL(req.url || "/", `http://localhost:${port}`).pathname;
|
|
1723
|
+
if (previewBase && (pathname === "/" || pathname === "")) {
|
|
1724
|
+
res.writeHead(302, { Location: `${previewBase}/` });
|
|
1725
|
+
res.end();
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
if (previewBase && pathname.startsWith(previewBase)) pathname = pathname.slice(previewBase.length) || "/";
|
|
1729
|
+
let filePath = join(config.outDir, pathname);
|
|
1730
|
+
if (existsSync(filePath) && !extname(filePath)) filePath = join(filePath, "index.html");
|
|
1731
|
+
if (!existsSync(filePath)) {
|
|
1732
|
+
filePath = join(config.outDir, "404", "index.html");
|
|
1733
|
+
if (!existsSync(filePath)) {
|
|
1734
|
+
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
1735
|
+
res.end("Not found");
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
serveFile(filePath, res, false, 404);
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1741
|
+
serveFile(filePath, res);
|
|
1742
|
+
});
|
|
1743
|
+
const previewUrl = `http://localhost:${port}${previewBase}/`;
|
|
1744
|
+
const model = await loadSiteModel(config);
|
|
1745
|
+
server.listen(port, () => {
|
|
1746
|
+
console.log();
|
|
1747
|
+
console.log(` Docs preview: ${previewUrl}`);
|
|
1748
|
+
console.log();
|
|
1749
|
+
logStartupSummary(config, model, previewUrl);
|
|
1750
|
+
if (options.open) openBrowser(previewUrl);
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
//#endregion
|
|
1754
|
+
export { defineDocsConfig as a, reportConfigIssues as c, withBase as d, Html as i, resolveDocsConfig as l, startDev as n, detectGitOrigin as o, build as r, loadDocsConfig as s, preview as t, validateConfig as u };
|
|
1755
|
+
|
|
1756
|
+
//# sourceMappingURL=site-dJ3MiiW3.mjs.map
|