diff --git a/.opencode/skills/book-pdf/SKILL.md b/.opencode/skills/book-pdf/SKILL.md new file mode 100644 index 0000000..249b2f4 --- /dev/null +++ b/.opencode/skills/book-pdf/SKILL.md @@ -0,0 +1,61 @@ +--- +name: book-pdf +description: Generar o regenerar los PDF de los capítulos del libro de C en dist/, con diseño consistente (resaltado de sintaxis, fuente mono para código, notas con fondo de color). Trigger - pdf, generar pdf, exportar capítulo, dist, md-to-pdf, print.css, "convertir a pdf", "rehacer pdf". +--- + +# Skill: book-pdf — Generación de PDF de los capítulos + +Todos los PDF del libro se generan **siempre** con este procedimiento, para que mantengan +exactamente el mismo diseño. Fuente de diseño única: `assets/pdf/print.css`. + +## Herramienta + +Usar el MCP **`md-to-pdf`** → herramienta **`md-to-pdf_markdown_to_pdf`**. +(NO escribir un pipeline propio con Node/Puppeteer ni instalar pandoc/LaTeX: ya existe este MCP.) + +## Pasos + +1. **Leer** `assets/pdf/print.css` (con la tool `read`). +2. **Invocar** `md-to-pdf_markdown_to_pdf` con estos parámetros fijos: + + | Parámetro | Valor | + | ----------------- | -------------------------------------------------------------- | + | `inputPath` | ruta absoluta del capítulo, p. ej. `book\12-arenas.md` | + | `outputPath` | `dist\.pdf`, p. ej. `dist\12-arenas.pdf` | + | `css` | **el contenido completo** de `assets/pdf/print.css` | + | `format` | `A4` | + | `printBackground` | `true` (obligatorio: pinta los fondos de código y notas) | + | `pageNumbers` | `true` | + | `headerText` | `Programación en C — Libro de ejercicios` | + | `footerText` | el capítulo, p. ej. `12 — Arenas` | + +3. Comprobar que la respuesta diga `PDF generated: ... ( KB)`. + +## Reglas de diseño (no romper) + +- **Fuente del cuerpo**: serif (`Georgia` / `Palatino` / `Times`). Definida en `print.css`. +- **Fuente de código**: mono distinta de la del cuerpo (`Cascadia Code` / `JetBrains Mono` / + `Consolas`). **Todo bloque de código debe declarar su lenguaje** en el fence + (```` ```c ````, ```` ```bash ````, ```` ```text ````). Sin lenguaje, `highlight.js` lo trata como + `plaintext` y **no hay resaltado**. Para trazas de consola usar ```` ```text ````. +- **Notas / advertencias**: se escriben como **blockquote** (`>`). En el PDF se dibujan **todas** + igual: caja con fondo azul claro (`#eef4fb`) y borde izquierdo acentuado. No inventar estilos + distintos de nota. +- **Resaltado**: `md-to-pdf` usa `highlight.js` y emite clases `.hljs-*`; los colores están en + `print.css`. No cambiar colores fuera de `print.css`. + +## Cambiar el diseño + +Si hay que cambiar fuentes, colores o el estilo de las notas, **editar solo +`assets/pdf/print.css`** (es la fuente única) y regenerar **todos** los capítulos para que no +queden PDF con diseños distintos. + +## Regenerar todo + +Generar cada `book\*.md` a `dist\.pdf` con los parámetros de arriba, uno por uno. + +## Notas de compatibilidad + +- Verificado en esta máquina: `md-to-pdf` 5.2.5 con `marked` 4.3.0 y `highlight.js` 11.12.0; + el highlighter de `md-to-pdf` **sí** resalta (emite `.hljs-keyword/string/comment`). +- El MCP corre headless Chromium vía `md-to-pdf`; no requiere instalación adicional. diff --git a/AGENTS.md b/AGENTS.md index 2111a8f..44fa90c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -80,21 +80,30 @@ El libro vive bajo un directorio raíz de contenido. Se propone: ``` c-programming/ -├─ AGENTS.md # este archivo (reglas del proyecto) -├─ README.md # presentación del libro e índice general -└─ book/ - ├─ 00-introduccion.md - ├─ 01-conceptos-basicos.md - ├─ 02-variables-y-tipos.md - ├─ 03-operadores-y-expresiones.md - ├─ 04-estructuras-de-control.md - ├─ 05-funciones.md - ├─ 06-arreglos-y-cadenas.md - ├─ 07-punteros.md - ├─ 08-structs-y-uniones.md - ├─ 09-memoria-dinamica.md - ├─ 10-archivos.md - └─ 11-estructuras-de-datos.md +├─ AGENTS.md # este archivo (reglas del proyecto) +├─ README.md # presentación del libro e índice general +├─ book/ # FUENTE: capítulos en Markdown +│ ├─ 00-introduccion.md +│ ├─ 01-conceptos-basicos.md +│ ├─ 02-variables-y-tipos.md +│ ├─ 03-operadores-y-expresiones.md +│ ├─ 04-estructuras-de-control.md +│ ├─ 05-funciones.md +│ ├─ 06-arreglos-y-cadenas.md +│ ├─ 07-punteros.md +│ ├─ 08-structs-y-uniones.md +│ ├─ 09-memoria-dinamica.md +│ ├─ 10-archivos.md +│ ├─ 11-estructuras-de-datos.md +│ └─ 12-arenas.md +├─ dist/ # SALIDA: un PDF por cada capítulo trabajado +│ └─ 12-arenas.pdf +├─ assets/ +│ └─ pdf/ +│ └─ print.css # hoja de estilo canónica de los PDF +└─ .opencode/ + └─ skills/ + └─ book-pdf/SKILL.md # procedimiento para generar los PDF ``` - **Un archivo por tema/concepto principal.** @@ -163,3 +172,32 @@ Checklist al crear o editar un ejercicio: 10. Actualizar el índice del `README.md` si se agregó un capítulo. > Recordatorio permanente: se entrega el **problema**, nunca la **respuesta**. + +--- + +## 9. Generación de PDF (`dist/`) + +Cada capítulo trabajado se publica como **PDF** en `dist/`, con el **mismo nombre** que su +Markdown: `book/12-arenas.md` → `dist/12-arenas.pdf`. + +- Los PDF se generan con el MCP **`md-to-pdf`** (herramienta `md-to-pdf_markdown_to_pdf`). + **No** instalar pandoc/LaTeX ni armar un pipeline propio: ya existe. +- El diseño es **único y compartido**: vive en `assets/pdf/print.css`. No se estiliza capítulo + por capítulo. +- El procedimiento completo y los **parámetros fijos** de generación están en la skill del + proyecto: `.opencode/skills/book-pdf/SKILL.md`. Hay que **seguirla siempre** para que todos los + PDF tengan el mismo diseño. + +Reglas de diseño (resumen): + +- **Fuente de código:** monoespaciada, distinta de la fuente del cuerpo (serif). Todo bloque de + código declara su lenguaje en el fence (```` ```c ````, ```` ```bash ````, ```` ```text ````); + así `highlight.js` aplica **resaltado de sintaxis**. Un bloque sin lenguaje no se resalta + (las trazas de consola van como ```` ```text ````). +- **Notas / advertencias:** se escriben como **blockquote** (`>`). En el PDF **todas** se dibujan + igual, con un **fondo de color** que resalta del blanco de la hoja. +- `printBackground` debe estar **activo** (si no, no se pintan los fondos de código y notas). +- Encabezado, pie de página y **numeración de páginas** fijos. + +> Si se modifica `assets/pdf/print.css`, hay que **regenerar todos** los capítulos para que ningún +> PDF quede con un diseño distinto. diff --git a/assets/pdf/print.css b/assets/pdf/print.css new file mode 100644 index 0000000..baf3950 --- /dev/null +++ b/assets/pdf/print.css @@ -0,0 +1,126 @@ +/* ===================================================================== + print.css — Hoja de estilo canónica para los PDF del libro. + Usada por el MCP `md-to-pdf` (herramienta markdown_to_pdf) como `css`. + Reglas de diseño: ver AGENTS.md y .opencode/skills/book-pdf/SKILL.md + NO editar los colores/fuentes sin actualizar también esas referencias. + ===================================================================== */ + +/* --- Garantiza que los colores de fondo se impriman --- */ +html { + -webkit-print-color-adjust: exact; + print-color-adjust: exact; +} + +:root { + --ink: #1f2733; + --muted: #5b6673; + --accent: #2f6fb3; /* azul del libro */ + --rule: #dfe4ea; + + --note-bg: #eef4fb; /* fondo de las notas (resalta del blanco) */ + --note-border: #2f6fb3; + + --code-bg: #f4f6f8; + --code-border: #dfe4ea; + --code-accent: #2f6fb3; +} + +/* --- Tipografía del cuerpo: SERIF (distinta de la mono del código) --- */ +body { + font-family: "Georgia", "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif; + font-size: 11.5pt; + line-height: 1.6; + color: var(--ink); +} + +/* --- Títulos: sans, para diferenciar de la prosa --- */ +h1, h2, h3, h4 { + font-family: "Segoe UI", "Calibri", system-ui, sans-serif; + color: #16202b; + line-height: 1.25; +} +h1 { font-size: 22pt; border-bottom: 3px solid var(--accent); padding-bottom: .25em; } +h2 { font-size: 16pt; margin-top: 1.7em; border-bottom: 1px solid var(--rule); padding-bottom: .2em; } +h3 { font-size: 13pt; margin-top: 1.3em; } +h4 { font-size: 11.5pt; margin-top: 1.1em; } + +/* --- Código inline: MONO, distinta de la serif del texto --- */ +code { + font-family: "Cascadia Code", "JetBrains Mono", "Consolas", "Courier New", monospace; + font-size: .88em; + background: var(--code-bg); + border: 1px solid var(--code-border); + border-radius: 4px; + padding: .08em .35em; +} + +/* --- Bloques de código: MONO + resaltado de sintaxis (highlight.js) --- */ +pre { + font-family: "Cascadia Code", "JetBrains Mono", "Consolas", "Courier New", monospace; + font-size: 9.5pt; + line-height: 1.5; + background: var(--code-bg); + border: 1px solid var(--code-border); + border-left: 4px solid var(--code-accent); + border-radius: 6px; + padding: .85em 1.1em; + white-space: pre-wrap; /* evita que el código se salga de la hoja */ + word-break: break-word; + overflow-wrap: anywhere; +} +pre code { + background: none; + border: none; + padding: 0; + font-size: inherit; + color: inherit; +} + +/* --- Paleta de resaltado de sintaxis (clases de highlight.js) --- */ +pre code.hljs { background: transparent; } +.hljs-comment, .hljs-quote { color: #6a737d; font-style: italic; } +.hljs-keyword, .hljs-selector-tag, +.hljs-built_in, .hljs-name { color: #c0392b; font-weight: 600; } +.hljs-string, .hljs-meta-string, +.hljs-regexp { color: #1a7f37; } +.hljs-number, .hljs-literal, +.hljs-boolean { color: #0550ae; } +.hljs-function, .hljs-title, +.hljs-title.function_, .hljs-params { color: #6f42c1; } +.hljs-type, .hljs-class .hljs-title { color: #953800; } +.hljs-meta, .hljs-preprocessor { color: #7a5af8; } +.hljs-variable, .hljs-attr, +.hljs-property, .hljs-template-variable { color: #0a3069; } +.hljs-symbol, .hljs-bullet, +.hljs-operator { color: #e36209; } + +/* --- Notas: TODO blockquote se dibuja igual, con fondo que resalta --- */ +blockquote { + margin: 1.2em 0; + padding: .8em 1.1em; + background: var(--note-bg); + border-left: 5px solid var(--note-border); + border-radius: 6px; + color: #24303d; +} +blockquote > :first-child { margin-top: 0; } +blockquote > :last-child { margin-bottom: 0; } +blockquote p { font-size: 10.5pt; } + +/* --- Tablas (escenarios de prueba) --- */ +table { + border-collapse: collapse; + width: 100%; + font-size: 10pt; + margin: 1em 0; +} +th, td { + border: 1px solid #d7dde3; + padding: .4em .6em; + text-align: left; +} +th { background: #eef1f4; font-family: "Segoe UI", "Calibri", sans-serif; } + +/* --- Separadores y enlaces --- */ +hr { border: none; border-top: 1px solid var(--rule); margin: 1.6em 0; } +a { color: var(--accent); text-decoration: none; } diff --git a/dist/12-arenas.pdf b/dist/12-arenas.pdf new file mode 100644 index 0000000..d7c9841 Binary files /dev/null and b/dist/12-arenas.pdf differ