# @ngx-docs-markdown-kit/parser-md-code-block

> Extension de @ngx-docs-markdown-kit/parser-md que reconoce bloques de codigo enriquecidos y tarjetas de comando (fences code-block/card-code-block), y expone los componentes de Angular (CodeBlockComponent, CardCodeBlockComponent) que los renderizan.

Latest version **0.2.0** (published 2026-09-24) · MIT license · 0 weekly downloads

## Install

```sh
npm install @ngx-docs-markdown-kit/parser-md-code-block
pnpm add @ngx-docs-markdown-kit/parser-md-code-block
yarn add @ngx-docs-markdown-kit/parser-md-code-block
bun add @ngx-docs-markdown-kit/parser-md-code-block
```

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.2.0 |
| Published | 2026-09-24 |
| First published | 2026-08-25 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | ^22.22.3 \|\| ^24.15.0 \|\| >=26.0.0 |
| Dependencies | 2 |
| Unpacked size | 169.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | FrugoCorp |
| Maintainers | frugocorp |
| Keywords | markdown, angular, code-block, syntax-highlighting, docs |

## Links

- npm: https://www.npmjs.com/package/@ngx-docs-markdown-kit/parser-md-code-block
- Repository: https://github.com/frugocorp/ngx-docs-markdown-kit
- Homepage: https://parser-md-code-block.frugocorp.com
- Issues: https://github.com/frugocorp/ngx-docs-markdown-kit/issues
- npm.io page: https://npm.io/package/@ngx-docs-markdown-kit/parser-md-code-block

## Dependencies (2)

