nuxt-agents-md 0.1.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 +48 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +69 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +258 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# nuxt-agents-md
|
|
2
|
+
|
|
3
|
+
Generate a Nuxt documentation index for AI coding agents. The Nuxt equivalent of [`npx @next/codemod agents-md`](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals).
|
|
4
|
+
|
|
5
|
+
Downloads the Nuxt docs matching your project's version, builds a compact pipe-delimited index, and injects it into your `CLAUDE.md` or `AGENTS.md`. Agents read local docs instead of guessing from training data.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx nuxt-agents-md
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This will:
|
|
14
|
+
|
|
15
|
+
1. Detect your Nuxt version from `package.json`
|
|
16
|
+
2. Download matching docs to `.nuxt-docs/` via git sparse-checkout
|
|
17
|
+
3. Build a ~4KB compressed index of all 220+ doc files
|
|
18
|
+
4. Inject it into `CLAUDE.md` between marker comments
|
|
19
|
+
|
|
20
|
+
### Options
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx nuxt-agents-md --output AGENTS.md # target a different file
|
|
24
|
+
npx nuxt-agents-md --version 4.3.1 # override detected version
|
|
25
|
+
npx nuxt-agents-md --docs-dir ./docs-ref # custom docs directory
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Re-running
|
|
29
|
+
|
|
30
|
+
The command is idempotent. Running it again updates the existing index in place (content between `<!-- NUXT-AGENTS-MD-START -->` and `<!-- NUXT-AGENTS-MD-END -->` markers).
|
|
31
|
+
|
|
32
|
+
## What gets injected
|
|
33
|
+
|
|
34
|
+
A single-line pipe-delimited index that tells the agent where to find each doc file:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
[Nuxt Docs Index]|root: ./.nuxt-docs|STOP. What you remember about Nuxt is WRONG...|1.getting-started:{01.introduction.md,02.installation.md,...}|4.api/2.composables:{use-fetch.md,use-async-data.md,...}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The agent reads the relevant `.nuxt-docs/` file when it needs to look something up — no network requests, no stale training data.
|
|
41
|
+
|
|
42
|
+
## Monorepo support
|
|
43
|
+
|
|
44
|
+
Automatically detects Nuxt in pnpm, npm, and yarn workspaces.
|
|
45
|
+
|
|
46
|
+
## License
|
|
47
|
+
|
|
48
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI for nuxt-agents-md.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx nuxt-agents-md # interactive (auto-detect version)
|
|
7
|
+
* npx nuxt-agents-md --output CLAUDE.md # specify output file
|
|
8
|
+
* npx nuxt-agents-md --version 4.3.1 # override version
|
|
9
|
+
* npx nuxt-agents-md --docs-dir .nuxt-docs # override docs destination
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI for nuxt-agents-md.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx nuxt-agents-md # interactive (auto-detect version)
|
|
7
|
+
* npx nuxt-agents-md --output CLAUDE.md # specify output file
|
|
8
|
+
* npx nuxt-agents-md --version 4.3.1 # override version
|
|
9
|
+
* npx nuxt-agents-md --docs-dir .nuxt-docs # override docs destination
|
|
10
|
+
*/
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { getNuxtVersion, pullDocs, collectDocFiles, buildDocTree, generateIndex, injectIndex, } from "./index.js";
|
|
14
|
+
function parseArgs(argv) {
|
|
15
|
+
const args = {};
|
|
16
|
+
for (let i = 0; i < argv.length; i++) {
|
|
17
|
+
if (argv[i].startsWith("--") && i + 1 < argv.length) {
|
|
18
|
+
args[argv[i].slice(2)] = argv[i + 1];
|
|
19
|
+
i++;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return args;
|
|
23
|
+
}
|
|
24
|
+
async function main() {
|
|
25
|
+
const cwd = process.cwd();
|
|
26
|
+
const args = parseArgs(process.argv.slice(2));
|
|
27
|
+
const outputFile = args.output || "CLAUDE.md";
|
|
28
|
+
const docsDir = path.isAbsolute(args["docs-dir"] || "")
|
|
29
|
+
? args["docs-dir"]
|
|
30
|
+
: path.join(cwd, args["docs-dir"] || ".nuxt-docs");
|
|
31
|
+
const versionOverride = args.version;
|
|
32
|
+
// Detect version
|
|
33
|
+
const detected = versionOverride ? { version: versionOverride } : getNuxtVersion(cwd);
|
|
34
|
+
console.log(`Nuxt version: ${detected.version || "unknown"}`);
|
|
35
|
+
if (!detected.version && !versionOverride) {
|
|
36
|
+
console.error(`Error: ${detected.error}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
// Download docs
|
|
40
|
+
console.log(`Downloading Nuxt docs to ${docsDir}...`);
|
|
41
|
+
const pull = await pullDocs({ cwd, version: versionOverride, docsDir });
|
|
42
|
+
if (!pull.success) {
|
|
43
|
+
console.error(`Error downloading docs: ${pull.error}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
console.log(`Downloaded docs for Nuxt ${pull.nuxtVersion}`);
|
|
47
|
+
// Build index
|
|
48
|
+
const files = collectDocFiles(pull.docsPath);
|
|
49
|
+
console.log(`Found ${files.length} doc files`);
|
|
50
|
+
const tree = buildDocTree(files);
|
|
51
|
+
// Use relative path in the index so it's portable across machines
|
|
52
|
+
const relativeDocsPath = path.relative(cwd, docsDir) || ".nuxt-docs";
|
|
53
|
+
const index = generateIndex({ docsPath: `./${relativeDocsPath}`, sections: tree, outputFile });
|
|
54
|
+
// Inject into target file
|
|
55
|
+
const outputPath = path.isAbsolute(outputFile) ? outputFile : path.join(cwd, outputFile);
|
|
56
|
+
let existing = "";
|
|
57
|
+
if (fs.existsSync(outputPath)) {
|
|
58
|
+
existing = fs.readFileSync(outputPath, "utf-8");
|
|
59
|
+
}
|
|
60
|
+
const result = injectIndex(existing, index);
|
|
61
|
+
fs.writeFileSync(outputPath, result, "utf-8");
|
|
62
|
+
const indexSize = Buffer.byteLength(index, "utf-8");
|
|
63
|
+
console.log(`Injected ${(indexSize / 1024).toFixed(1)}KB index into ${outputFile}`);
|
|
64
|
+
console.log("Done.");
|
|
65
|
+
}
|
|
66
|
+
main().catch((err) => {
|
|
67
|
+
console.error(err);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* nuxt-agents-md: Generate Nuxt documentation index for AI coding agents.
|
|
3
|
+
*
|
|
4
|
+
* Downloads docs from GitHub via git sparse-checkout, builds a compact
|
|
5
|
+
* index of all doc files, and injects it into CLAUDE.md or AGENTS.md.
|
|
6
|
+
*/
|
|
7
|
+
interface NuxtVersionResult {
|
|
8
|
+
version: string | null;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function getNuxtVersion(cwd: string): NuxtVersionResult;
|
|
12
|
+
interface PullResult {
|
|
13
|
+
success: boolean;
|
|
14
|
+
docsPath?: string;
|
|
15
|
+
nuxtVersion?: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function pullDocs(options: {
|
|
19
|
+
cwd: string;
|
|
20
|
+
version?: string;
|
|
21
|
+
docsDir?: string;
|
|
22
|
+
}): Promise<PullResult>;
|
|
23
|
+
export declare function collectDocFiles(dir: string): {
|
|
24
|
+
relativePath: string;
|
|
25
|
+
}[];
|
|
26
|
+
interface DocSection {
|
|
27
|
+
name: string;
|
|
28
|
+
files: {
|
|
29
|
+
relativePath: string;
|
|
30
|
+
}[];
|
|
31
|
+
subsections: DocSection[];
|
|
32
|
+
}
|
|
33
|
+
export declare function buildDocTree(files: {
|
|
34
|
+
relativePath: string;
|
|
35
|
+
}[]): DocSection[];
|
|
36
|
+
export declare function generateIndex(data: {
|
|
37
|
+
docsPath: string;
|
|
38
|
+
sections: DocSection[];
|
|
39
|
+
outputFile?: string;
|
|
40
|
+
}): string;
|
|
41
|
+
export declare function injectIndex(existingContent: string, indexContent: string): string;
|
|
42
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* nuxt-agents-md: Generate Nuxt documentation index for AI coding agents.
|
|
3
|
+
*
|
|
4
|
+
* Downloads docs from GitHub via git sparse-checkout, builds a compact
|
|
5
|
+
* index of all doc files, and injects it into CLAUDE.md or AGENTS.md.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from "node:child_process";
|
|
8
|
+
import fs from "node:fs";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import os from "node:os";
|
|
11
|
+
export function getNuxtVersion(cwd) {
|
|
12
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
13
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
14
|
+
return { version: null, error: "No package.json found in the current directory" };
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
18
|
+
const deps = pkg.dependencies || {};
|
|
19
|
+
const devDeps = pkg.devDependencies || {};
|
|
20
|
+
const nuxtVersion = deps.nuxt || devDeps.nuxt;
|
|
21
|
+
if (nuxtVersion) {
|
|
22
|
+
const clean = nuxtVersion.replace(/^[\^~>=<]+/, "");
|
|
23
|
+
return { version: clean };
|
|
24
|
+
}
|
|
25
|
+
// Check pnpm workspace
|
|
26
|
+
const pnpmWorkspace = path.join(cwd, "pnpm-workspace.yaml");
|
|
27
|
+
if (fs.existsSync(pnpmWorkspace)) {
|
|
28
|
+
const found = findNuxtInWorkspace(cwd, parsePnpmWorkspace(pnpmWorkspace));
|
|
29
|
+
if (found)
|
|
30
|
+
return { version: found };
|
|
31
|
+
}
|
|
32
|
+
// Check npm/yarn workspaces
|
|
33
|
+
if (pkg.workspaces) {
|
|
34
|
+
const patterns = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages || [];
|
|
35
|
+
const found = findNuxtInWorkspace(cwd, patterns);
|
|
36
|
+
if (found)
|
|
37
|
+
return { version: found };
|
|
38
|
+
}
|
|
39
|
+
return { version: null, error: "Nuxt is not installed in this project." };
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
return { version: null, error: `Failed to parse package.json: ${err instanceof Error ? err.message : String(err)}` };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function parsePnpmWorkspace(filePath) {
|
|
46
|
+
try {
|
|
47
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
48
|
+
const packages = [];
|
|
49
|
+
let inPackages = false;
|
|
50
|
+
for (const line of content.split("\n")) {
|
|
51
|
+
const trimmed = line.trim();
|
|
52
|
+
if (trimmed === "packages:") {
|
|
53
|
+
inPackages = true;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (inPackages) {
|
|
57
|
+
if (trimmed && !trimmed.startsWith("-") && !trimmed.startsWith("#"))
|
|
58
|
+
break;
|
|
59
|
+
const match = trimmed.match(/^-\s*['"]?([^'"]+)['"]?$/);
|
|
60
|
+
if (match)
|
|
61
|
+
packages.push(match[1]);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return packages;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function findNuxtInWorkspace(cwd, patterns) {
|
|
71
|
+
for (const pattern of patterns) {
|
|
72
|
+
const dirs = expandGlob(cwd, pattern);
|
|
73
|
+
for (const dir of dirs) {
|
|
74
|
+
const pkgPath = path.join(dir, "package.json");
|
|
75
|
+
if (!fs.existsSync(pkgPath))
|
|
76
|
+
continue;
|
|
77
|
+
try {
|
|
78
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
79
|
+
const ver = pkg.dependencies?.nuxt || pkg.devDependencies?.nuxt;
|
|
80
|
+
if (ver)
|
|
81
|
+
return ver.replace(/^[\^~>=<]+/, "");
|
|
82
|
+
}
|
|
83
|
+
catch { /* skip */ }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
function expandGlob(cwd, pattern) {
|
|
89
|
+
// Simple glob expansion for workspace patterns like "packages/*"
|
|
90
|
+
if (!pattern.includes("*"))
|
|
91
|
+
return [path.join(cwd, pattern)];
|
|
92
|
+
const base = pattern.replace(/\/?\*.*$/, "");
|
|
93
|
+
const baseDir = path.join(cwd, base);
|
|
94
|
+
if (!fs.existsSync(baseDir))
|
|
95
|
+
return [];
|
|
96
|
+
return fs.readdirSync(baseDir)
|
|
97
|
+
.map((name) => path.join(baseDir, name))
|
|
98
|
+
.filter((p) => fs.statSync(p).isDirectory());
|
|
99
|
+
}
|
|
100
|
+
// --- Major version mapping ---
|
|
101
|
+
function majorVersion(version) {
|
|
102
|
+
const match = version.match(/^(\d+)/);
|
|
103
|
+
return match ? match[1] : "4";
|
|
104
|
+
}
|
|
105
|
+
function gitBranchForVersion(version) {
|
|
106
|
+
const major = majorVersion(version);
|
|
107
|
+
// Nuxt 4.x is on main branch, Nuxt 3.x was on 3.x branch
|
|
108
|
+
if (parseInt(major) >= 4)
|
|
109
|
+
return "main";
|
|
110
|
+
return `${major}.x`;
|
|
111
|
+
}
|
|
112
|
+
export async function pullDocs(options) {
|
|
113
|
+
const { cwd, version: versionOverride, docsDir } = options;
|
|
114
|
+
let nuxtVersion;
|
|
115
|
+
if (versionOverride) {
|
|
116
|
+
nuxtVersion = versionOverride;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const result = getNuxtVersion(cwd);
|
|
120
|
+
if (!result.version)
|
|
121
|
+
return { success: false, error: result.error || "Could not detect Nuxt version" };
|
|
122
|
+
nuxtVersion = result.version;
|
|
123
|
+
}
|
|
124
|
+
const docsPath = docsDir ?? path.join(cwd, ".nuxt-docs");
|
|
125
|
+
try {
|
|
126
|
+
const branch = gitBranchForVersion(nuxtVersion);
|
|
127
|
+
await cloneDocsFolder(branch, docsPath);
|
|
128
|
+
return { success: true, docsPath, nuxtVersion };
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function cloneDocsFolder(branch, destDir) {
|
|
135
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nuxt-agents-md-"));
|
|
136
|
+
try {
|
|
137
|
+
execSync(`git clone --depth 1 --filter=blob:none --sparse --branch ${branch} https://github.com/nuxt/nuxt.git .`, { cwd: tempDir, stdio: "pipe" });
|
|
138
|
+
execSync("git sparse-checkout set docs", { cwd: tempDir, stdio: "pipe" });
|
|
139
|
+
const sourceDocsDir = path.join(tempDir, "docs");
|
|
140
|
+
if (!fs.existsSync(sourceDocsDir)) {
|
|
141
|
+
throw new Error("docs folder not found in cloned repository");
|
|
142
|
+
}
|
|
143
|
+
if (fs.existsSync(destDir))
|
|
144
|
+
fs.rmSync(destDir, { recursive: true });
|
|
145
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
146
|
+
fs.cpSync(sourceDocsDir, destDir, { recursive: true });
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
if (fs.existsSync(tempDir))
|
|
150
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// --- Index building ---
|
|
154
|
+
export function collectDocFiles(dir) {
|
|
155
|
+
return fs.readdirSync(dir, { recursive: true })
|
|
156
|
+
.filter((f) => (f.endsWith(".md") || f.endsWith(".mdx"))
|
|
157
|
+
&& !f.startsWith(".")
|
|
158
|
+
&& !f.startsWith("README"))
|
|
159
|
+
.sort()
|
|
160
|
+
.map((f) => ({ relativePath: f.replace(/\\/g, "/") }));
|
|
161
|
+
}
|
|
162
|
+
export function buildDocTree(files) {
|
|
163
|
+
const sections = new Map();
|
|
164
|
+
for (const file of files) {
|
|
165
|
+
const parts = file.relativePath.split("/");
|
|
166
|
+
if (parts.length < 2)
|
|
167
|
+
continue;
|
|
168
|
+
const topDir = parts[0];
|
|
169
|
+
if (!sections.has(topDir)) {
|
|
170
|
+
sections.set(topDir, { name: topDir, files: [], subsections: [] });
|
|
171
|
+
}
|
|
172
|
+
const section = sections.get(topDir);
|
|
173
|
+
if (parts.length === 2) {
|
|
174
|
+
section.files.push(file);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const subDir = parts[1];
|
|
178
|
+
let sub = section.subsections.find((s) => s.name === subDir);
|
|
179
|
+
if (!sub) {
|
|
180
|
+
sub = { name: subDir, files: [], subsections: [] };
|
|
181
|
+
section.subsections.push(sub);
|
|
182
|
+
}
|
|
183
|
+
if (parts.length === 3) {
|
|
184
|
+
sub.files.push(file);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
const subSubDir = parts[2];
|
|
188
|
+
let subSub = sub.subsections.find((s) => s.name === subSubDir);
|
|
189
|
+
if (!subSub) {
|
|
190
|
+
subSub = { name: subSubDir, files: [], subsections: [] };
|
|
191
|
+
sub.subsections.push(subSub);
|
|
192
|
+
}
|
|
193
|
+
subSub.files.push(file);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const sorted = Array.from(sections.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
198
|
+
for (const s of sorted) {
|
|
199
|
+
s.files.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
200
|
+
s.subsections.sort((a, b) => a.name.localeCompare(b.name));
|
|
201
|
+
for (const sub of s.subsections) {
|
|
202
|
+
sub.files.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
203
|
+
sub.subsections.sort((a, b) => a.name.localeCompare(b.name));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return sorted;
|
|
207
|
+
}
|
|
208
|
+
function collectAllFiles(sections) {
|
|
209
|
+
const files = [];
|
|
210
|
+
for (const s of sections) {
|
|
211
|
+
for (const f of s.files)
|
|
212
|
+
files.push(f.relativePath);
|
|
213
|
+
files.push(...collectAllFiles(s.subsections));
|
|
214
|
+
}
|
|
215
|
+
return files;
|
|
216
|
+
}
|
|
217
|
+
function groupByDirectory(files) {
|
|
218
|
+
const grouped = new Map();
|
|
219
|
+
for (const filePath of files) {
|
|
220
|
+
const lastSlash = filePath.lastIndexOf("/");
|
|
221
|
+
const dir = lastSlash === -1 ? "." : filePath.slice(0, lastSlash);
|
|
222
|
+
const fileName = lastSlash === -1 ? filePath : filePath.slice(lastSlash + 1);
|
|
223
|
+
const existing = grouped.get(dir);
|
|
224
|
+
if (existing)
|
|
225
|
+
existing.push(fileName);
|
|
226
|
+
else
|
|
227
|
+
grouped.set(dir, [fileName]);
|
|
228
|
+
}
|
|
229
|
+
return grouped;
|
|
230
|
+
}
|
|
231
|
+
export function generateIndex(data) {
|
|
232
|
+
const { docsPath, sections, outputFile } = data;
|
|
233
|
+
const parts = [];
|
|
234
|
+
parts.push("[Nuxt Docs Index]");
|
|
235
|
+
parts.push(`root: ${docsPath}`);
|
|
236
|
+
parts.push("STOP. What you remember about Nuxt is WRONG for this project. Always search docs and read before any task.");
|
|
237
|
+
const targetFile = outputFile || "CLAUDE.md";
|
|
238
|
+
parts.push(`If docs missing, run: npx nuxt-agents-md --output ${targetFile}`);
|
|
239
|
+
const allFiles = collectAllFiles(sections);
|
|
240
|
+
const grouped = groupByDirectory(allFiles);
|
|
241
|
+
for (const [dir, files] of grouped) {
|
|
242
|
+
parts.push(`${dir}:{${files.join(",")}}`);
|
|
243
|
+
}
|
|
244
|
+
return parts.join("|");
|
|
245
|
+
}
|
|
246
|
+
// --- Injection ---
|
|
247
|
+
const START_MARKER = "<!-- NUXT-AGENTS-MD-START -->";
|
|
248
|
+
const END_MARKER = "<!-- NUXT-AGENTS-MD-END -->";
|
|
249
|
+
export function injectIndex(existingContent, indexContent) {
|
|
250
|
+
const wrapped = `${START_MARKER}\n${indexContent}\n${END_MARKER}`;
|
|
251
|
+
if (existingContent.includes(START_MARKER)) {
|
|
252
|
+
const startIdx = existingContent.indexOf(START_MARKER);
|
|
253
|
+
const endIdx = existingContent.indexOf(END_MARKER) + END_MARKER.length;
|
|
254
|
+
return existingContent.slice(0, startIdx) + wrapped + existingContent.slice(endIdx);
|
|
255
|
+
}
|
|
256
|
+
const separator = existingContent.endsWith("\n") ? "\n" : "\n\n";
|
|
257
|
+
return existingContent + separator + wrapped + "\n";
|
|
258
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nuxt-agents-md",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Generate Nuxt documentation index for AI coding agents (CLAUDE.md / AGENTS.md)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"nuxt-agents-md": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsx src/cli.ts"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"nuxt",
|
|
20
|
+
"agents",
|
|
21
|
+
"claude",
|
|
22
|
+
"ai",
|
|
23
|
+
"coding-agents",
|
|
24
|
+
"documentation"
|
|
25
|
+
],
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"tsx": "^4.21.0",
|
|
29
|
+
"typescript": "^5.9.3"
|
|
30
|
+
}
|
|
31
|
+
}
|