docviz-builder 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 (233) hide show
  1. package/AGENTS.md +371 -0
  2. package/LICENSE +21 -0
  3. package/README.md +837 -0
  4. package/bin/docviz-mcp.mjs +10 -0
  5. package/bin/docviz.mjs +11 -0
  6. package/dist/build/builder.d.ts +62 -0
  7. package/dist/build/builder.d.ts.map +1 -0
  8. package/dist/build/builder.js +337 -0
  9. package/dist/build/builder.js.map +1 -0
  10. package/dist/build/diff.d.ts +64 -0
  11. package/dist/build/diff.d.ts.map +1 -0
  12. package/dist/build/diff.js +156 -0
  13. package/dist/build/diff.js.map +1 -0
  14. package/dist/build/doctor.d.ts +39 -0
  15. package/dist/build/doctor.d.ts.map +1 -0
  16. package/dist/build/doctor.js +190 -0
  17. package/dist/build/doctor.js.map +1 -0
  18. package/dist/build/init.d.ts +28 -0
  19. package/dist/build/init.d.ts.map +1 -0
  20. package/dist/build/init.js +274 -0
  21. package/dist/build/init.js.map +1 -0
  22. package/dist/build/preview.d.ts +13 -0
  23. package/dist/build/preview.d.ts.map +1 -0
  24. package/dist/build/preview.js +277 -0
  25. package/dist/build/preview.js.map +1 -0
  26. package/dist/build/skill.d.ts +41 -0
  27. package/dist/build/skill.d.ts.map +1 -0
  28. package/dist/build/skill.js +63 -0
  29. package/dist/build/skill.js.map +1 -0
  30. package/dist/build/verify.d.ts +26 -0
  31. package/dist/build/verify.d.ts.map +1 -0
  32. package/dist/build/verify.js +99 -0
  33. package/dist/build/verify.js.map +1 -0
  34. package/dist/cli.d.ts +20 -0
  35. package/dist/cli.d.ts.map +1 -0
  36. package/dist/cli.js +427 -0
  37. package/dist/cli.js.map +1 -0
  38. package/dist/config/load.d.ts +32 -0
  39. package/dist/config/load.d.ts.map +1 -0
  40. package/dist/config/load.js +279 -0
  41. package/dist/config/load.js.map +1 -0
  42. package/dist/config/types.d.ts +89 -0
  43. package/dist/config/types.d.ts.map +1 -0
  44. package/dist/config/types.js +5 -0
  45. package/dist/config/types.js.map +1 -0
  46. package/dist/core/cache.d.ts +32 -0
  47. package/dist/core/cache.d.ts.map +1 -0
  48. package/dist/core/cache.js +69 -0
  49. package/dist/core/cache.js.map +1 -0
  50. package/dist/core/errors.d.ts +115 -0
  51. package/dist/core/errors.d.ts.map +1 -0
  52. package/dist/core/errors.js +164 -0
  53. package/dist/core/errors.js.map +1 -0
  54. package/dist/core/hash.d.ts +57 -0
  55. package/dist/core/hash.d.ts.map +1 -0
  56. package/dist/core/hash.js +0 -0
  57. package/dist/core/hash.js.map +1 -0
  58. package/dist/core/package-version.d.ts +9 -0
  59. package/dist/core/package-version.d.ts.map +1 -0
  60. package/dist/core/package-version.js +44 -0
  61. package/dist/core/package-version.js.map +1 -0
  62. package/dist/core/paths.d.ts +46 -0
  63. package/dist/core/paths.d.ts.map +1 -0
  64. package/dist/core/paths.js +105 -0
  65. package/dist/core/paths.js.map +1 -0
  66. package/dist/core/registry.d.ts +24 -0
  67. package/dist/core/registry.d.ts.map +1 -0
  68. package/dist/core/registry.js +72 -0
  69. package/dist/core/registry.js.map +1 -0
  70. package/dist/core/types.d.ts +78 -0
  71. package/dist/core/types.d.ts.map +1 -0
  72. package/dist/core/types.js +11 -0
  73. package/dist/core/types.js.map +1 -0
  74. package/dist/dsl/architecture.d.ts +15 -0
  75. package/dist/dsl/architecture.d.ts.map +1 -0
  76. package/dist/dsl/architecture.js +242 -0
  77. package/dist/dsl/architecture.js.map +1 -0
  78. package/dist/dsl/catalog.d.ts +62 -0
  79. package/dist/dsl/catalog.d.ts.map +1 -0
  80. package/dist/dsl/catalog.en.d.ts +18 -0
  81. package/dist/dsl/catalog.en.d.ts.map +1 -0
  82. package/dist/dsl/catalog.en.js +299 -0
  83. package/dist/dsl/catalog.en.js.map +1 -0
  84. package/dist/dsl/catalog.js +1082 -0
  85. package/dist/dsl/catalog.js.map +1 -0
  86. package/dist/dsl/chart.d.ts +14 -0
  87. package/dist/dsl/chart.d.ts.map +1 -0
  88. package/dist/dsl/chart.js +435 -0
  89. package/dist/dsl/chart.js.map +1 -0
  90. package/dist/dsl/compile.d.ts +31 -0
  91. package/dist/dsl/compile.d.ts.map +1 -0
  92. package/dist/dsl/compile.js +120 -0
  93. package/dist/dsl/compile.js.map +1 -0
  94. package/dist/dsl/diagram-bpmn.d.ts +13 -0
  95. package/dist/dsl/diagram-bpmn.d.ts.map +1 -0
  96. package/dist/dsl/diagram-bpmn.js +215 -0
  97. package/dist/dsl/diagram-bpmn.js.map +1 -0
  98. package/dist/dsl/diagram-product.d.ts +15 -0
  99. package/dist/dsl/diagram-product.d.ts.map +1 -0
  100. package/dist/dsl/diagram-product.js +291 -0
  101. package/dist/dsl/diagram-product.js.map +1 -0
  102. package/dist/dsl/diagram-technical.d.ts +28 -0
  103. package/dist/dsl/diagram-technical.d.ts.map +1 -0
  104. package/dist/dsl/diagram-technical.js +365 -0
  105. package/dist/dsl/diagram-technical.js.map +1 -0
  106. package/dist/dsl/diagram.d.ts +22 -0
  107. package/dist/dsl/diagram.d.ts.map +1 -0
  108. package/dist/dsl/diagram.js +542 -0
  109. package/dist/dsl/diagram.js.map +1 -0
  110. package/dist/dsl/fallbacks-d2.d.ts +27 -0
  111. package/dist/dsl/fallbacks-d2.d.ts.map +1 -0
  112. package/dist/dsl/fallbacks-d2.js +265 -0
  113. package/dist/dsl/fallbacks-d2.js.map +1 -0
  114. package/dist/dsl/fallbacks.d.ts +25 -0
  115. package/dist/dsl/fallbacks.d.ts.map +1 -0
  116. package/dist/dsl/fallbacks.js +264 -0
  117. package/dist/dsl/fallbacks.js.map +1 -0
  118. package/dist/dsl/fields.d.ts +93 -0
  119. package/dist/dsl/fields.d.ts.map +1 -0
  120. package/dist/dsl/fields.js +233 -0
  121. package/dist/dsl/fields.js.map +1 -0
  122. package/dist/dsl/index.d.ts +50 -0
  123. package/dist/dsl/index.d.ts.map +1 -0
  124. package/dist/dsl/index.js +114 -0
  125. package/dist/dsl/index.js.map +1 -0
  126. package/dist/dsl/util.d.ts +105 -0
  127. package/dist/dsl/util.d.ts.map +1 -0
  128. package/dist/dsl/util.js +261 -0
  129. package/dist/dsl/util.js.map +1 -0
  130. package/dist/index.d.ts +27 -0
  131. package/dist/index.d.ts.map +1 -0
  132. package/dist/index.js +21 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/markdown/scan.d.ts +73 -0
  135. package/dist/markdown/scan.d.ts.map +1 -0
  136. package/dist/markdown/scan.js +150 -0
  137. package/dist/markdown/scan.js.map +1 -0
  138. package/dist/markdown/transform.d.ts +28 -0
  139. package/dist/markdown/transform.d.ts.map +1 -0
  140. package/dist/markdown/transform.js +38 -0
  141. package/dist/markdown/transform.js.map +1 -0
  142. package/dist/mcp/server.d.ts +18 -0
  143. package/dist/mcp/server.d.ts.map +1 -0
  144. package/dist/mcp/server.js +118 -0
  145. package/dist/mcp/server.js.map +1 -0
  146. package/dist/mcp/tools.d.ts +118 -0
  147. package/dist/mcp/tools.d.ts.map +1 -0
  148. package/dist/mcp/tools.js +573 -0
  149. package/dist/mcp/tools.js.map +1 -0
  150. package/dist/renderers/base.d.ts +18 -0
  151. package/dist/renderers/base.d.ts.map +1 -0
  152. package/dist/renderers/base.js +59 -0
  153. package/dist/renderers/base.js.map +1 -0
  154. package/dist/renderers/bpmn.d.ts +68 -0
  155. package/dist/renderers/bpmn.d.ts.map +1 -0
  156. package/dist/renderers/bpmn.js +158 -0
  157. package/dist/renderers/bpmn.js.map +1 -0
  158. package/dist/renderers/browser.d.ts +30 -0
  159. package/dist/renderers/browser.d.ts.map +1 -0
  160. package/dist/renderers/browser.js +143 -0
  161. package/dist/renderers/browser.js.map +1 -0
  162. package/dist/renderers/color-scheme.d.ts +40 -0
  163. package/dist/renderers/color-scheme.d.ts.map +1 -0
  164. package/dist/renderers/color-scheme.js +122 -0
  165. package/dist/renderers/color-scheme.js.map +1 -0
  166. package/dist/renderers/d2.d.ts +37 -0
  167. package/dist/renderers/d2.d.ts.map +1 -0
  168. package/dist/renderers/d2.js +108 -0
  169. package/dist/renderers/d2.js.map +1 -0
  170. package/dist/renderers/graphviz.d.ts +33 -0
  171. package/dist/renderers/graphviz.d.ts.map +1 -0
  172. package/dist/renderers/graphviz.js +88 -0
  173. package/dist/renderers/graphviz.js.map +1 -0
  174. package/dist/renderers/in-page.d.ts +33 -0
  175. package/dist/renderers/in-page.d.ts.map +1 -0
  176. package/dist/renderers/in-page.js +76 -0
  177. package/dist/renderers/in-page.js.map +1 -0
  178. package/dist/renderers/index.d.ts +20 -0
  179. package/dist/renderers/index.d.ts.map +1 -0
  180. package/dist/renderers/index.js +94 -0
  181. package/dist/renderers/index.js.map +1 -0
  182. package/dist/renderers/kroki.d.ts +38 -0
  183. package/dist/renderers/kroki.d.ts.map +1 -0
  184. package/dist/renderers/kroki.js +151 -0
  185. package/dist/renderers/kroki.js.map +1 -0
  186. package/dist/renderers/likec4-svg.d.ts +82 -0
  187. package/dist/renderers/likec4-svg.d.ts.map +1 -0
  188. package/dist/renderers/likec4-svg.js +435 -0
  189. package/dist/renderers/likec4-svg.js.map +1 -0
  190. package/dist/renderers/likec4.d.ts +22 -0
  191. package/dist/renderers/likec4.d.ts.map +1 -0
  192. package/dist/renderers/likec4.js +77 -0
  193. package/dist/renderers/likec4.js.map +1 -0
  194. package/dist/renderers/mermaid.d.ts +64 -0
  195. package/dist/renderers/mermaid.d.ts.map +1 -0
  196. package/dist/renderers/mermaid.js +196 -0
  197. package/dist/renderers/mermaid.js.map +1 -0
  198. package/dist/renderers/plantuml.d.ts +56 -0
  199. package/dist/renderers/plantuml.d.ts.map +1 -0
  200. package/dist/renderers/plantuml.js +195 -0
  201. package/dist/renderers/plantuml.js.map +1 -0
  202. package/dist/renderers/svg-utils.d.ts +46 -0
  203. package/dist/renderers/svg-utils.d.ts.map +1 -0
  204. package/dist/renderers/svg-utils.js +439 -0
  205. package/dist/renderers/svg-utils.js.map +1 -0
  206. package/dist/renderers/svgbob.d.ts +26 -0
  207. package/dist/renderers/svgbob.d.ts.map +1 -0
  208. package/dist/renderers/svgbob.js +70 -0
  209. package/dist/renderers/svgbob.js.map +1 -0
  210. package/dist/renderers/vega-lite.d.ts +18 -0
  211. package/dist/renderers/vega-lite.d.ts.map +1 -0
  212. package/dist/renderers/vega-lite.js +94 -0
  213. package/dist/renderers/vega-lite.js.map +1 -0
  214. package/dist/themes/index.d.ts +17 -0
  215. package/dist/themes/index.d.ts.map +1 -0
  216. package/dist/themes/index.js +419 -0
  217. package/dist/themes/index.js.map +1 -0
  218. package/dist/themes/types.d.ts +99 -0
  219. package/dist/themes/types.d.ts.map +1 -0
  220. package/dist/themes/types.js +9 -0
  221. package/dist/themes/types.js.map +1 -0
  222. package/eval/casos.json +513 -0
  223. package/package.json +114 -0
  224. package/scripts/capture-preview.mjs +101 -0
  225. package/scripts/check-github.mjs +128 -0
  226. package/scripts/eval.d.mts +8 -0
  227. package/scripts/eval.mjs +284 -0
  228. package/scripts/fetch-plantuml.mjs +122 -0
  229. package/scripts/generate-catalog-doc.mjs +106 -0
  230. package/scripts/rasterize.mjs +68 -0
  231. package/scripts/sync-docs.mjs +158 -0
  232. package/skills/docviz/SKILL.md +111 -0
  233. package/vendor/.gitkeep +0 -0
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Genera `examples/catalogo.md` a partir del catalogo de tipos.
4
+ *
5
+ * El documento sirve para dos cosas a la vez: es la referencia visual de todo
6
+ * lo que DocViz sabe dibujar, y es la prueba manual mas completa que existe,
7
+ * porque compilarlo obliga a que cada tipo del catalogo se renderice de verdad.
8
+ *
9
+ * Se genera en lugar de escribirse a mano para que no pueda quedar desfasado:
10
+ * anadir un tipo al catalogo lo anade aqui.
11
+ */
12
+
13
+ import { writeFile } from 'node:fs/promises';
14
+ import path from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+ import { TYPE_CATALOG } from '../dist/dsl/catalog.js';
17
+
18
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
19
+ const target = path.join(root, 'examples', 'catalogo.md');
20
+
21
+ const TITULOS = {
22
+ diagram: 'Diagramas',
23
+ chart: 'Graficos',
24
+ architecture: 'Arquitectura',
25
+ };
26
+
27
+ const INTROS = {
28
+ diagram:
29
+ 'Se declaran en un bloque `diagram`. El campo `type` expresa la intencion; ' +
30
+ 'el motor lo elige DocViz.',
31
+ chart:
32
+ 'Se declaran en un bloque `chart`. Todos se dibujan con Vega-Lite y el ' +
33
+ 'resultado es un SVG estatico, sin JavaScript.',
34
+ architecture:
35
+ 'Se declaran en un bloque `architecture`. Se dibujan con LikeC4, y si no ' +
36
+ 'estuviera disponible, con C4-PlantUML.',
37
+ };
38
+
39
+ const lines = [
40
+ '---',
41
+ 'title: Catalogo de visualizaciones',
42
+ '---',
43
+ '',
44
+ '# Catalogo de visualizaciones',
45
+ '',
46
+ 'Todos los tipos que DocViz sabe dibujar, cada uno con el bloque que lo',
47
+ 'produce y el resultado ya compilado.',
48
+ '',
49
+ 'Este documento **no se escribe a mano**: lo genera `npm run catalog` a partir',
50
+ 'del catalogo de tipos, de modo que no puede quedar desfasado respecto a lo que',
51
+ 'el compilador admite de verdad.',
52
+ '',
53
+ ];
54
+
55
+ const resumen = ['| Tipo | Para que sirve | Motor |', '|---|---|---|'];
56
+ for (const spec of TYPE_CATALOG) {
57
+ resumen.push(`| \`${spec.type}\` | ${spec.purpose} | ${spec.engine} |`);
58
+ }
59
+ lines.push(...resumen, '');
60
+
61
+ for (const lang of ['diagram', 'chart', 'architecture']) {
62
+ const specs = TYPE_CATALOG.filter((s) => s.lang === lang);
63
+ if (specs.length === 0) continue;
64
+
65
+ lines.push('---', '', `## ${TITULOS[lang]}`, '', INTROS[lang], '');
66
+
67
+ for (const spec of specs) {
68
+ lines.push(`### \`${spec.type}\``, '');
69
+ lines.push(spec.purpose, '');
70
+ lines.push(`**Cuando usarlo.** ${spec.whenToUse}`, '');
71
+ lines.push(`**Cuando no.** ${spec.whenNotToUse}`, '');
72
+
73
+ const detalles = [];
74
+ if (spec.aliases !== undefined && spec.aliases.length > 0) {
75
+ detalles.push(`Alias: ${spec.aliases.map((a) => `\`${a}\``).join(', ')}.`);
76
+ }
77
+ if (spec.fallbacks !== undefined && spec.fallbacks.length > 0) {
78
+ detalles.push(`Si falta ${spec.engine}, se dibuja con ${spec.fallbacks.join(' o ')}.`);
79
+ }
80
+ if (detalles.length > 0) lines.push(detalles.join(' '), '');
81
+
82
+ // El bloque fuente se muestra dentro de una valla de cuatro tildes para que
83
+ // el propio compilador no lo tome por una visualizacion que debe dibujar.
84
+ lines.push('````md', `\`\`\`${spec.lang}`, spec.example, '```', '````', '');
85
+
86
+ // Y este es el bloque real, el que si se compila.
87
+ lines.push(`\`\`\`${spec.lang} title="${spec.type}"`, spec.example, '```', '');
88
+ }
89
+ }
90
+
91
+ lines.push(
92
+ '---',
93
+ '',
94
+ '## Como se elige',
95
+ '',
96
+ 'Si dudas entre varios tipos, describe en una frase que quieres explicar y',
97
+ 'consulta la herramienta MCP `docviz_suggest`, o ejecuta `docviz types` para',
98
+ 'ver el catalogo con su proposito y su ejemplo.',
99
+ '',
100
+ 'Y antes de dibujar, comprueba que el diagrama aporta algo: para informacion',
101
+ 'sencilla, una tabla o un parrafo comunican mejor.',
102
+ '',
103
+ );
104
+
105
+ await writeFile(target, lines.join('\n'), 'utf8');
106
+ process.stdout.write(`escrito ${path.relative(root, target)} con ${TYPE_CATALOG.length} tipos\n`);
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Rasteriza los SVG generados a PNG para revisarlos visualmente.
4
+ *
5
+ * Se usa en la validacion manual y para producir las evidencias de
6
+ * `artifacts/test-results/screenshots/`. No forma parte del pipeline de build.
7
+ *
8
+ * node scripts/rasterize.mjs <dirConSvg> <dirDestino> [--scale 2]
9
+ */
10
+
11
+ import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
12
+ import path from 'node:path';
13
+ import process from 'node:process';
14
+ import puppeteer from 'puppeteer-core';
15
+ import { findBrowser, browserNotFoundHelp } from '../dist/renderers/browser.js';
16
+
17
+ const [, , sourceDir, targetDir, ...rest] = process.argv;
18
+ if (sourceDir === undefined || targetDir === undefined) {
19
+ process.stderr.write('uso: node scripts/rasterize.mjs <dirConSvg> <dirDestino> [--scale N]\n');
20
+ process.exit(2);
21
+ }
22
+ const scaleIndex = rest.indexOf('--scale');
23
+ const scale = scaleIndex >= 0 ? Number(rest[scaleIndex + 1]) : 2;
24
+ // `--scheme dark` emula un visor en modo oscuro para comprobar la variante dual.
25
+ const schemeIndex = rest.indexOf('--scheme');
26
+ const scheme = schemeIndex >= 0 ? rest[schemeIndex + 1] : 'light';
27
+
28
+ const executablePath = findBrowser();
29
+ if (executablePath === undefined) {
30
+ process.stderr.write(`${browserNotFoundHelp()}\n`);
31
+ process.exit(1);
32
+ }
33
+
34
+ const files = (await readdir(sourceDir)).filter((f) => f.endsWith('.svg')).sort();
35
+ if (files.length === 0) {
36
+ process.stderr.write(`no hay SVG en ${sourceDir}\n`);
37
+ process.exit(1);
38
+ }
39
+
40
+ await mkdir(targetDir, { recursive: true });
41
+ const browser = await puppeteer.launch({ executablePath, headless: true, args: ['--no-sandbox'] });
42
+
43
+ for (const file of files) {
44
+ const svg = await readFile(path.join(sourceDir, file), 'utf8');
45
+ const page = await browser.newPage();
46
+ // El orden de los atributos varia entre motores: se leen por nombre.
47
+ const openTag = /<svg\b[^>]*>/.exec(svg)?.[0] ?? '';
48
+ const width = Number(/\bwidth="(\d+(?:\.\d+)?)"/.exec(openTag)?.[1] ?? 900);
49
+ const height = Number(/\bheight="(\d+(?:\.\d+)?)"/.exec(openTag)?.[1] ?? 700);
50
+
51
+ await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: scheme }]);
52
+ await page.setViewport({ width: Math.min(width, 2400), height: Math.min(height, 2400), deviceScaleFactor: scale });
53
+ // El SVG se carga como imagen, igual que en un visor Markdown: es la unica
54
+ // forma de comprobar que su variante oscura se activa de verdad.
55
+ const dataUri = `data:image/svg+xml;base64,${Buffer.from(svg, 'utf8').toString('base64')}`;
56
+ await page.setContent(
57
+ `<!doctype html><html><body style="margin:0;background:${scheme === 'dark' ? '#0b0d10' : '#ffffff'}">` +
58
+ `<img src="${dataUri}" width="${width}" height="${height}"></body></html>`,
59
+ { waitUntil: 'load' },
60
+ );
61
+ const png = await page.screenshot({ type: 'png', fullPage: true });
62
+ const target = path.join(targetDir, file.replace(/\.svg$/, '.png'));
63
+ await writeFile(target, png);
64
+ await page.close();
65
+ process.stdout.write(`${file} -> ${path.relative(process.cwd(), target)} (${width}x${height})\n`);
66
+ }
67
+
68
+ await browser.close();
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sincroniza con el catalogo todo lo que la documentacion afirma sobre los
4
+ * tipos disponibles.
5
+ *
6
+ * El catalogo es la fuente de verdad, pero README, AGENTS y la documentacion
7
+ * del proyecto repiten sus tablas para que se puedan leer sin ejecutar nada.
8
+ * Copiar a mano garantiza que un dia diverjan, asi que las regiones marcadas se
9
+ * generan desde el codigo.
10
+ *
11
+ * node scripts/sync-docs.mjs regenera
12
+ * node scripts/sync-docs.mjs --check falla si algo quedo desfasado
13
+ *
14
+ * El modo `--check` es lo que convierte la promesa en garantia: forma parte de
15
+ * `docs:check` y de las pruebas, asi que un tipo nuevo no puede publicarse con
16
+ * la documentacion vieja.
17
+ */
18
+
19
+ import { readFile, writeFile } from 'node:fs/promises';
20
+ import path from 'node:path';
21
+ import process from 'node:process';
22
+ import { fileURLToPath } from 'node:url';
23
+ import { TYPE_CATALOG } from '../dist/dsl/catalog.js';
24
+ import { themeNames } from '../dist/themes/index.js';
25
+
26
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
27
+ const check = process.argv.includes('--check');
28
+
29
+ // --------------------------------------------------------------------------
30
+ // Fragmentos generados
31
+ // --------------------------------------------------------------------------
32
+
33
+ const LANGS = [
34
+ ['diagram', 'Diagramas — bloque `diagram`'],
35
+ ['chart', 'Gráficos — bloque `chart`'],
36
+ ['architecture', 'Arquitectura — bloque `architecture`'],
37
+ ];
38
+
39
+ /** Tabla "necesidad -> tipo -> motor" de una valla. */
40
+ function tablaPorValla(lang) {
41
+ const filas = TYPE_CATALOG.filter((s) => s.lang === lang).map((s) => {
42
+ const respaldo = s.fallbacks !== undefined && s.fallbacks.length > 0 ? ` (o ${s.fallbacks.join(' / ')})` : '';
43
+ return `| ${s.purpose.replace(/\.$/, '')} | \`${s.type}\` | ${s.engine}${respaldo} |`;
44
+ });
45
+ return ['| Necesidad | `type` | Motor |', '|---|---|---|', ...filas].join('\n');
46
+ }
47
+
48
+ /** Las tres tablas, con su encabezado. */
49
+ function tablasCompletas(nivel) {
50
+ const h = '#'.repeat(nivel);
51
+ return LANGS.map(([lang, titulo]) => `${h} ${titulo}\n\n${tablaPorValla(lang)}`).join('\n\n');
52
+ }
53
+
54
+ /** Recuento por motor, para el resumen del README. */
55
+ function resumenPorMotor() {
56
+ const porMotor = new Map();
57
+ for (const spec of TYPE_CATALOG) {
58
+ porMotor.set(spec.engine, (porMotor.get(spec.engine) ?? 0) + 1);
59
+ }
60
+ const filas = [...porMotor.entries()]
61
+ .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
62
+ .map(([motor, n]) => `| ${motor} | ${n} |`);
63
+ return ['| Motor | Tipos |', '|---|---|', ...filas].join('\n');
64
+ }
65
+
66
+ /** Diagrama que explica el reparto de intenciones entre motores. */
67
+ function diagramaDeReparto() {
68
+ const porMotor = new Map();
69
+ for (const spec of TYPE_CATALOG) {
70
+ const lista = porMotor.get(spec.engine) ?? [];
71
+ lista.push(spec.type);
72
+ porMotor.set(spec.engine, lista);
73
+ }
74
+ const lineas = ['type: flow', 'title: Del tipo declarado al motor', 'direction: lr', '', 'flow:'];
75
+ for (const [motor, tipos] of [...porMotor.entries()].sort((a, b) => b[1].length - a[1].length)) {
76
+ // Tres ejemplos bastan para que se entienda el reparto; la lista completa
77
+ // esta en la tabla, y un diagrama con 57 nodos no explicaria nada.
78
+ const muestra = tipos.slice(0, 3).join(', ');
79
+ const resto = tipos.length > 3 ? ` y ${tipos.length - 3} mas` : '';
80
+ lineas.push(` - DSL -> ${motor}: ${muestra}${resto}`);
81
+ }
82
+ return ['```diagram', ...lineas, '```'].join('\n');
83
+ }
84
+
85
+ const FRAGMENTOS = {
86
+ 'tipos-tablas-3': () => tablasCompletas(3),
87
+ 'tipos-tablas-4': () => tablasCompletas(4),
88
+ 'tipos-resumen': () => resumenPorMotor(),
89
+ 'tipos-reparto': () => diagramaDeReparto(),
90
+ 'tipos-total': () => String(TYPE_CATALOG.length),
91
+ 'temas': () => themeNames().map((t) => `\`${t}\``).join(', '),
92
+ };
93
+
94
+ // --------------------------------------------------------------------------
95
+ // Sustitucion entre marcas
96
+ // --------------------------------------------------------------------------
97
+
98
+ /**
99
+ * Reemplaza el contenido entre `<!-- docviz:<nombre> -->` y
100
+ * `<!-- /docviz:<nombre> -->`.
101
+ *
102
+ * Se usan comentarios HTML porque son invisibles al leer el Markdown y
103
+ * sobreviven a la compilacion, de modo que la region se puede regenerar tantas
104
+ * veces como haga falta sin tocar la prosa que la rodea.
105
+ */
106
+ function aplicar(texto, archivo) {
107
+ let salida = texto;
108
+ const marcas = [...texto.matchAll(/<!--\s*docviz:([\w-]+)\s*-->/g)].map((m) => m[1]);
109
+
110
+ for (const nombre of marcas) {
111
+ const generar = FRAGMENTOS[nombre];
112
+ if (generar === undefined) {
113
+ throw new Error(`${archivo}: la marca "docviz:${nombre}" no corresponde a ningun fragmento conocido`);
114
+ }
115
+ const patron = new RegExp(
116
+ `(<!--\\s*docviz:${nombre}\\s*-->)[\\s\\S]*?(<!--\\s*/docviz:${nombre}\\s*-->)`,
117
+ 'g',
118
+ );
119
+ if (!patron.test(salida)) {
120
+ throw new Error(`${archivo}: falta la marca de cierre <!-- /docviz:${nombre} -->`);
121
+ }
122
+ patron.lastIndex = 0;
123
+ const contenido = generar();
124
+ // Un fragmento de una sola linea se queda en linea: si no, partiria la
125
+ // frase que lo rodea y el Markdown fuente quedaria ilegible.
126
+ const cuerpo = contenido.includes('\n') ? `\n${contenido}\n` : contenido;
127
+ salida = salida.replace(patron, `$1${cuerpo}$2`);
128
+ }
129
+ return salida;
130
+ }
131
+
132
+ const ARCHIVOS = ['README.md', 'AGENTS.md', 'docs-src/dsl.md'];
133
+
134
+ let desfasados = [];
135
+ for (const relativo of ARCHIVOS) {
136
+ const archivo = path.join(root, relativo);
137
+ const original = await readFile(archivo, 'utf8');
138
+ const actualizado = aplicar(original, relativo);
139
+ if (original === actualizado) continue;
140
+ if (check) desfasados.push(relativo);
141
+ else await writeFile(archivo, actualizado, 'utf8');
142
+ }
143
+
144
+ if (check) {
145
+ if (desfasados.length > 0) {
146
+ process.stderr.write(
147
+ `Documentacion desfasada respecto al catalogo:\n` +
148
+ desfasados.map((f) => ` - ${f}`).join('\n') +
149
+ `\n\nEjecuta \`npm run docs:sync\` y vuelve a confirmar.\n`,
150
+ );
151
+ process.exit(1);
152
+ }
153
+ process.stdout.write(`documentacion al dia con el catalogo (${TYPE_CATALOG.length} tipos)\n`);
154
+ } else {
155
+ process.stdout.write(
156
+ `sincronizados ${ARCHIVOS.length} documentos con el catalogo (${TYPE_CATALOG.length} tipos)\n`,
157
+ );
158
+ }
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: docviz
3
+ description: Genera diagramas y gráficos dentro de documentación Markdown declarando la intención (secuencia, flujo, arquitectura C4, barras, tendencia…) en lugar de escribir PlantUML, Mermaid, D2 o Vega-Lite a mano. Úsalo siempre que vayas a dibujar algo en un documento, cuando dudes qué tipo de diagrama encaja, o cuando un bloque de diagrama no compile. Todo se renderiza en local y la salida es Markdown estándar con imágenes SVG, así que se ve igual en GitHub, en un wiki o en un PDF.
4
+ ---
5
+
6
+ # DocViz — diagramas como código dentro de Markdown
7
+
8
+ Escribes **qué quieres explicar**; DocViz elige el motor y devuelve Markdown
9
+ portable con la imagen ya generada. No escribas PlantUML, Mermaid, D2, Graphviz,
10
+ Vega-Lite ni LikeC4 a mano: cada visor soporta un subconjunto distinto y el
11
+ resultado deja de verse según dónde se lea.
12
+
13
+ ## Las tres vallas
14
+
15
+ | Valla | Cuándo |
16
+ |---|---|
17
+ | `diagram` | Interacción, flujo, estados, dependencias, análisis estratégico |
18
+ | `chart` | Comparación cuantitativa, tendencia, distribución |
19
+ | `architecture` | Modelo C4 |
20
+
21
+ ````md
22
+ ```diagram
23
+ type: sequence
24
+ title: Autenticación
25
+
26
+ participants:
27
+ - Usuario
28
+ - API
29
+
30
+ flow:
31
+ - Usuario -> API: Login
32
+ - API --> Usuario: Token
33
+ ```
34
+ ````
35
+
36
+ `->` es un mensaje, `-->` una respuesta.
37
+
38
+ ## No adivines el tipo — pregunta
39
+
40
+ Hay 57 tipos. Antes de escribir un bloque, si no estás seguro:
41
+
42
+ ```bash
43
+ npx docviz suggest "el proceso de aprobación de una solicitud" # recomienda el tipo
44
+ npx docviz types # catálogo con su propósito
45
+ npx docviz types sequence # ficha y ejemplo que compila tal cual
46
+ ```
47
+
48
+ `docviz types <tipo>` imprime el esqueleto mínimo del tipo. Cópialo y rellénalo:
49
+ es la forma más rápida de no equivocarte de campo.
50
+
51
+ ## Flujo de trabajo
52
+
53
+ ```bash
54
+ npx docviz check docs-src # valida sin dibujar (rápido)
55
+ npx docviz build docs-src --output docs # compila a Markdown + SVG
56
+ npx docviz verify docs # comprueba que no haya imágenes rotas
57
+ npx docviz diff <docs-src anterior> docs-src # qué diagramas cambiaron
58
+ ```
59
+
60
+ No des la tarea por terminada mientras `check` o `verify` fallen.
61
+
62
+ ## Cuando algo falla
63
+
64
+ Cada error trae un **código** además de archivo y línea. Léelo, no adivines:
65
+
66
+ | Código | Qué hacer |
67
+ |---|---|
68
+ | `DV101` | Falta un campo obligatorio; el detalle dice cuál |
69
+ | `DV102` | El campo está con la forma equivocada (lista donde iba mapa, o al revés) |
70
+ | `DV103` | El valor no es uno de los admitidos; el detalle los enumera |
71
+ | `DV104` | Escribiste un campo que ese tipo no usa. Si te propone otro nombre, es una errata |
72
+ | `DV105` | El bloque no es YAML válido; suele ser la indentación |
73
+ | `DV106` | El `type` no existe o va en otra valla; usa `docviz suggest` |
74
+ | `DV005` | Falta Java o Chromium en la máquina. No cambies el diagrama: dilo |
75
+
76
+ Un documento con varios bloques rotos los reporta **todos a la vez**:
77
+ arréglalos en una sola pasada.
78
+
79
+ Y antes de reescribir un bloque a mano:
80
+
81
+ ```bash
82
+ npx docviz fix bloque.yaml # corrige las erratas y dice si con eso basta
83
+ ```
84
+
85
+ Un `AVISO ... [DV104]` no rompe el build, pero significa que un campo que
86
+ escribiste no llegó al dibujo. O sobra, o está mal escrito; en ningún caso se
87
+ ignora.
88
+
89
+ ## Reglas
90
+
91
+ - Modifica los documentos fuente; nunca el directorio de salida ni `assets/generated`.
92
+ - No generes SVG o PNG a mano si DocViz puede generarlos.
93
+ - No fijes colores: el tema trae su equivalente en modo oscuro y un color escrito
94
+ a mano pierde esa propiedad.
95
+ - No sustituyas un diagrama declarativo por una captura de pantalla.
96
+ - Antes de dibujar, comprueba que aporta algo: para información sencilla, una
97
+ tabla o un párrafo comunican mejor. Un diagrama de veinte cajas no explica
98
+ nada — divídelo.
99
+
100
+ ## Primera vez en un proyecto
101
+
102
+ ```bash
103
+ npm install -D docviz-builder
104
+ npx docviz setup # descarga plantuml.jar (única operación de red)
105
+ npx docviz init # configuración, AGENTS.md y un documento de ejemplo
106
+ npx docviz doctor # qué motores puede usar esta máquina
107
+ ```
108
+
109
+ `docviz init` deja un `AGENTS.md` con el catálogo completo de los 57 tipos y sus
110
+ tablas de decisión. Consúltalo cuando necesites el detalle que este resumen no
111
+ trae.
File without changes