




















@@ -1,7 +1,8 @@
1+import { spawnSync } from "node:child_process";
12import fs from "node:fs";
23import path from "node:path";
34import JSON5 from "json5";
4-import { describe, expect, it } from "vitest";
5+import { describe, expect, it, vi } from "vitest";
5667const PLUGIN_DOCS_DIR = path.join(process.cwd(), "docs", "plugins");
78@@ -10,6 +11,54 @@ function lineNumberAt(source: string, index: number): number {
1011}
11121213function listMarkdownFiles(dir: string): string[] {
14+const externalFiles = listExternalMarkdownFiles(dir);
15+if (externalFiles) {
16+return externalFiles;
17+}
18+return walkMarkdownFiles(dir);
19+}
20+21+function listExternalMarkdownFiles(dir: string): string[] | null {
22+const repoPath = path.relative(process.cwd(), dir).split(path.sep).join("/");
23+return listGitMarkdownFiles(repoPath) ?? listFindMarkdownFiles(dir);
24+}
25+26+function listGitMarkdownFiles(repoPath: string): string[] | null {
27+const result = spawnSync("git", ["ls-files", "--", repoPath], {
28+cwd: process.cwd(),
29+encoding: "utf8",
30+maxBuffer: 1024 * 1024,
31+stdio: ["ignore", "pipe", "ignore"],
32+});
33+if (result.status !== 0) {
34+return null;
35+}
36+return result.stdout
37+.split("\n")
38+.map((line) => line.trim())
39+.filter((line) => line.endsWith(".md"))
40+.map((filePath) => path.join(process.cwd(), filePath))
41+.toSorted();
42+}
43+44+function listFindMarkdownFiles(dir: string): string[] | null {
45+const result = spawnSync("find", [dir, "-type", "f", "-name", "*.md"], {
46+cwd: process.cwd(),
47+encoding: "utf8",
48+maxBuffer: 1024 * 1024,
49+stdio: ["ignore", "pipe", "ignore"],
50+});
51+if (result.status !== 0) {
52+return null;
53+}
54+return result.stdout
55+.split("\n")
56+.map((line) => line.trim())
57+.filter((line) => line.length > 0)
58+.toSorted();
59+}
60+61+function walkMarkdownFiles(dir: string): string[] {
1362const files: string[] = [];
1463for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1564const entryPath = path.join(dir, entry.name);
@@ -23,6 +72,19 @@ function listMarkdownFiles(dir: string): string[] {
2372}
24732574describe("plugin docs examples", () => {
75+it("lists plugin docs without scanning directories in-process", () => {
76+const readDir = vi.spyOn(fs, "readdirSync");
77+try {
78+const files = listMarkdownFiles(PLUGIN_DOCS_DIR);
79+80+expect(files.length).toBeGreaterThan(0);
81+expect(files.every((filePath) => filePath.endsWith(".md"))).toBe(true);
82+expect(readDir).not.toHaveBeenCalled();
83+} finally {
84+readDir.mockRestore();
85+}
86+});
87+2688it("keeps plugin docs JSON fences parseable", () => {
2789const failures: string[] = [];
2890for (const docPath of listMarkdownFiles(PLUGIN_DOCS_DIR)) {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。