- [tslib](https://npm.io/package/tslib.md) ^2.3.0
- [highlight.js](https://npm.io/package/highlight.js.md) ^11.11.1

## Alternatives

- [@oh-my-pi/pi-natives](https://npm.io/package/@oh-my-pi/pi-natives.md) — 51.8K weekly downloads
- [@capgo/capacitor-light-sensor](https://npm.io/package/@capgo/capacitor-light-sensor.md) — 3.0K weekly downloads
- [@heyhuynhgiabuu/pi-diff](https://npm.io/package/@heyhuynhgiabuu/pi-diff.md) — 492 weekly downloads
- [@lotsa/verdant-lang-asm](https://npm.io/package/@lotsa/verdant-lang-asm.md) — 38 weekly downloads
- [new-era-syntax](https://npm.io/package/new-era-syntax.md) — 20 weekly downloads

## Recent versions

- 0.2.0 (latest) — 2026-09-24
- 0.1.0 — 2026-08-25

## README

# @ngx-docs-markdown-kit/parser-md-code-block

Extension de [`@ngx-docs-markdown-kit/parser-md`](../parser-md) para bloques de codigo enriquecidos (boton de copiar, resaltado de sintaxis via `highlight.js`, temas configurables) y tarjetas de comando (comando + resultado esperado + nota). Mismo mecanismo que [`parser-md-image`](../parser-md-image): un fence normal con un `lang` especial, reconocido via `buildSegment()`. Cero cambios al nucleo.

Un fence de Markdown SIN uno de los 2 nombres reconocidos (ver abajo) nunca se enriquece -- cae al render default de `marked` (sin boton de copiar, sin componente). Este paquete es deliberadamente selectivo: enriquecer *todo* fence por default sorprende a cualquiera que solo quiera un ` ```bash ` normal.

## Sintaxis

### `code-block` -- un bloque de codigo enriquecido

4 backticks envolviendo UN fence normal de 3 backticks con el codigo real (asi el fence interior conserva el resaltado de sintaxis nativo de tu editor):

````md
`````code-block src/Program.cs
```csharp
Console.WriteLine("Hola");
```
`````
````

`src/Program.cs` (segundo token del info string, opcional) es la ruta recomendada donde vive ese codigo -- se muestra como parte de la etiqueta del bloque. El lenguaje para el resaltado de sintaxis lo trae el fence INTERIOR (`csharp` en el ejemplo), no el exterior.

Produce el mismo segmento `type: 'code'` que un fence simple ya enriquecido en versiones anteriores de este paquete.

### `card-code-block` -- comando + resultado esperado + nota

4 backticks con campos nombrados `@campo`, cada uno en su propia linea, hasta el siguiente `@campo` o el cierre del fence:

````md
`````card-code-block
@description
Corre las pruebas del proyecto con **npm**.

@command bash
npm test

@result<Resultado esperado> text
Test Files  1 passed (1)
     Tests  3 passed (3)

@note<Nota>
Si falla, revisa que hayas corrido `npm install` primero.
`````
````

Campos soportados (todos opcionales salvo `@command`):

| Campo | Contenido | Etiqueta visible |
| --- | --- | --- |
| `@description` | Markdown libre (parrafos siguientes hasta el proximo `@campo`) | Sin etiqueta, solo el texto |
| `@command [lang]` | Un fence de codigo (el comando real) | Sin etiqueta -- el lenguaje se muestra en la barra del bloque |
| `@result[<Etiqueta>] [lang]` | Un fence de codigo (la salida esperada) | `<Etiqueta>` si se da, si no "Resultado esperado" |
| `@note[<Etiqueta>]` | Markdown libre | `<Etiqueta>` si se da, si no ninguna (solo el icono) |

`<Etiqueta>` es texto libre entre `<` y `>`, opcional en cualquier campo (aunque solo `@result`/`@note` la muestran visualmente hoy). `lang` (para `@command`/`@result`) tambien es opcional -- si se omite, se usa el lenguaje que ya trae el fence de codigo anidado de ese campo.

Produce un segmento `type: 'card-code-block'` (`CardCodeBlockSegment`).

### Un fence normal, sin enriquecer

```md
```bash
npm install
```
```

Sigue funcionando exactamente igual que en Markdown puro (`marked` lo renderiza por su cuenta) -- sin boton de copiar, sin temas, sin componente Angular de por medio.

## Uso

```ts
import { createParser } from '@ngx-docs-markdown-kit/parser-md';
import { codeBlockExtension } from '@ngx-docs-markdown-kit/parser-md-code-block';

const parser = createParser().use(codeBlockExtension());
```

Y en el template, junto a los demas tipos de segmento (ver el `@switch` en `doc-segments.html` de `create-ngx-docs-site`):

```html
@case ('code') {
  <ndmk-code-block [code]="segment.code" [lang]="segment.lang" [path]="segment.path" />
}
@case ('card-code-block') {
  <ndmk-card-code-block
    [descriptionHtml]="segment.descriptionHtml"
    [commandLang]="segment.commandLang"
    [command]="segment.command"
    [resultLabel]="segment.resultLabel"
    [resultLang]="segment.resultLang"
    [resultText]="segment.resultText"
    [noteLabel]="segment.noteLabel"
    [noteHtml]="segment.noteHtml"
  />
}
```

## Temas de codigo

Ver [`parser-md-code-block-themes`](../parser-md-code-block-themes) (extension opcional) para paletas de color adicionales por lenguaje, seleccionables en runtime via `CodeThemeService`.

<!-- parser-md-code-block:doc_start -->
<!-- parser-md-code-block:doc_header_start -->
# parser-md-code-block

![parser-md-code-block](https://parser-md-code-block.frugocorp.com/images/FrugoCorp-Logo-300x300.jpg)

![version](https://img.shields.io/badge/version-0.2.0-blue) ![node](https://img.shields.io/badge/node-%5E22.22.3%20%7C%7C%20%5E24.15.0%20%7C%7C%20%3E%3D26.0.0-339933?logo=node.js&logoColor=white) [![npm](https://img.shields.io/npm/v/%40ngx-docs-markdown-kit%2Fparser-md-code-block)](https://www.npmjs.com/package/@ngx-docs-markdown-kit/parser-md-code-block)

**Dependencias:**
- `@angular/animations`: ^22.1.0
- `@angular/cdk`: ^22.1.0
- `@angular/common`: ^22.1.0
- `@angular/compiler`: ^22.1.0
- `@angular/core`: ^22.1.0
- `@angular/forms`: ^22.1.0
- `@angular/material`: ^22.1.0
- `@angular/platform-browser`: ^22.1.0
- `@angular/platform-server`: ^22.1.0
- `@angular/router`: ^22.1.0
- `@angular/ssr`: ^22.1.3
- `@ngx-docs-markdown-kit/parser-md`: ^0.1.0
- `@ngx-docs-markdown-kit/parser-md-seo`: ^0.1.0
- `@ngx-docs-markdown-kit/parser-md-code-block`: ^0.1.0
- `@ngx-docs-markdown-kit/parser-md-code-block-themes`: ^0.1.0
- `@ngx-docs-markdown-kit/parser-md-image`: ^0.1.0
- `@ngx-docs-markdown-kit/parser-md-card`: ^0.1.0
- `@ngx-docs-markdown-kit/parser-md-converter`: ^0.1.0
- `@ngx-docs-markdown-kit/ui`: ^0.1.0
- `rxjs`: ~7.8.0
- `tslib`: ^2.3.0
<!-- parser-md-code-block:doc_header_end -->
<!-- parser-md-code-block:doc_body_start -->
## Apartados de parser-md-code-block

- [Docs](#docs-de-parser-md-code-block) -- Documentación de @ngx-docs-markdown-kit/parser-md-code-block -- bloques de código enriquecidos y tarjetas de comando.
- [Parser MD Code Block](#parser-md-code-block-de-parser-md-code-block) -- Bloques de codigo enriquecidos y tarjetas de comando para sitios @ngx-docs-markdown-kit.

---

## Docs de parser-md-code-block

[REGRESAR A APARTADOS DE parser-md-code-block](#apartados-de-parser-md-code-block)

---

## Índice Docs de parser-md-code-block

- [Primeros pasos](#primeros-pasos-de-parser-md-code-block) -- Instalación y wiring de la extensión.
  - [Instalación](#instalación-de-parser-md-code-block) -- npm install + wiring de la extensión y sus componentes.
- [Uso](#uso-de-parser-md-code-block) -- La sintaxis de los 2 fences -- code-block y card-code-block.
  - [Bloque de código enriquecido](#bloque-de-código-enriquecido-de-parser-md-code-block) -- El fence ```code-block -- botón de copiar, resaltado de sintaxis, ruta opcional.
  - [Tarjeta de comando](#tarjeta-de-comando-de-parser-md-code-block) -- El fence ```card-code-block -- comando + resultado esperado + nota, con campos @nombre.
- [Ecosistema](#ecosistema-de-parser-md-code-block) -- Relación de @ngx-docs-markdown-kit/parser-md-code-block con el resto del kit -- qué depende de esta librería y por qué.
  - [Relación con el ecosistema](#relación-con-el-ecosistema-de-parser-md-code-block) -- Quién depende de @ngx-docs-markdown-kit/parser-md-code-block y por qué, dentro del kit.

---

## Primeros pasos de parser-md-code-block

[< Índice Docs de parser-md-code-block](#índice-docs-de-parser-md-code-block)

---

### Instalación de parser-md-code-block

[< Primeros pasos de parser-md-code-block](#primeros-pasos-de-parser-md-code-block)

---

```bash
npm install @ngx-docs-markdown-kit/parser-md-code-block
```

#### Registrar la extensión

```typescript
import { createParser } from '@ngx-docs-markdown-kit/parser-md';
import { codeBlockExtension } from '@ngx-docs-markdown-kit/parser-md-code-block';

const parser = createParser().use(codeBlockExtension());
```

#### Renderizar los segmentos

En el template, junto a los demás tipos de segmento (mismo `@switch` que usa `create-ngx-docs-site`
en `doc-segments.html`):

```html
@case ('code') {
  <ndmk-code-block [code]="segment.code" [lang]="segment.lang" [path]="segment.path" />
}
@case ('card-code-block') {
  <ndmk-card-code-block
    [descriptionHtml]="segment.descriptionHtml"
    [commandLang]="segment.commandLang"
    [command]="segment.command"
    [resultLabel]="segment.resultLabel"
    [resultLang]="segment.resultLang"
    [resultText]="segment.resultText"
    [noteLabel]="segment.noteLabel"
    [noteHtml]="segment.noteHtml"
  />
}
```

Ver [Bloque de código](#bloque-de-código-enriquecido-de-parser-md-code-block) y [Tarjeta de comando](#tarjeta-de-comando-de-parser-md-code-block)
para la sintaxis completa de cada fence.

#### Temas de código (opcional)

[`parser-md-code-block-themes`](https://www.npmjs.com/package/@ngx-docs-markdown-kit/parser-md-code-block-themes)
agrega paletas de color adicionales por lenguaje, seleccionables en runtime.

## Uso de parser-md-code-block

[< Índice Docs de parser-md-code-block](#índice-docs-de-parser-md-code-block)

---

### Bloque de código enriquecido de parser-md-code-block

[< Uso de parser-md-code-block](#uso-de-parser-md-code-block)

---

Un fence de Markdown SIN el `lang` reconocido (` ```bash ` normal, 3 backticks) nunca se enriquece
-- cae al render default de `marked` (sin botón de copiar, sin componente). Deliberadamente
selectivo: enriquecer TODO fence por default sorprende a cualquiera que solo quiera un bloque
normal. Antes de esta librería el comportamiento era el inverso (cualquier fence simple se
enriquecía automático) -- se invirtió a propósito.

` ```code-block ` (4 backticks) envuelve UN fence normal de 3 backticks con el código real -- así
el fence interior conserva el resaltado de sintaxis nativo de tu editor mientras lo escribís:

````code-block src/Program.cs
```csharp
Console.WriteLine("Hola");
```
````

`src/Program.cs` (segundo token del info string, opcional) es la ruta recomendada donde vive ese
código -- se muestra como parte de la etiqueta del bloque. El lenguaje para el resaltado de sintaxis
lo trae el fence INTERIOR (`csharp` en el ejemplo), no el exterior.

Produce un segmento `{ type: 'code', code, lang, path }` (`CodeSegment`), renderizado por
`ndmk-code-block`.

#### Por qué 4 backticks en el fence exterior

Un fence de Markdown de N backticks solo lo cierra OTRO fence de N backticks o más. Envolver con 4
backticks deja que el contenido traiga su propio fence de 3 backticks (el código real) sin que este
último cierre el exterior antes de tiempo -- el fence interior se lexea de nuevo
(`ctx.lex(token.text)`, en `code-block-extension.ts`) buscando el primer token de tipo `code`
dentro, y de ahí salen `code`/`lang`; `path` sale del resto del info string exterior.

#### Cómo funciona por dentro

`CodeBlockComponent` usa `highlight.js/lib/core` -- el build SIN gramáticas incluidas, para que el
bundle final no cargue lenguajes que la app anfitriona nunca usa. Cada lenguaje se registra en
`hljs` de forma perezosa, la primera vez que se necesita, y el registro se dedupea por FUNCIÓN real
(`registeredLanguages.get(lang) === register`), no por nombre de lenguaje -- si dos
`provideCodeBlockLanguages()` distintos (ej. un módulo lazy con su propio override) declaran el
mismo `lang` con una función `register` DISTINTA, no queda descartada en silencio para siempre: se
vuelve a registrar (`hljs.registerLanguage` soporta sobreescribir, gana la última llamada). Solo se
saltea el registro cuando es EXACTAMENTE la misma función ya registrada -- el caso común, evita
trabajo repetido en cada render.

El componente usa `ViewEncapsulation.None` -- el HTML que produce `hljs.highlight()` (spans
`hljs-keyword`/`hljs-string`/etc.) llega vía `[innerHTML]`, y los nodos insertados así no reciben el
atributo de scoping que Angular sí aplica al resto del template. Sin `ViewEncapsulation.None`, las
reglas de color del `.scss` del componente no alcanzarían ese HTML crudo.

El contenedor lleva la clase `not-prose` (convención de Tailwind Typography): si el sitio anfitrión
envuelve el markdown renderizado en `.prose`, sus selectores `:where(pre)`/`:where(code)` igual
alcanzarían este bloque por nombre de etiqueta -- pintando un segundo fondo encimado sobre el que ya
define `.code-block`, y agregando comillas invertidas literales antes/después del código.
`not-prose` es el escape hatch oficial de ese plugin para "este subárbol ya trae su propio estilo,
no lo toques"; es inofensiva si el sitio no usa Tailwind Typography (una clase sin ningún selector
que la use).

##### C#, un caso especial

`hljs` es un resaltador por expresiones regulares, no un compilador real -- su gramática de C# solo
cubre keywords/strings/comments/numbers/tipos primitivos. `enhance-csharp.ts` es una segunda pasada
que corre SOLO para `lang="csharp"`, sobre el HTML ya resaltado, y solo toca texto que `hljs` dejó
sin envolver en ningún `<span>`: colorea `PascalCase` como tipo (convención de C# para
clases/interfaces/records/DTOs) e `identificador(` como llamada a método. Vive en su propio archivo
-- no dentro de `CodeBlockComponent` -- porque tiene una razón de cambio distinta (ajustar la
detección de tipos/métodos de C#) a la del componente (layout/copiado/tema del bloque).

#### Temas de resaltado por lenguaje

El `data-theme` del contenedor (`modTheme()`, resuelto vía `CodeThemeService.themeFor(lang)`) forma
parte del selector CSS del tema junto con `data-lang`:
`.code-block[data-theme='<id>'][data-lang='<lang>']`. El id del tema entra al selector -- no solo un
booleano genérico -- porque `CodeThemeService` nunca descarga el `<link>` de un tema anterior al
elegir uno nuevo (ver `loadStylesheet()`): pueden quedar 2 o más hojas de estilo de temas distintas
cargadas al mismo tiempo (ej. `bash` en "A11y Dark", `csharp` en "An Old Hope"). Sin el id de tema en
el selector, esas hojas competirían por pintar el mismo bloque. Esta librería trae la infraestructura
completa (`CodeThemeService`, `CODE_THEME_CATALOG`) pero el catálogo vive vacío por default -- lo
llena [`parser-md-code-block-themes`](https://parser-md-code-block-themes.frugocorp.com), ver
[Ecosistema](#relación-con-el-ecosistema-de-parser-md-code-block).

#### Numeración de líneas

Desde `0.2.0`: 2 inputs opcionales, apagados por default (ningún consumidor existente se ve
afectado). `lineNumbersVisible` prende un gutter con los números reales de cada línea de `code()`;
`lineNumbersLabelStartLine` (default `1`) es el número de la PRIMERA línea mostrada -- las
siguientes suman 1 sola, sin necesidad de indicar dónde termina.

```html
<ndmk-code-block [code]="code" [lang]="lang" [lineNumbersVisible]="true" [lineNumbersLabelStartLine]="32" />
```

##### Por qué número y código viven en la MISMA fila, no en 2 columnas

La primera versión de esto armaba 2 elementos por separado -- una columna `<ol>` de números al
lado de `<pre>`, tratando de coincidir en altura vía CSS (mismo `padding`/`line-height` copiado a
mano en los 2 lugares). Se veía bien con código corto, pero un comentario multi-línea real
(`highlight.js` tokeniza un comentario de varias líneas como UN SOLO `<span>`, con los saltos de
línea reales adentro de ese span) desalineaba el gutter cada vez más a medida que aparecían más
líneas largas -- la CANTIDAD de líneas siempre daba bien (por eso no se veía en tests que solo
comparaban esa cantidad), el problema era de layout, no de conteo: 2 elementos independientes
nunca pueden garantizar la misma altura por línea sin duplicar sus constantes de CSS a mano para
siempre, en 2 archivos distintos.

El fix real: `splitHighlightedHtmlByLine()` corta el HTML YA resaltado por `\n`, pero llevando una
pila de los `<span>` abiertos -- al cortar, cierra todos los abiertos (HTML válido para esa línea)
y los vuelve a abrir al principio de la siguiente (mismo color/clase continúa), mismo mecanismo que
usan los plugins de numeración reales del ecosistema `highlight.js` (ej.
`highlightjs-line-numbers.js`) para este problema exacto. Con eso, cada línea se renderiza como su
propia fila (`<span class="code-block-row">`), con el número y el contenido como hijos DIRECTOS de
esa misma fila -- ya no son 2 layouts separados que puedan desincronizarse, es estructuralmente
imposible.

El botón de copiar sigue leyendo `code()` (el signal crudo), nunca el DOM -- los números nunca
pueden colarse en lo que se copia, sin ninguna lógica extra para excluirlos.

### Tarjeta de comando de parser-md-code-block

[< Uso de parser-md-code-block](#uso-de-parser-md-code-block)

---

` ```card-code-block ` (4 backticks) con campos nombrados `@campo`, cada uno en su propia línea,
hasta el siguiente `@campo` o el cierre del fence:

````card-code-block
@description
Corre las pruebas del proyecto con **npm**.

@command bash
npm test

@result<Resultado esperado> text
Test Files  1 passed (1)
     Tests  3 passed (3)

@note<Nota>
Si falla, revisa que hayas corrido `npm install` primero.
````

#### Campos soportados

Todos opcionales salvo `@command`:

| Campo | Contenido | Etiqueta visible |
| --- | --- | --- |
| `@description` | Markdown libre (párrafos hasta el próximo `@campo`) | Sin etiqueta, solo el texto |
| `@command [lang]` | Un fence de código (el comando real) | Sin etiqueta -- el lenguaje se muestra en la barra del bloque |
| `@result[<Etiqueta>] [lang]` | Un fence de código (la salida esperada) | `<Etiqueta>` si se da, si no "Resultado esperado" |
| `@note[<Etiqueta>]` | Markdown libre | `<Etiqueta>` si se da, si no ninguna (solo el ícono) |

`<Etiqueta>` es texto libre entre `<` y `>`, opcional en cualquier campo (aunque solo
`@result`/`@note` la muestran visualmente hoy). `lang` (para `@command`/`@result`) también es
opcional -- si se omite, se usa el lenguaje que ya trae el fence de código anidado de ese campo.

Produce un segmento `{ type: 'card-code-block', descriptionHtml, commandLang, command, resultLabel,
resultLang, resultText, noteLabel, noteHtml }` (`CardCodeBlockSegment`), renderizado por
`ndmk-card-code-block`.

#### Cómo funciona por dentro

`parseCardCodeBlock()` (en `code-block-extension.ts`) NO usa `ctx.lex()` para encontrar los campos
-- parsea el cuerpo del fence LÍNEA POR LÍNEA, buscando el patrón `@campo[<Etiqueta>] [lang]` al
principio de cada línea. Es deliberado: si usara el lexer de Markdown, `@command bash` seguido en la
línea siguiente por `npm install` (sin línea en blanco entre ambas) sería UN solo párrafo para
`marked` -- nada en el árbol de tokens distingue ahí "esto es la etiqueta del campo" de "esto es su
contenido". Partiendo por líneas con una regex explícita, cada sección sabe de antemano a qué campo
pertenece antes de decidir qué hacer con su cuerpo.

Una vez separadas las secciones, cada campo elige su tratamiento: `description`/`note` se vuelven a
lexear como Markdown (`ctx.render(ctx.lex(section.body))`) -- soportan **negrita**, enlaces, etc.
`command`/`result` se guardan RAW, sin pasar por el lexer -- así una línea como `npm install` nunca
se interpreta como prosa ni se le escapan caracteres que un comando real podría necesitar.

`CardCodeBlockComponent` no reimplementa el resaltado ni el botón de copiar -- compone el layout de
la tarjeta reusando 2 instancias internas de `ndmk-code-block` (ver
[Bloque de código](#bloque-de-código-enriquecido-de-parser-md-code-block)): una para `@command`, otra para `@result` con
`embedded="true"`, que suprime la etiqueta flotante y el tratamiento visual de "salida de ejemplo"
propios de ese componente (la tarjeta ya trae los suyos). El HTML de `description`/`note` llega
sanitizado con `DomSanitizer.bypassSecurityTrustHtml()` -- válido acá porque el HTML viene de
contenido Markdown ya procesado por `parser-md`, nunca de un usuario final directo, el mismo
criterio que aplicaría cualquier renderer de Markdown a HTML confiable.

#### Por qué existe además de `code-block`

`card-code-block` no es una variante visual de `code-block` -- es un formato distinto para un caso
de uso distinto: documentar un PASO ejecutable (qué hace, cómo se corre, qué esperar, qué hacer si
falla) como una unidad, en vez de un bloque de código suelto.

## Ecosistema de parser-md-code-block

[< Índice Docs de parser-md-code-block](#índice-docs-de-parser-md-code-block)

---

### Relación con el ecosistema de parser-md-code-block

[< Ecosistema de parser-md-code-block](#ecosistema-de-parser-md-code-block)

---

`@ngx-docs-markdown-kit/parser-md-code-block` es una EXTENSIÓN de
[`@ngx-docs-markdown-kit/parser-md`](https://parser-md.frugocorp.com) -- lo trae como peer
dependency y se registra con `.use(codeBlockExtension())`, sin tocar ni forkear el núcleo. `parser-md`
no sabe nada de `code-block`/`card-code-block`; simplemente expone el punto de extensión
(`buildSegment`) que esta librería implementa.

#### Quién depende de esta librería

- **[`@ngx-docs-markdown-kit/parser-md-code-block-themes`](https://parser-md-code-block-themes.frugocorp.com)**
  la trae como peer dependency real -- es un paquete de PALETAS DE COLOR (generadas desde los temas
  de `highlight.js`) para el resaltado de sintaxis que ya vive acá. Sin `parser-md-code-block`
  instalado, `parser-md-code-block-themes` no tiene nada que llenar: `CODE_THEME_CATALOG` (ver
  `code-theme-catalog.ts` en esta librería) está vacío por default a propósito, y ese otro paquete
  existe únicamente para poblarlo. La dirección de la dependencia es esta, no al revés -- esta
  librería nunca importa nada de `parser-md-code-block-themes`.
- **`create-ngx-docs-site`** (el CLI generador) la trae siempre en la plantilla de cualquier sitio
  nuevo, junto con `parser-md`, para que los fences ` ```code-block ` y ` ```card-code-block `
  funcionen de entrada en cualquier sitio generado.

#### Qué NO depende de esta librería

El selector de tema por lenguaje ("Mod") que expone `parser-md-code-block-themes` no reimplementa
un `<select>` propio -- usa `SearchableSelectComponent` de
[`@ngx-docs-markdown-kit/ui`](https://ui.frugocorp.com). Ese componente vivió en algún momento
DENTRO de esta librería, pero no tenía nada que ver con parsear Markdown ni resaltar código, así que
se extrajo a `ui` (librería sin ninguna dependencia de `parser-md`) -- ver la sección "Por qué
existe como librería separada" de
[su página de uso](https://ui.frugocorp.com/docs/usage/searchable-select) para el detalle completo.
`parser-md-code-block` en sí no depende de `ui` ni de ningún componente genérico: solo expone
`CodeBlockComponent`/`CardCodeBlockComponent` y la infraestructura de temas (`CodeThemeService`,
`CODE_THEME_CATALOG`, `CODE_BLOCK_LANGUAGES`) que otros paquetes consumen.

#### Por qué el catálogo de temas vive vacío acá

`CODE_THEME_CATALOG` (`InjectionToken<readonly CodeThemeCatalogEntry[]>`) y `CodeThemeService`
están completos y funcionales en esta librería sin instalar nada más -- el selector de "Mod" queda
disponible, simplemente sin ningún tema para elegir más allá de "Default". La razón de tenerlos acá
y no en `parser-md-code-block-themes` es que son INFRAESTRUCTURA (persistencia en `localStorage`,
carga de `<link>` de CSS, resolución de tema por lenguaje) genérica, reusable por cualquier catálogo
de temas futuro -- no algo específico de los ~80 temas concretos que trae ese paquete. Instalar
`parser-md-code-block-themes` es estrictamente opcional: sin él, todo sigue funcionando, solo que
sin paletas alternativas.

#### Por qué `code-block-languages.ts` es un archivo de datos puro

`CODE_BLOCK_LANGUAGES` (los 8 lenguajes registrados por default: `csharp`, `bash`, `powershell`,
`json`, `typescript`, `javascript`, `css`, `scss`) vive en un archivo sin ningún import relativo a
propósito -- `scripts/generate-code-themes.mjs`, en la raíz del monorepo, lo importa DIRECTO con el
soporte nativo de TypeScript de Node (sin bundler) para saber para qué lenguajes generar CSS al
armar el catálogo de `parser-md-code-block-themes`. Ese modo de carga no resuelve una cadena de
imports locales como sí lo hace el build real de Angular -- por eso el enhancer de C#
(`enhance-csharp.ts`, la segunda pasada que colorea PascalCase/llamadas a método que la gramática
regex de `hljs` no cubre) NO se referencia desde ese archivo de datos: vive wireado directo en
`CodeBlockComponent`, que ese script nunca carga.

## Parser MD Code Block de parser-md-code-block

[REGRESAR A APARTADOS DE parser-md-code-block](#apartados-de-parser-md-code-block)

---

[GitHub](https://github.com/frugocorp/ngx-docs-markdown-kit) | [Sitio](https://parser-md-code-block.frugocorp.com) | [FrugoCorp](https://frugocorp.com)

`parser-md-code-block` extiende `parser-md` con 2 fences enriquecidos --
` ```code-block ` y ` ```card-code-block ` -- y los componentes de Angular
(`CodeBlockComponent`, `CardCodeBlockComponent`) que los renderizan con resaltado de sintaxis real.

### Por que un fence aparte del Markdown normal

Un fence simple (3 backticks) nunca se enriquece a proposito -- solo el fence de 4 backticks activa
el resaltado y las tarjetas de comando. `card-code-block` parsea sus campos (`@description`/
`@command`/`@result`/`@note`) linea por linea en vez de con el lexer de Markdown, porque un
`@command` seguido de codigo sin linea en blanco es indistinguible para `marked`.

### Que trae de base

Resaltado de sintaxis real (no aproximado) para los lenguajes soportados, mas la infraestructura de
temas que consume `parser-md-code-block-themes` como extension opcional -- si no esta instalado, el
bloque de codigo sigue funcionando con su tema por default. Desde `0.2.0`, un gutter de numeros de
linea opcional (`lineNumbersVisible`/`lineNumbersLabelStartLine`), que
[`@ngx-docs-markdown-kit/parser-md-file-embed`](https://parser-md-file-embed.frugocorp.com) usa
para mostrar fragmentos reales de un archivo con su numeracion original -- ver
[Bloque de codigo enriquecido](#bloque-de-código-enriquecido-de-parser-md-code-block).
<!-- parser-md-code-block:doc_body_end -->
<!-- parser-md-code-block:doc_end -->

---
_Source: https://npm.io/package/@ngx-docs-markdown-kit/parser-md-code-block · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
