Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -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\<mismo-nombre>.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: ... (<n> 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\<nombre>.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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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; }
|
||||
Vendored
BIN
Binary file not shown.
Reference in New Issue
Block a user