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.
- package/AGENTS.md +371 -0
- package/LICENSE +21 -0
- package/README.md +837 -0
- package/bin/docviz-mcp.mjs +10 -0
- package/bin/docviz.mjs +11 -0
- package/dist/build/builder.d.ts +62 -0
- package/dist/build/builder.d.ts.map +1 -0
- package/dist/build/builder.js +337 -0
- package/dist/build/builder.js.map +1 -0
- package/dist/build/diff.d.ts +64 -0
- package/dist/build/diff.d.ts.map +1 -0
- package/dist/build/diff.js +156 -0
- package/dist/build/diff.js.map +1 -0
- package/dist/build/doctor.d.ts +39 -0
- package/dist/build/doctor.d.ts.map +1 -0
- package/dist/build/doctor.js +190 -0
- package/dist/build/doctor.js.map +1 -0
- package/dist/build/init.d.ts +28 -0
- package/dist/build/init.d.ts.map +1 -0
- package/dist/build/init.js +274 -0
- package/dist/build/init.js.map +1 -0
- package/dist/build/preview.d.ts +13 -0
- package/dist/build/preview.d.ts.map +1 -0
- package/dist/build/preview.js +277 -0
- package/dist/build/preview.js.map +1 -0
- package/dist/build/skill.d.ts +41 -0
- package/dist/build/skill.d.ts.map +1 -0
- package/dist/build/skill.js +63 -0
- package/dist/build/skill.js.map +1 -0
- package/dist/build/verify.d.ts +26 -0
- package/dist/build/verify.d.ts.map +1 -0
- package/dist/build/verify.js +99 -0
- package/dist/build/verify.js.map +1 -0
- package/dist/cli.d.ts +20 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +427 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/load.d.ts +32 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +279 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/types.d.ts +89 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/core/cache.d.ts +32 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +69 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/errors.d.ts +115 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +164 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/hash.d.ts +57 -0
- package/dist/core/hash.d.ts.map +1 -0
- package/dist/core/hash.js +0 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/package-version.d.ts +9 -0
- package/dist/core/package-version.d.ts.map +1 -0
- package/dist/core/package-version.js +44 -0
- package/dist/core/package-version.js.map +1 -0
- package/dist/core/paths.d.ts +46 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +105 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/registry.d.ts +24 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +72 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/types.d.ts +78 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +11 -0
- package/dist/core/types.js.map +1 -0
- package/dist/dsl/architecture.d.ts +15 -0
- package/dist/dsl/architecture.d.ts.map +1 -0
- package/dist/dsl/architecture.js +242 -0
- package/dist/dsl/architecture.js.map +1 -0
- package/dist/dsl/catalog.d.ts +62 -0
- package/dist/dsl/catalog.d.ts.map +1 -0
- package/dist/dsl/catalog.en.d.ts +18 -0
- package/dist/dsl/catalog.en.d.ts.map +1 -0
- package/dist/dsl/catalog.en.js +299 -0
- package/dist/dsl/catalog.en.js.map +1 -0
- package/dist/dsl/catalog.js +1082 -0
- package/dist/dsl/catalog.js.map +1 -0
- package/dist/dsl/chart.d.ts +14 -0
- package/dist/dsl/chart.d.ts.map +1 -0
- package/dist/dsl/chart.js +435 -0
- package/dist/dsl/chart.js.map +1 -0
- package/dist/dsl/compile.d.ts +31 -0
- package/dist/dsl/compile.d.ts.map +1 -0
- package/dist/dsl/compile.js +120 -0
- package/dist/dsl/compile.js.map +1 -0
- package/dist/dsl/diagram-bpmn.d.ts +13 -0
- package/dist/dsl/diagram-bpmn.d.ts.map +1 -0
- package/dist/dsl/diagram-bpmn.js +215 -0
- package/dist/dsl/diagram-bpmn.js.map +1 -0
- package/dist/dsl/diagram-product.d.ts +15 -0
- package/dist/dsl/diagram-product.d.ts.map +1 -0
- package/dist/dsl/diagram-product.js +291 -0
- package/dist/dsl/diagram-product.js.map +1 -0
- package/dist/dsl/diagram-technical.d.ts +28 -0
- package/dist/dsl/diagram-technical.d.ts.map +1 -0
- package/dist/dsl/diagram-technical.js +365 -0
- package/dist/dsl/diagram-technical.js.map +1 -0
- package/dist/dsl/diagram.d.ts +22 -0
- package/dist/dsl/diagram.d.ts.map +1 -0
- package/dist/dsl/diagram.js +542 -0
- package/dist/dsl/diagram.js.map +1 -0
- package/dist/dsl/fallbacks-d2.d.ts +27 -0
- package/dist/dsl/fallbacks-d2.d.ts.map +1 -0
- package/dist/dsl/fallbacks-d2.js +265 -0
- package/dist/dsl/fallbacks-d2.js.map +1 -0
- package/dist/dsl/fallbacks.d.ts +25 -0
- package/dist/dsl/fallbacks.d.ts.map +1 -0
- package/dist/dsl/fallbacks.js +264 -0
- package/dist/dsl/fallbacks.js.map +1 -0
- package/dist/dsl/fields.d.ts +93 -0
- package/dist/dsl/fields.d.ts.map +1 -0
- package/dist/dsl/fields.js +233 -0
- package/dist/dsl/fields.js.map +1 -0
- package/dist/dsl/index.d.ts +50 -0
- package/dist/dsl/index.d.ts.map +1 -0
- package/dist/dsl/index.js +114 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/dsl/util.d.ts +105 -0
- package/dist/dsl/util.d.ts.map +1 -0
- package/dist/dsl/util.js +261 -0
- package/dist/dsl/util.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown/scan.d.ts +73 -0
- package/dist/markdown/scan.d.ts.map +1 -0
- package/dist/markdown/scan.js +150 -0
- package/dist/markdown/scan.js.map +1 -0
- package/dist/markdown/transform.d.ts +28 -0
- package/dist/markdown/transform.d.ts.map +1 -0
- package/dist/markdown/transform.js +38 -0
- package/dist/markdown/transform.js.map +1 -0
- package/dist/mcp/server.d.ts +18 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +118 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +118 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +573 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/renderers/base.d.ts +18 -0
- package/dist/renderers/base.d.ts.map +1 -0
- package/dist/renderers/base.js +59 -0
- package/dist/renderers/base.js.map +1 -0
- package/dist/renderers/bpmn.d.ts +68 -0
- package/dist/renderers/bpmn.d.ts.map +1 -0
- package/dist/renderers/bpmn.js +158 -0
- package/dist/renderers/bpmn.js.map +1 -0
- package/dist/renderers/browser.d.ts +30 -0
- package/dist/renderers/browser.d.ts.map +1 -0
- package/dist/renderers/browser.js +143 -0
- package/dist/renderers/browser.js.map +1 -0
- package/dist/renderers/color-scheme.d.ts +40 -0
- package/dist/renderers/color-scheme.d.ts.map +1 -0
- package/dist/renderers/color-scheme.js +122 -0
- package/dist/renderers/color-scheme.js.map +1 -0
- package/dist/renderers/d2.d.ts +37 -0
- package/dist/renderers/d2.d.ts.map +1 -0
- package/dist/renderers/d2.js +108 -0
- package/dist/renderers/d2.js.map +1 -0
- package/dist/renderers/graphviz.d.ts +33 -0
- package/dist/renderers/graphviz.d.ts.map +1 -0
- package/dist/renderers/graphviz.js +88 -0
- package/dist/renderers/graphviz.js.map +1 -0
- package/dist/renderers/in-page.d.ts +33 -0
- package/dist/renderers/in-page.d.ts.map +1 -0
- package/dist/renderers/in-page.js +76 -0
- package/dist/renderers/in-page.js.map +1 -0
- package/dist/renderers/index.d.ts +20 -0
- package/dist/renderers/index.d.ts.map +1 -0
- package/dist/renderers/index.js +94 -0
- package/dist/renderers/index.js.map +1 -0
- package/dist/renderers/kroki.d.ts +38 -0
- package/dist/renderers/kroki.d.ts.map +1 -0
- package/dist/renderers/kroki.js +151 -0
- package/dist/renderers/kroki.js.map +1 -0
- package/dist/renderers/likec4-svg.d.ts +82 -0
- package/dist/renderers/likec4-svg.d.ts.map +1 -0
- package/dist/renderers/likec4-svg.js +435 -0
- package/dist/renderers/likec4-svg.js.map +1 -0
- package/dist/renderers/likec4.d.ts +22 -0
- package/dist/renderers/likec4.d.ts.map +1 -0
- package/dist/renderers/likec4.js +77 -0
- package/dist/renderers/likec4.js.map +1 -0
- package/dist/renderers/mermaid.d.ts +64 -0
- package/dist/renderers/mermaid.d.ts.map +1 -0
- package/dist/renderers/mermaid.js +196 -0
- package/dist/renderers/mermaid.js.map +1 -0
- package/dist/renderers/plantuml.d.ts +56 -0
- package/dist/renderers/plantuml.d.ts.map +1 -0
- package/dist/renderers/plantuml.js +195 -0
- package/dist/renderers/plantuml.js.map +1 -0
- package/dist/renderers/svg-utils.d.ts +46 -0
- package/dist/renderers/svg-utils.d.ts.map +1 -0
- package/dist/renderers/svg-utils.js +439 -0
- package/dist/renderers/svg-utils.js.map +1 -0
- package/dist/renderers/svgbob.d.ts +26 -0
- package/dist/renderers/svgbob.d.ts.map +1 -0
- package/dist/renderers/svgbob.js +70 -0
- package/dist/renderers/svgbob.js.map +1 -0
- package/dist/renderers/vega-lite.d.ts +18 -0
- package/dist/renderers/vega-lite.d.ts.map +1 -0
- package/dist/renderers/vega-lite.js +94 -0
- package/dist/renderers/vega-lite.js.map +1 -0
- package/dist/themes/index.d.ts +17 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +419 -0
- package/dist/themes/index.js.map +1 -0
- package/dist/themes/types.d.ts +99 -0
- package/dist/themes/types.d.ts.map +1 -0
- package/dist/themes/types.js +9 -0
- package/dist/themes/types.js.map +1 -0
- package/eval/casos.json +513 -0
- package/package.json +114 -0
- package/scripts/capture-preview.mjs +101 -0
- package/scripts/check-github.mjs +128 -0
- package/scripts/eval.d.mts +8 -0
- package/scripts/eval.mjs +284 -0
- package/scripts/fetch-plantuml.mjs +122 -0
- package/scripts/generate-catalog-doc.mjs +106 -0
- package/scripts/rasterize.mjs +68 -0
- package/scripts/sync-docs.mjs +158 -0
- package/skills/docviz/SKILL.md +111 -0
- 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.
|
package/vendor/.gitkeep
ADDED
|
File without changes
|