create-zudo-doc 2.4.0 → 2.5.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/dist/scaffold.d.ts +1 -1
- package/dist/scaffold.js +8 -6
- package/dist/settings-gen.js +2 -2
- package/package.json +1 -1
- package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +82 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +10 -2
package/dist/scaffold.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export { getSecondaryLang };
|
|
|
11
11
|
*
|
|
12
12
|
* Bumped in lockstep by scripts/release-create-zudo-doc.sh.
|
|
13
13
|
*/
|
|
14
|
-
export declare const ZUDO_DOC_PIN = "^2.
|
|
14
|
+
export declare const ZUDO_DOC_PIN = "^2.5.0";
|
|
15
15
|
export declare function scaffold(choices: UserChoices): Promise<void>;
|
package/dist/scaffold.js
CHANGED
|
@@ -18,7 +18,7 @@ export { getSecondaryLang };
|
|
|
18
18
|
*
|
|
19
19
|
* Bumped in lockstep by scripts/release-create-zudo-doc.sh.
|
|
20
20
|
*/
|
|
21
|
-
export const ZUDO_DOC_PIN = "^2.
|
|
21
|
+
export const ZUDO_DOC_PIN = "^2.5.0";
|
|
22
22
|
/**
|
|
23
23
|
* Files in `templates/base/**` that must never be copied into a generated
|
|
24
24
|
* project. Each entry is matched against the path relative to `templates/base/`
|
|
@@ -489,15 +489,17 @@ function generatePackageJson(choices) {
|
|
|
489
489
|
// next.74: routine toolchain bump from next.72 (next.73
|
|
490
490
|
// skipped), adopted in lockstep with the root package.json pins. No
|
|
491
491
|
// consumer-facing / CLI change.
|
|
492
|
-
// next.75
|
|
492
|
+
// next.75: toolchain bump from next.74 restoring Tailwind
|
|
493
493
|
// class-candidate scanning through symlinked project trees
|
|
494
494
|
// (zudolab/zudo-doc#2511), adopted in lockstep with the root package.json
|
|
495
495
|
// pins. No consumer-facing / CLI change.
|
|
496
|
-
|
|
497
|
-
|
|
496
|
+
// next.76 (current pin): routine toolchain bump from next.75, adopted in
|
|
497
|
+
// lockstep with the root package.json pins. No consumer-facing / CLI change.
|
|
498
|
+
"@takazudo/zfb": "0.1.0-next.76",
|
|
499
|
+
"@takazudo/zfb-runtime": "0.1.0-next.76",
|
|
498
500
|
// zfb-adapter-cloudflare — required for any route with `prerender = false`.
|
|
499
501
|
// Pinned in lockstep with @takazudo/zfb.
|
|
500
|
-
"@takazudo/zfb-adapter-cloudflare": "0.1.0-next.
|
|
502
|
+
"@takazudo/zfb-adapter-cloudflare": "0.1.0-next.76",
|
|
501
503
|
// @takazudo/zudo-doc — published from this monorepo via
|
|
502
504
|
// .github/workflows/publish-zudo-doc.yml. The pin here is bumped in
|
|
503
505
|
// lockstep by scripts/release-create-zudo-doc.sh whenever zudo-doc's
|
|
@@ -580,7 +582,7 @@ function generatePackageJson(choices) {
|
|
|
580
582
|
// @takazudo/zudo-doc/integrations/doc-history which in turn imports
|
|
581
583
|
// @takazudo/zudo-doc-history-server/git-history. Without this dep the
|
|
582
584
|
// plugin host fails at init with ERR_MODULE_NOT_FOUND — W8A (#1739).
|
|
583
|
-
deps["@takazudo/zudo-doc-history-server"] = "^2.
|
|
585
|
+
deps["@takazudo/zudo-doc-history-server"] = "^2.5.0";
|
|
584
586
|
// tsx is no longer needed here: the relocated package plugin imports the
|
|
585
587
|
// runner directly (no `tsx -e` spawn) since the package ships compiled
|
|
586
588
|
// dist/ — package-first migration #2321 (#2337).
|
package/dist/settings-gen.js
CHANGED
|
@@ -212,10 +212,10 @@ export function generateSettingsFile(choices) {
|
|
|
212
212
|
if (choices.features.includes("claudeResources")) {
|
|
213
213
|
lines.push(` claudeResources: {`);
|
|
214
214
|
lines.push(` claudeDir: ".claude",`);
|
|
215
|
-
lines.push(` } as { claudeDir: string; projectRoot?: string } | false,`);
|
|
215
|
+
lines.push(` } as { claudeDir: string; projectRoot?: string; scanRoot?: string } | false,`);
|
|
216
216
|
}
|
|
217
217
|
else {
|
|
218
|
-
lines.push(` claudeResources: false as { claudeDir: string; projectRoot?: string } | false,`);
|
|
218
|
+
lines.push(` claudeResources: false as { claudeDir: string; projectRoot?: string; scanRoot?: string } | false,`);
|
|
219
219
|
}
|
|
220
220
|
if (choices.features.includes("claudeResources")) {
|
|
221
221
|
lines.push(` defaultLocaleOnlyPrefixes: [`);
|
package/package.json
CHANGED
|
@@ -575,6 +575,88 @@ describe("generateClaudeResourcesDocs", () => {
|
|
|
575
575
|
});
|
|
576
576
|
});
|
|
577
577
|
|
|
578
|
+
// ---------------------------------------------------------------------------
|
|
579
|
+
// excludeDirs boundary matching (#2561)
|
|
580
|
+
// ---------------------------------------------------------------------------
|
|
581
|
+
|
|
582
|
+
describe("excludeDirs boundary matching", () => {
|
|
583
|
+
it("discovers CLAUDE.md in a prefix-colliding sibling of an excluded dir (dist-extra vs dist)", () => {
|
|
584
|
+
fs.mkdirSync(path.join(tmpDir, "dist-extra"), { recursive: true });
|
|
585
|
+
fs.writeFileSync(
|
|
586
|
+
path.join(tmpDir, "dist-extra", "CLAUDE.md"),
|
|
587
|
+
"# dist-extra instructions",
|
|
588
|
+
);
|
|
589
|
+
|
|
590
|
+
const result = generateClaudeResourcesDocs({
|
|
591
|
+
claudeDir,
|
|
592
|
+
projectRoot: tmpDir,
|
|
593
|
+
docsDir,
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
// root/CLAUDE.md (from the fixture) + dist-extra/CLAUDE.md
|
|
597
|
+
expect(result.claudemd).toBe(2);
|
|
598
|
+
const decoyPage = path.join(docsDir, "claude-md", "dist-extra.mdx");
|
|
599
|
+
expect(fs.existsSync(decoyPage)).toBe(true);
|
|
600
|
+
expect(fs.readFileSync(decoyPage, "utf8")).toContain("dist-extra instructions");
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
it("still excludes CLAUDE.md directly inside the excluded dist directory", () => {
|
|
604
|
+
fs.mkdirSync(path.join(tmpDir, "dist"), { recursive: true });
|
|
605
|
+
fs.writeFileSync(
|
|
606
|
+
path.join(tmpDir, "dist", "CLAUDE.md"),
|
|
607
|
+
"# dist instructions — should be excluded",
|
|
608
|
+
);
|
|
609
|
+
|
|
610
|
+
const result = generateClaudeResourcesDocs({
|
|
611
|
+
claudeDir,
|
|
612
|
+
projectRoot: tmpDir,
|
|
613
|
+
docsDir,
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
// Only root/CLAUDE.md (from the fixture) — dist/CLAUDE.md is excluded.
|
|
617
|
+
expect(result.claudemd).toBe(1);
|
|
618
|
+
expect(fs.existsSync(path.join(docsDir, "claude-md", "dist.mdx"))).toBe(false);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it("still excludes nested CLAUDE.md files under the excluded dist directory (exact-match boundary holds)", () => {
|
|
622
|
+
fs.mkdirSync(path.join(tmpDir, "dist", "nested"), { recursive: true });
|
|
623
|
+
fs.writeFileSync(
|
|
624
|
+
path.join(tmpDir, "dist", "nested", "CLAUDE.md"),
|
|
625
|
+
"# nested dist instructions — should be excluded",
|
|
626
|
+
);
|
|
627
|
+
|
|
628
|
+
const result = generateClaudeResourcesDocs({
|
|
629
|
+
claudeDir,
|
|
630
|
+
projectRoot: tmpDir,
|
|
631
|
+
docsDir,
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
// Only root/CLAUDE.md (from the fixture) — the whole dist/ subtree,
|
|
635
|
+
// including nested dirs, is excluded once the top-level dist match hits.
|
|
636
|
+
expect(result.claudemd).toBe(1);
|
|
637
|
+
expect(fs.existsSync(path.join(docsDir, "claude-md", "dist--nested.mdx"))).toBe(false);
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
it("still excludes docsDir contents when docsDir carries a trailing separator", () => {
|
|
641
|
+
// path.join preserves a trailing separator on a single argument, so the
|
|
642
|
+
// docsDir exclude entry keeps it — the boundary compare must not break.
|
|
643
|
+
fs.writeFileSync(
|
|
644
|
+
path.join(docsDir, "CLAUDE.md"),
|
|
645
|
+
"# decoy inside docsDir — should be excluded",
|
|
646
|
+
);
|
|
647
|
+
|
|
648
|
+
const result = generateClaudeResourcesDocs({
|
|
649
|
+
claudeDir,
|
|
650
|
+
projectRoot: tmpDir,
|
|
651
|
+
docsDir: docsDir + path.sep,
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
// Only root/CLAUDE.md (from the fixture) — docs/CLAUDE.md is excluded.
|
|
655
|
+
expect(result.claudemd).toBe(1);
|
|
656
|
+
expect(fs.existsSync(path.join(docsDir, "claude-md", "docs.mdx"))).toBe(false);
|
|
657
|
+
});
|
|
658
|
+
});
|
|
659
|
+
|
|
578
660
|
// ---------------------------------------------------------------------------
|
|
579
661
|
// CLAUDE.md repo-relative link downgrade (#2411, Class B)
|
|
580
662
|
// ---------------------------------------------------------------------------
|
package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts
CHANGED
|
@@ -214,11 +214,19 @@ function findClaudeMdFiles(dir: string, excludeDirs: string[]): string[] {
|
|
|
214
214
|
const results: string[] = [];
|
|
215
215
|
if (!fs.existsSync(dir)) return results;
|
|
216
216
|
|
|
217
|
+
// Strip trailing separators (path.join preserves one on e.g. "docs/") so the
|
|
218
|
+
// boundary compare below stays exact for such entries too.
|
|
219
|
+
const excludes = excludeDirs.map((d) =>
|
|
220
|
+
d.endsWith(path.sep) ? d.slice(0, -path.sep.length) : d,
|
|
221
|
+
);
|
|
222
|
+
|
|
217
223
|
for (const item of fs.readdirSync(dir)) {
|
|
218
224
|
if (item === "node_modules") continue;
|
|
219
225
|
if (item.startsWith(".")) continue;
|
|
220
226
|
const itemPath = path.join(dir, item);
|
|
221
|
-
|
|
227
|
+
// Path-segment-boundary-aware: a raw startsWith(d) would also match a
|
|
228
|
+
// sibling like "dist-extra" against an excluded "dist" (#2561).
|
|
229
|
+
if (excludes.some((d) => itemPath === d || itemPath.startsWith(d + path.sep))) continue;
|
|
222
230
|
|
|
223
231
|
// lstat (not stat) so symlinks aren't followed — a symlinked dir can point
|
|
224
232
|
// back into the project (e.g. e2e fixtures linking to packages/) or out to
|
|
@@ -231,7 +239,7 @@ function findClaudeMdFiles(dir: string, excludeDirs: string[]): string[] {
|
|
|
231
239
|
continue;
|
|
232
240
|
}
|
|
233
241
|
if (stat.isDirectory()) {
|
|
234
|
-
results.push(...findClaudeMdFiles(itemPath,
|
|
242
|
+
results.push(...findClaudeMdFiles(itemPath, excludes));
|
|
235
243
|
} else if (stat.isFile() && item === "CLAUDE.md") {
|
|
236
244
|
results.push(itemPath);
|
|
237
245
|
}
|