ai-contextify 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.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +237 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +93 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/exporters/chunks.d.ts +7 -0
  8. package/dist/exporters/chunks.d.ts.map +1 -0
  9. package/dist/exporters/chunks.js +18 -0
  10. package/dist/exporters/chunks.js.map +1 -0
  11. package/dist/exporters/markdown.d.ts +9 -0
  12. package/dist/exporters/markdown.d.ts.map +1 -0
  13. package/dist/exporters/markdown.js +62 -0
  14. package/dist/exporters/markdown.js.map +1 -0
  15. package/dist/exporters/metadata.d.ts +3 -0
  16. package/dist/exporters/metadata.d.ts.map +1 -0
  17. package/dist/exporters/metadata.js +7 -0
  18. package/dist/exporters/metadata.js.map +1 -0
  19. package/dist/exporters/xml.d.ts +12 -0
  20. package/dist/exporters/xml.d.ts.map +1 -0
  21. package/dist/exporters/xml.js +35 -0
  22. package/dist/exporters/xml.js.map +1 -0
  23. package/dist/index.d.ts +4 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +128 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/parsers/code.d.ts +2 -0
  28. package/dist/parsers/code.d.ts.map +1 -0
  29. package/dist/parsers/code.js +6 -0
  30. package/dist/parsers/code.js.map +1 -0
  31. package/dist/parsers/docx.d.ts +2 -0
  32. package/dist/parsers/docx.d.ts.map +1 -0
  33. package/dist/parsers/docx.js +16 -0
  34. package/dist/parsers/docx.js.map +1 -0
  35. package/dist/parsers/index.d.ts +8 -0
  36. package/dist/parsers/index.d.ts.map +1 -0
  37. package/dist/parsers/index.js +56 -0
  38. package/dist/parsers/index.js.map +1 -0
  39. package/dist/parsers/json.d.ts +2 -0
  40. package/dist/parsers/json.d.ts.map +1 -0
  41. package/dist/parsers/json.js +12 -0
  42. package/dist/parsers/json.js.map +1 -0
  43. package/dist/parsers/markdown.d.ts +2 -0
  44. package/dist/parsers/markdown.d.ts.map +1 -0
  45. package/dist/parsers/markdown.js +11 -0
  46. package/dist/parsers/markdown.js.map +1 -0
  47. package/dist/parsers/pdf.d.ts +2 -0
  48. package/dist/parsers/pdf.d.ts.map +1 -0
  49. package/dist/parsers/pdf.js +17 -0
  50. package/dist/parsers/pdf.js.map +1 -0
  51. package/dist/parsers/text.d.ts +2 -0
  52. package/dist/parsers/text.d.ts.map +1 -0
  53. package/dist/parsers/text.js +6 -0
  54. package/dist/parsers/text.js.map +1 -0
  55. package/dist/scanner/index.d.ts +15 -0
  56. package/dist/scanner/index.d.ts.map +1 -0
  57. package/dist/scanner/index.js +66 -0
  58. package/dist/scanner/index.js.map +1 -0
  59. package/dist/types.d.ts +50 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +2 -0
  62. package/dist/types.js.map +1 -0
  63. package/dist/utils/chunking.d.ts +11 -0
  64. package/dist/utils/chunking.d.ts.map +1 -0
  65. package/dist/utils/chunking.js +62 -0
  66. package/dist/utils/chunking.js.map +1 -0
  67. package/dist/utils/language.d.ts +3 -0
  68. package/dist/utils/language.d.ts.map +1 -0
  69. package/dist/utils/language.js +72 -0
  70. package/dist/utils/language.js.map +1 -0
  71. package/dist/utils/logger.d.ts +9 -0
  72. package/dist/utils/logger.d.ts.map +1 -0
  73. package/dist/utils/logger.js +10 -0
  74. package/dist/utils/logger.js.map +1 -0
  75. package/dist/utils/tokens.d.ts +9 -0
  76. package/dist/utils/tokens.d.ts.map +1 -0
  77. package/dist/utils/tokens.js +22 -0
  78. package/dist/utils/tokens.js.map +1 -0
  79. package/package.json +62 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ai-contextify contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,237 @@
