create-zudo-doc 5.24.1 → 5.25.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/CHANGELOG.md CHANGED
@@ -8,6 +8,23 @@ The format is based on Keep a Changelog, and release notes are generated from th
8
8
 
9
9
  No unreleased changes.
10
10
 
11
+ ## [5.25.0] - 2026-09-16
12
+
13
+ ### Bug Fixes
14
+
15
+ - The generated `scripts/check-links.js`'s MDX id scan no longer lets an escaped `\<` in prose start a fake tag that swallows a later element's static `id` across a blank line, wrongly reporting a valid anchor as broken. Projects that copied `scripts/check-links.js` from the template can re-copy it to pick up the fix. (0ea5eeae6)
16
+
17
+ ### Other Changes
18
+
19
+ - New scaffolds no longer add a `.zudo-doc/` entry to the generated `.gitignore`. The staging step it was for was removed from `@takazudo/zudo-doc`'s route injection — see that package's changelog. (54a3f12a9)
20
+ - Generated projects now pin `@takazudo/zfb`, `@takazudo/zfb-runtime`, and `@takazudo/zfb-md-wasm` to `2.18.0` (e4d4b64b3). That release reworks package-injected routes and plugin virtual modules and changes no API, export, or config default, so existing projects need no migration.
21
+
22
+ ## [5.24.2] - 2026-09-15
23
+
24
+ ### Bug Fixes
25
+
26
+ - Generated projects list `diff` only when doc history is enabled (directly, or through `bodyFootUtil`), and no longer list `katex` by default. Projects that turn on `math: true` install `katex` themselves (`pnpm add katex`). (c778ca989)
27
+
11
28
  ## [5.24.1] - 2026-09-15
12
29
 
13
30
  ### Other Changes
@@ -31,5 +31,5 @@ export declare function deriveDocSkillName(projectName: string): string;
31
31
  *
32
32
  * Bumped in lockstep by scripts/release-create-zudo-doc.sh.
33
33
  */
34
- export declare const ZUDO_DOC_PIN = "^5.24.1";
34
+ export declare const ZUDO_DOC_PIN = "^5.25.0";
35
35
  export declare function scaffold(choices: UserChoices): Promise<void>;