1
+ # ai-contextify
2
+
3
+ > Convierte archivos y proyectos completos en contexto optimizado para LLMs como **Claude**, **ChatGPT** y **Gemini**.
4
+
5
+ `ai-contextify` es una CLI moderna de Node.js que escanea una carpeta, parsea cada archivo soportado (PDF, DOCX, Markdown, TXT, JSON, código fuente…), normaliza todo a Markdown limpio y emite un único bundle listo para pegar en cualquier prompt de modelo de lenguaje — junto con un `metadata.json` que describe cada archivo, su tamaño y una estimación de tokens.
6
+
7
+ ```bash
8
+ npx ai-contextify ./docs
9
+ ```
10
+
11
+ ```
12
+ context-output/
13
+ ├── combined.md # un gran documento markdown listo para prompts
14
+ └── metadata.json # tipos, tamaños, tokens estimados y errores por archivo
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Características
20
+
21
+ - **Escaneo recursivo** con exclusiones sensatas por defecto (omite `node_modules`, `dist`, `build`, `.git`, lockfiles).
22
+ - **Parsers multi-formato**
23
+ - PDF (`pdf-parse`)
24
+ - DOCX (`mammoth` → Markdown)
25
+ - Markdown / MDX (normalizado con `remark` + GFM)
26
+ - Texto plano, logs, RST
27
+ - JSON / JSONC (formateado)
28
+ - Código fuente en 40+ lenguajes (con fenced code blocks correctos)
29
+ - **Estimación de tokens** integrada — conoce el presupuesto antes de pegar.
30
+ - **Chunking opcional** (`--chunk 6000`) para ventanas de contexto pequeñas.
31
+ - **Export XML estilo Claude opcional** (`--xml`) usando tags `<documents>` / `<document_content>`.
32
+ - **UX bonita en terminal** con spinners de `ora` y colores de `chalk`.
33
+ - **TypeScript estricto**, ESM, multiplataforma (macOS, Linux, Windows), Node ≥ 18.
34
+ - Diseñado para ser **extensible** — agrega un parser nuevo soltando un archivo en `src/parsers/` y registrándolo en `src/parsers/index.ts`.
35
+
36
+ ---
37
+
38
+ ## Instalación
39
+
40
+ Úsalo directamente sin instalar:
41
+
42
+ ```bash
43
+ npx ai-contextify ./docs
44
+ ```
45
+
46
+ O instálalo globalmente:
47
+
48
+ ```bash
49
+ npm install -g ai-contextify
50
+ ai-contextify ./docs
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Uso
56
+
57
+ ```
58
+ ai-contextify <input> [opciones]
59
+ ```
60
+
61
+ | Opción | Descripción | Por defecto |
62
+ | ----------------------- | ------------------------------------------------------------------------------------ | ------------------ |
63
+ | `-o, --output <dir>` | Directorio de salida | `context-output` |
64
+ | `-i, --include <globs…>`| Patrones glob a incluir | todo |
65
+ | `-e, --exclude <globs…>`| Patrones glob adicionales a excluir (los defaults siempre se aplican) | — |
66
+ | `--max-size <bytes>` | Omite archivos más grandes que esta cantidad de bytes | `10485760` (10 MB) |
67
+ | `--chunk <tokens>` | Emite también `chunks/chunk-N.md` de aproximadamente esta cantidad de tokens | desactivado |
68
+ | `--xml` | Emite también `context.xml` en el formato `<documents>` de Claude | desactivado |
69
+ | `--title <título>` | Título usado en `combined.md` | derivado del input |
70
+ | `--follow-symlinks` | Sigue enlaces simbólicos al escanear | `false` |
71
+ | `-V, --version` | Muestra la versión | |
72
+ | `-h, --help` | Muestra la ayuda | |
73
+
74
+ ### Ejemplos
75
+
76
+ Empaqueta una carpeta de docs:
77
+
78
+ ```bash
79
+ ai-contextify ./docs
80
+ ```
81
+
82
+ Salida personalizada, descartando tests y la carpeta de build:
83
+
84
+ ```bash
85
+ ai-contextify ./src -o ./context -e "**/*.test.ts" "**/__snapshots__/**"
86
+ ```
87
+
88
+ Divide en chunks de ~6k tokens para modelos pequeños y además emite XML de Claude:
89
+
90
+ ```bash
91
+ ai-contextify ./project --chunk 6000 --xml
92
+ ```
93
+
94
+ Un solo archivo:
95
+
96
+ ```bash
97
+ ai-contextify ./paper.pdf
98
+ ```
99
+
100
+ ---
101
+
102
+ ## API programática
103
+
104
+ ```ts
105
+ import { build } from "ai-contextify";
106
+
107
+ const summary = await build({
108
+ input: "./docs",
109
+ output: "./context-output",
110
+ chunkSize: 6000,
111
+ emitXml: true,
112
+ });
113
+
114
+ console.log(`Se escribieron ${summary.fileCount} archivos, ~${summary.totalTokens} tokens`);
115
+ ```
116
+
117
+ El tipo exportado `BuildSummary` te dice qué se escribió, dónde, y cuántos tokens estás a punto de gastar.
118
+
119
+ ---
120
+
121
+ ## Salida
122
+
123
+ ### `combined.md`
124
+
125
+ Un único documento Markdown que:
126
+
127
+ 1. Comienza con un encabezado (título, origen, número de archivos, tokens totales).
128
+ 2. Lista una tabla de contenidos clickeable.
129
+ 3. Renderiza cada archivo como su propia sección, con bloques de código usando el tag de lenguaje correcto y PDFs/DOCX renderizados como texto plano.
130
+
131
+ ### `metadata.json`
132
+
133
+ ```json
134
+ {
135
+ "inputDir": "/ruta/abs/a/docs",
136
+ "outputDir": "/ruta/abs/a/context-output",
137
+ "generatedAt": "2026-05-24T12:00:00.000Z",
138
+ "fileCount": 12,
139
+ "totalBytes": 84211,
140
+ "totalTokens": 21034,
141
+ "durationMs": 482,
142
+ "files": [
143
+ { "path": "README.md", "kind": "markdown", "bytes": 4321, "tokens": 1080 }
144
+ ],
145
+ "artifacts": {
146
+ "combined": "/ruta/abs/a/context-output/combined.md",
147
+ "metadata": "/ruta/abs/a/context-output/metadata.json"
148
+ }
149
+ }
150
+ ```
151
+
152
+ ### `context.xml` (con `--xml`)
153
+
154
+ ```xml
155
+ <documents>
156
+ <document index="1">
157
+ <source>README.md</source>
158
+ <kind>markdown</kind>
159
+ <tokens>1080</tokens>
160
+ <document_content>
161
+
162
+ </document_content>
163
+ </document>
164
+ </documents>
165
+ ```
166
+
167
+ ### `chunks/` (con `--chunk N`)
168
+
169
+ `chunk-01.md`, `chunk-02.md`, … cada uno ≲ N tokens. Los cortes ocurren en límites de párrafo cuando es posible.
170
+
171
+ ---
172
+
173
+ ## Desarrollo
174
+
175
+ ```bash
176
+ pnpm install
177
+ pnpm build
178
+ npm link
179
+ ai-contextify ./example
180
+ ```
181
+
182
+ Scripts:
183
+
184
+ | Script | Qué hace |
185
+ | -------------- | ----------------------------------------- |
186
+ | `pnpm dev` | Ejecuta la CLI desde el código con `tsx` |
187
+ | `pnpm build` | Compila TypeScript a `dist/` |
188
+ | `pnpm start` | Ejecuta la CLI compilada |
189
+ | `pnpm clean` | Elimina `dist/` |
190
+
191
+ Estructura del proyecto:
192
+
193
+ ```
194
+ src/
195
+ ├── cli.ts # Punto de entrada de Commander
196
+ ├── index.ts # API programática build()
197
+ ├── types.ts
198
+ ├── scanner/ # Escaneo con fast-glob y exclusiones sensatas
199
+ ├── parsers/
200
+ │ ├── pdf.ts
201
+ │ ├── docx.ts
202
+ │ ├── markdown.ts
203
+ │ ├── text.ts
204
+ │ ├── json.ts
205
+ │ ├── code.ts
206
+ │ └── index.ts # Detección de tipo + dispatch
207
+ ├── exporters/
208
+ │ ├── markdown.ts # combined.md
209
+ │ ├── metadata.ts # metadata.json
210
+ │ ├── xml.ts # Formato <documents> de Claude
211
+ │ └── chunks.ts # chunks/chunk-N.md
212
+ └── utils/
213
+ ├── logger.ts
214
+ ├── tokens.ts # Estimador de tokens barato y sin dependencias
215
+ ├── chunking.ts
216
+ └── language.ts # extensión → tag de lenguaje
217
+ ```
218
+
219
+ ### Agregar un parser
220
+
221
+ 1. Crea `src/parsers/miformato.ts` exportando `async function parseMiformato(path: string): Promise<string>`.
222
+ 2. Agrega un nuevo `FileKind` en `src/types.ts`.
223
+ 3. Registra la extensión en `detectKind()` y el dispatch en `parseFile()` dentro de `src/parsers/index.ts`.
224
+
225
+ Eso es todo — el scanner, los exporters y el pipeline de metadata lo recogen automáticamente.
226
+
227
+ ---
228
+
229
+ ## Contribuir
230
+
231
+ ¡Los PRs son bienvenidos! Si quieres agregar un parser nuevo, soportar otro formato de export, o mejorar el estimador de tokens, abre un issue para discutirlo primero.
232
+
233
+ ---
234
+
235
+ ## Licencia
236
+
237
+ [MIT](./LICENSE)
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import chalk from "chalk";
5
+ import { Command } from "commander";
6
+ import { build } from "./index.js";
7
+ import { logger } from "./utils/logger.js";
8
+ import { formatTokenCount } from "./utils/tokens.js";
9
+ const program = new Command();
10
+ program
11
+ .name("ai-contextify")
12
+ .description("Convert files and entire projects into optimized context for LLMs (Claude, ChatGPT, Gemini).")
13
+ .version("0.1.0")
14
+ .argument("<input>", "File or directory to convert into LLM context")
15
+ .option("-o, --output <dir>", "Output directory", "context-output")
16
+ .option("-i, --include <patterns...>", "Glob patterns to include (default: everything)")
17
+ .option("-e, --exclude <patterns...>", "Extra glob patterns to exclude (node_modules/dist/build/.git are always excluded)")
18
+ .option("--max-size <bytes>", "Skip files larger than this many bytes", String(10 * 1024 * 1024))
19
+ .option("--chunk <tokens>", "Also emit chunk-*.md files of approximately this many tokens")
20
+ .option("--xml", "Also emit context.xml in Claude's <documents> format")
21
+ .option("--title <title>", "Title for the combined.md document")
22
+ .option("--follow-symlinks", "Follow symbolic links while scanning", false)
23
+ .action(async (input, opts) => {
24
+ const absoluteInput = path.resolve(input);
25
+ const absoluteOutput = path.resolve(opts.output);
26
+ logger.step(`Input: ${chalk.bold(absoluteInput)}`);
27
+ logger.step(`Output: ${chalk.bold(absoluteOutput)}`);
28
+ const maxSizeBytes = Number.parseInt(opts.maxSize, 10);
29
+ if (!Number.isFinite(maxSizeBytes) || maxSizeBytes <= 0) {
30
+ logger.error(`Invalid --max-size: ${opts.maxSize}`);
31
+ process.exit(1);
32
+ }
33
+ const chunkSize = opts.chunk ? Number.parseInt(opts.chunk, 10) : undefined;
34
+ if (opts.chunk && (!Number.isFinite(chunkSize) || (chunkSize ?? 0) <= 0)) {
35
+ logger.error(`Invalid --chunk: ${opts.chunk}`);
36
+ process.exit(1);
37
+ }
38
+ try {
39
+ const summary = await build({
40
+ input: absoluteInput,
41
+ output: absoluteOutput,
42
+ include: opts.include,
43
+ exclude: opts.exclude,
44
+ maxFileSizeBytes: maxSizeBytes,
45
+ followSymlinks: opts.followSymlinks,
46
+ chunkSize,
47
+ emitXml: opts.xml === true,
48
+ title: opts.title,
49
+ });
50
+ console.log("");
51
+ logger.success(chalk.bold("Done!"));
52
+ logger.dim(` Files: ${summary.fileCount}`);
53
+ logger.dim(` Bytes: ${summary.totalBytes.toLocaleString()}`);
54
+ logger.dim(` Tokens: ~${formatTokenCount(summary.totalTokens)}`);
55
+ logger.dim(` Duration: ${(summary.durationMs / 1000).toFixed(2)}s`);
56
+ if (summary.artifacts.combined) {
57
+ logger.dim(` ${chalk.cyan("combined.md")} → ${summary.artifacts.combined}`);
58
+ }
59
+ if (summary.artifacts.metadata) {
60
+ logger.dim(` ${chalk.cyan("metadata.json")} → ${summary.artifacts.metadata}`);
61
+ }
62
+ if (summary.artifacts.xml) {
63
+ logger.dim(` ${chalk.cyan("context.xml")} → ${summary.artifacts.xml}`);
64
+ }
65
+ if (summary.artifacts.chunks?.length) {
66
+ logger.dim(` ${chalk.cyan("chunks/")} → ${summary.artifacts.chunks.length} files`);
67
+ }
68
+ const errored = summary.files.filter((f) => f.parseError);
69
+ if (errored.length > 0) {
70
+ console.log("");
71
+ logger.warn(`${errored.length} file(s) failed to parse:`);
72
+ for (const f of errored.slice(0, 10)) {
73
+ logger.dim(` - ${f.path}: ${f.parseError}`);
74
+ }
75
+ if (errored.length > 10) {
76
+ logger.dim(` …and ${errored.length - 10} more (see metadata.json)`);
77
+ }
78
+ }
79
+ }
80
+ catch (err) {
81
+ const message = err instanceof Error ? err.message : String(err);
82
+ logger.error(message);
83
+ if (process.env.DEBUG)
84
+ console.error(err);
85
+ process.exit(1);
86
+ }
87
+ });
88
+ program.parseAsync(process.argv).catch((err) => {
89
+ const message = err instanceof Error ? err.message : String(err);
90
+ logger.error(message);
91
+ process.exit(1);
92
+ });
93
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface ChunkExportOptions {
2
+ outputDir: string;
3
+ combinedMarkdown: string;
4
+ chunkTokens: number;
5
+ }
6
+ export declare function exportChunks(options: ChunkExportOptions): Promise<string[]>;
7
+ //# sourceMappingURL=chunks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunks.d.ts","sourceRoot":"","sources":["../../src/exporters/chunks.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBnB"}
@@ -0,0 +1,18 @@
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ import { chunkText } from "../utils/chunking.js";
4
+ export async function exportChunks(options) {
5
+ const chunks = chunkText(options.combinedMarkdown, options.chunkTokens);
6
+ await fs.ensureDir(options.outputDir);
7
+ const written = [];
8
+ const pad = String(chunks.length).length;
9
+ for (const chunk of chunks) {
10
+ const filename = `chunk-${String(chunk.index + 1).padStart(pad, "0")}.md`;
11
+ const fullPath = path.join(options.outputDir, filename);
12
+ const header = `<!-- chunk ${chunk.index + 1}/${chunks.length} · ~${chunk.tokens} tokens -->\n\n`;
13
+ await fs.writeFile(fullPath, header + chunk.content + "\n", "utf8");
14
+ written.push(fullPath);
15
+ }
16
+ return written;
17
+ }
18
+ //# sourceMappingURL=chunks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunks.js","sourceRoot":"","sources":["../../src/exporters/chunks.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAQjD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAA2B;IAE3B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IACxE,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAEzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,SAAS,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,cAAc,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,iBAAiB,CAAC;QAClG,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ParsedFile } from "../types.js";
2
+ export interface MarkdownExportOptions {
3
+ outputPath: string;
4
+ title: string;
5
+ inputDir: string;
6
+ generatedAt: string;
7
+ }
8
+ export declare function exportCombinedMarkdown(files: ParsedFile[], options: MarkdownExportOptions): Promise<void>;
9
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/exporters/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
@@ -0,0 +1,62 @@
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ import { detectLanguage } from "../utils/language.js";
4
+ import { formatTokenCount } from "../utils/tokens.js";
5
+ export async function exportCombinedMarkdown(files, options) {
6
+ const lines = [];
7
+ lines.push(`# ${options.title}`);
8
+ lines.push("");
9
+ lines.push(`> Generated by **ai-contextify** on ${options.generatedAt}.`, `> Source: \`${options.inputDir}\``, `> Files: ${files.length} · Total tokens (est.): ${formatTokenCount(files.reduce((acc, f) => acc + f.estimatedTokens, 0))}`);
10
+ lines.push("");
11
+ lines.push("## Table of contents");
12
+ lines.push("");
13
+ for (const file of files) {
14
+ const anchor = anchorFor(file.relativePath);
15
+ lines.push(`- [\`${file.relativePath}\`](#${anchor}) — ${file.kind} · ${formatTokenCount(file.estimatedTokens)} tok`);
16
+ }
17
+ lines.push("");
18
+ lines.push("---");
19
+ lines.push("");
20
+ for (const file of files) {
21
+ lines.push(`## \`${file.relativePath}\``);
22
+ lines.push("");
23
+ lines.push(`- **Kind:** ${file.kind}`, `- **Size:** ${file.bytes} bytes`, `- **Estimated tokens:** ${file.estimatedTokens}`);
24
+ if (file.parseError) {
25
+ lines.push(`- **Parse error:** ${file.parseError}`);
26
+ }
27
+ lines.push("");
28
+ lines.push(renderBody(file));
29
+ lines.push("");
30
+ lines.push("---");
31
+ lines.push("");
32
+ }
33
+ await fs.ensureDir(path.dirname(options.outputPath));
34
+ await fs.writeFile(options.outputPath, lines.join("\n"), "utf8");
35
+ }
36
+ function renderBody(file) {
37
+ if (!file.content.trim())
38
+ return "_(empty)_";
39
+ if (file.kind === "markdown")
40
+ return file.content.trim();
41
+ if (file.kind === "code" || file.kind === "json") {
42
+ const lang = file.language ?? detectLanguage(file.extension, file.relativePath);
43
+ return wrapFence(file.content, lang);
44
+ }
45
+ // pdf / docx / text / unknown → render as plain text block.
46
+ return file.content.trim();
47
+ }
48
+ function wrapFence(content, language) {
49
+ // Pick a fence longer than any run of backticks in the content.
50
+ const longestBacktickRun = (content.match(/`+/g) ?? [])
51
+ .reduce((max, run) => Math.max(max, run.length), 0);
52
+ const fenceLength = Math.max(3, longestBacktickRun + 1);
53
+ const fence = "`".repeat(fenceLength);
54
+ return `${fence}${language}\n${content.replace(/\s+$/, "")}\n${fence}`;
55
+ }
56
+ function anchorFor(relPath) {
57
+ return relPath
58
+ .toLowerCase()
59
+ .replace(/[^a-z0-9]+/g, "-")
60
+ .replace(/(^-|-$)/g, "");
61
+ }
62
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/exporters/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { BuildSummary } from "../types.js";
2
+ export declare function exportMetadata(outputPath: string, summary: BuildSummary): Promise<void>;
3
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/exporters/metadata.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -0,0 +1,7 @@
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ export async function exportMetadata(outputPath, summary) {
4
+ await fs.ensureDir(path.dirname(outputPath));
5
+ await fs.writeFile(outputPath, `${JSON.stringify(summary, null, 2)}\n`, "utf8");
6
+ }
7
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/exporters/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAG1B,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAAkB,EAClB,OAAqB;IAErB,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7C,MAAM,EAAE,CAAC,SAAS,CAChB,UAAU,EACV,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EACvC,MAAM,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ParsedFile } from "../types.js";
2
+ export interface XmlExportOptions {
3
+ outputPath: string;
4
+ inputDir: string;
5
+ generatedAt: string;
6
+ }
7
+ /**
8
+ * Emit a Claude-style `<documents>` XML bundle. This format is the one
9
+ * Anthropic recommends for stuffing multiple documents into a single prompt.
10
+ */
11
+ export declare function exportClaudeXml(files: ParsedFile[], options: XmlExportOptions): Promise<void>;
12
+ //# sourceMappingURL=xml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../../src/exporters/xml.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,35 @@
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ /**
4
+ * Emit a Claude-style `<documents>` XML bundle. This format is the one
5
+ * Anthropic recommends for stuffing multiple documents into a single prompt.
6
+ */
7
+ export async function exportClaudeXml(files, options) {
8
+ const lines = [];
9
+ lines.push(`<!-- ai-contextify · ${options.generatedAt} -->`);
10
+ lines.push(`<!-- source: ${escapeAttr(options.inputDir)} -->`);
11
+ lines.push("<documents>");
12
+ files.forEach((file, index) => {
13
+ lines.push(` <document index="${index + 1}">`);
14
+ lines.push(` <source>${escapeText(file.relativePath)}</source>`);
15
+ lines.push(` <kind>${file.kind}</kind>`);
16
+ lines.push(` <tokens>${file.estimatedTokens}</tokens>`);
17
+ lines.push(" <document_content>");
18
+ lines.push(escapeText(file.content));
19
+ lines.push(" </document_content>");
20
+ lines.push(" </document>");
21
+ });
22
+ lines.push("</documents>");
23
+ await fs.ensureDir(path.dirname(options.outputPath));
24
+ await fs.writeFile(options.outputPath, `${lines.join("\n")}\n`, "utf8");
25
+ }
26
+ function escapeText(value) {
27
+ return value
28
+ .replace(/&/g, "&amp;")
29
+ .replace(/</g, "&lt;")
30
+ .replace(/>/g, "&gt;");
31
+ }
32
+ function escapeAttr(value) {
33
+ return escapeText(value).replace(/"/g, "&quot;");
34
+ }
35
+ //# sourceMappingURL=xml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml.js","sourceRoot":"","sources":["../../src/exporters/xml.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAS1B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAmB,EACnB,OAAyB;IAEzB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,WAAW,MAAM,CAAC,CAAC;IAC9D,KAAK,CAAC,IAAI,CAAC,gBAAgB,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/D,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE1B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,KAAK,CAAC,IAAI,CAAC,sBAAsB,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,eAAe,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,eAAe,WAAW,CAAC,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAE3B,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { BuildOptions, BuildSummary } from "./types.js";
2
+ export declare function build(options: BuildOptions): Promise<BuildSummary>;
3
+ export type { BuildOptions, BuildSummary, ParsedFile, FileKind } from "./types.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;AAWzE,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAkIxE;AAED,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}