package/dist/scaffold.js CHANGED
@@ -47,7 +47,7 @@ export function deriveDocSkillName(projectName) {
47
47
  *
48
48
  * Bumped in lockstep by scripts/release-create-zudo-doc.sh.
49
49
  */
50
- export const ZUDO_DOC_PIN = "^5.24.1";
50
+ export const ZUDO_DOC_PIN = "^5.25.0";
51
51
  /**
52
52
  * Files in `templates/base/**` that must not be copied by the unconditional
53
53
  * base mirror. Each entry is matched against the path relative to
@@ -466,9 +466,6 @@ export async function scaffold(choices) {
466
466
  "# Cloudflare Wrangler",
467
467
  ".wrangler/",
468
468
  "",
469
- "# zudo-doc build artifact (routes-src/ staged here at build time)",
470
- ".zudo-doc/",
471
- "",
472
469
  ];
473
470
  // The doc-lookup skill is only generated when skillSymlinker is selected
474
471
  // (the setup-doc-skill.sh script and `setup:doc-skill` npm script are gated
@@ -778,9 +775,17 @@ function generatePackageJson(choices, localePlan) {
778
775
  // moved sizes; zfb-runtime and zfb-adapter-cloudflare change only their
779
776
  // README/description. No public API, export, config default, or engine
780
777
  // requirement moves, so a fresh scaffold needs no migration.
781
- "@takazudo/zfb": "2.17.0",
782
- "@takazudo/zfb-runtime": "2.17.0",
783
- "@takazudo/zfb-md-wasm": "2.17.0",
778
+ // 2.18.0: zfb reworks package-injected routes and plugin virtual modules —
779
+ // the islands scanner now resolves plugin virtual modules and is seeded with
780
+ // package-route entrypoints, dev CSS content globs are seeded from injected
781
+ // routes, injected-route entrypoints and their import closure are staged as
782
+ // exact files, and SSR virtual modules may import those canonical files while
783
+ // the hidden-path guard still holds. zfb-runtime, zfb-adapter-cloudflare, and
784
+ // md-wasm carry no package-specific change. No public API, export, config
785
+ // default, or engine requirement moves, so a fresh scaffold needs no migration.
786
+ "@takazudo/zfb": "2.18.0",
787
+ "@takazudo/zfb-runtime": "2.18.0",
788
+ "@takazudo/zfb-md-wasm": "2.18.0",
784
789
  // @takazudo/zudo-doc — published from this monorepo via
785
790
  // .github/workflows/publish-zudo-doc.yml. The pin here is bumped in
786
791
  // lockstep by scripts/release-create-zudo-doc.sh whenever zudo-doc's
@@ -821,25 +826,16 @@ function generatePackageJson(choices, localePlan) {
821
826
  // compiles. Same pin as host. Caught by W6B (#1735) consumer-build
822
827
  // verification.
823
828
  "preact-render-to-string": "^6.6.6",
824
- // katex — server-side LaTeX renderer used by the always-on
825
- // pages/lib/_math-block.tsx (called from pages/_mdx-components.ts
826
- // for `$…$` and `$$…$$` math nodes). Caught by W6B (#1735)
827
- // consumer-build verification — the import lives in the mirrored
828
- // pages, not behind any feature gate. Same pin as host.
829
- katex: "^0.16.38",
830
- // diff — required at build time by EVERY generated project, not just
831
- // docHistory ones. The always-copied host base template
832
- // `pages/lib/_doc-history-area.tsx` statically imports the real
833
- // `DocHistory` from `@takazudo/zudo-doc/doc-history` (to keep zfb's island
834
- // scanner chain page→stub→DocHistory walkable), which pulls
835
- // `@takazudo/zudo-doc/dist/doc-history/index.js`'s `await import("diff")`
836
- // into the bundle. With packageOwnedRoutes default ON (1.0), a
837
- // docHistory-off project still bundles that path, so without `diff` here
838
- // `zfb build` fails at esbuild with "Could not resolve 'diff'" (#2342).
839
- // `diff` is an *optional* peerDependency of @takazudo/zudo-doc, so a
840
- // missing copy produces no `pnpm install` warning — which is why this gap
841
- // shipped silently and only surfaced at build time.
842
- diff: "^8.0.3",
829
+ // katex is intentionally ABSENT here. `math` is not a create-zudo-doc
830
+ // feature (it defaults to `false` in DEFAULT_SETTINGS) and
831
+ // @takazudo/zudo-doc now loads katex via a rejection-handled dynamic
832
+ // import that stays non-build-fatal when the package is absent (#4206 /
833
+ // #4209). A project that turns `math: true` on by hand must
834
+ // `pnpm add katex` itself — see the math-equations doc.
835
+ // diff is likewise intentionally ABSENT from this unconditional block —
836
+ // it is added below, gated on the docHistory feature, for the same
837
+ // #4206 / #4209 reason: the doc-history route's `import("diff")` is now
838
+ // rejection-handled instead of build-fatal when docHistory is off.
843
839
  // (@takazudo/zdtp is NOT here — it is gated on the designTokenPanel
844
840
  // feature, see the block below. It WAS unconditional from #2660 through
845
841
  // #4018: `chrome/derive.tsx`'s `deriveBodyEndIslands` statically imports
@@ -881,6 +877,17 @@ function generatePackageJson(choices, localePlan) {
881
877
  // search ships as @takazudo/zudo-doc's own self-contained generated
882
878
  // search-widget script (custom word-match scorer) — no third-party search
883
879
  // engine dependency is needed here. Do not re-add minisearch/pagefind.
880
+ if (choices.features.includes("docHistory")) {
881
+ // diff powers the History dropdown's Compare view
882
+ // (`@takazudo/zudo-doc/doc-history`'s `await import("diff")`). #4209 made
883
+ // that import rejection-handled, so a docHistory-OFF project no longer
884
+ // needs the dep at all — including bodyFootUtil-only projects, since
885
+ // scaffold() already normalizes bodyFootUtil into docHistory before this
886
+ // function runs (see the co-enable block near the top of scaffold()).
887
+ // assetViewer alone does not reach this import and must not carry it
888
+ // (#4206 / #4209; it was an unconditional base dep before this fix).
889
+ deps.diff = "^8.0.3";
890
+ }
884
891
  if (choices.features.includes("designTokenPanel")) {
885
892
  // Only the design-token-panel feature graph reaches @takazudo/zdtp: the
886
893
  // panel payload loads through a rejection-handled `import("@takazudo/zdtp")`
@@ -892,9 +899,9 @@ function generatePackageJson(choices, localePlan) {
892
899
  }
893
900
  if (choices.features.includes("docHistory") ||
894
901
  choices.features.includes("assetViewer")) {
895
- // (`diff` remains an unconditional base dep — see the `deps` block above:
896
- // packageOwnedRoutes always bundles the doc-history-area path, whose
897
- // module-scope `diff` import is pulled in regardless of this flag. #2342.)
902
+ // (`diff` is gated separately, on docHistory alone — see the block just
903
+ // above this one. assetViewer does not reach the Compare view's
904
+ // `import("diff")`, so it must not add the dep on its own; #4206 / #4209.)
898
905
  //
899
906
  // @takazudo/zudo-doc-history-server is gated HERE because docHistory and
900
907
  // assetViewer are the only feature graphs that reach it. The doc-history
@@ -911,7 +918,7 @@ function generatePackageJson(choices, localePlan) {
911
918
  // `/exclude` at module scope from the always-bundled chrome graph; #3110
912
919
  // moved compileExclude into @takazudo/zudo-doc, so projects with both
913
920
  // docHistory and assetViewer off no longer need the package at all.
914
- deps["@takazudo/zudo-doc-history-server"] = "^5.24.1";
921
+ deps["@takazudo/zudo-doc-history-server"] = "^5.25.0";
915
922
  // tsx is no longer needed here: the relocated package plugin imports the
916
923
  // runner directly (no `tsx -e` spawn) since the package ships compiled
917
924
  // dist/ — package-first migration #2321 (#2337).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-zudo-doc",
3
- "version": "5.24.1",
3
+ "version": "5.25.0",
4
4
  "description": "Create a new zudo-doc documentation site",
5
5
  "license": "MIT",
6
6
  "author": "Takeshi Takatsudo",
@@ -663,8 +663,27 @@ function extractStaticMdxIds(body) {
663
663
  // (#4048). The rest of this pattern keeps its own semantics — `\bid` also
664
664
  // accepts `data-id`, and only non-empty quoted values count, unlike the
665
665
  // built-HTML id scan.
666
+ //
667
+ // Two extra guards, scoped to this MDX scan only (the shared
668
+ // HTML_ATTRIBUTE_RUN above is untouched — the built-HTML scans still rely on
669
+ // multi-line quoted attributes):
670
+ //
671
+ // - MDX_UNESCAPED_LT_LOOKBEHIND: an escaped `\<` in prose is valid MDX and
672
+ // must not start a fake tag. Parity matters, not just "preceded by a
673
+ // backslash" — `\\<` is an escaped backslash followed by an active `<`.
674
+ // The lookbehind is anchored at the run's start (`(?<!\\)`) so it judges
675
+ // the whole contiguous backslash run, not a suffix of it.
676
+ // - MDX_ID_ATTRIBUTE_RUN: without this, a fake tag opened by an escaped `<`
677
+ // can have prose apostrophes read as a `'...'` quoted value that crosses
678
+ // a real `>` and swallows a real element's id on a later line (#4218).
679
+ // Disallowing a blank line inside a quoted value bounds the damage to a
680
+ // single paragraph while still letting a real JSX tag — including a
681
+ // quoted value spanning one newline — match.
682
+ const MDX_UNESCAPED_LT_LOOKBEHIND = /(?<!(?<!\\)(?:\\\\)*\\)/.source;
683
+ const MDX_ID_ATTRIBUTE_RUN =
684
+ /(?:"(?:(?!\r?\n[ \t]*\r?\n)[^"])*"|'(?:(?!\r?\n[ \t]*\r?\n)[^'])*'|[^>"'])/.source;
666
685
  const regex = new RegExp(
667
- `<[A-Za-z]${HTML_ATTRIBUTE_RUN}*?\\bid\\s*=\\s*(?:"([^"]+)"|'([^']+)')${HTML_ATTRIBUTE_RUN}*>`,
686
+ `${MDX_UNESCAPED_LT_LOOKBEHIND}<[A-Za-z]${MDX_ID_ATTRIBUTE_RUN}*?\\bid\\s*=\\s*(?:"([^"]+)"|'([^']+)')${MDX_ID_ATTRIBUTE_RUN}*>`,
668
687
  "gs",
669
688
  );
670
689
  let match;