npm.io
0.1.1 • Published 13h ago

@ngx-docs-markdown-kit/parser-md-file-embed

Licence
MIT
Version
0.1.1
Deps
2
Size
94 kB
Vulns
0
Weekly
0

parser-md-file-embed

parser-md-file-embed

version node npm

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.2.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.2.0
  • @ngx-docs-markdown-kit/parser-md-file-embed: ^0.1.0
  • @ngx-docs-markdown-kit/parser-md-converter: ^0.2.0
  • @ngx-docs-markdown-kit/ui: ^0.1.0
  • rxjs: ~7.8.0
  • tslib: ^2.3.0

Apartados de parser-md-file-embed

  • Docs -- Documentación de @ngx-docs-markdown-kit/parser-md-file-embed -- embeber el contenido real de un archivo de public/ dentro de un code-block, siempre sincronizado.
  • Parser MD File Embed -- Embebe el contenido real de un archivo de public/ dentro de un code-block, siempre sincronizado, para sitios @ngx-docs-markdown-kit.

Docs de parser-md-file-embed

REGRESAR A APARTADOS DE parser-md-file-embed


Índice Docs de parser-md-file-embed

  • Primeros pasos -- Instalación y wiring de la extensión.
    • Instalación -- npm install + wiring de la extensión, el componente, y el lector de disco opcional para SSR.
  • Uso -- Sintaxis del fence, rangos de líneas, y cómo se detecta el lenguaje para resaltar.
    • [El fence ```file-embed](#el-fence-file-embed-de-parser-md-file-embed) -- Embebe el contenido REAL de un archivo de public/ dentro de un code-block -- siempre sincronizado, nunca una copia pegada a mano.
    • Rangos de líneas -- Uno o varios fragmentos disjuntos de un mismo archivo, y el sentinel 0 para "desde/hasta donde el archivo tenga texto real".
    • Detección de lenguaje -- Cómo se decide con qué lenguaje resaltar un archivo embebido -- la tabla por extensión, y cuándo gana el "lang" explícito.
  • Ecosistema -- De qué depende @ngx-docs-markdown-kit/parser-md-file-embed, y por qué nunca reimplementa lo que ya hace parser-md-code-block.
    • Relación con el ecosistema -- De qué depende @ngx-docs-markdown-kit/parser-md-file-embed, quién la consume, y por qué nunca depende de highlight.js.

Primeros pasos de parser-md-file-embed

< Índice Docs de parser-md-file-embed


Instalación de parser-md-file-embed

< Primeros pasos de parser-md-file-embed


npm install @ngx-docs-markdown-kit/parser-md-file-embed

Trae @ngx-docs-markdown-kit/parser-md-code-block (^0.2.0 o superior) como dependencia real (siempre instalada junto con este paquete) -- todo el resaltado/tema/copiado real se delega en <ndmk-code-block> de ese paquete, este nunca duplica esa lógica.

Registrar la extensión
import { createParser } from '@ngx-docs-markdown-kit/parser-md';
import { fileEmbedExtension } from '@ngx-docs-markdown-kit/parser-md-file-embed';

const parser = createParser().use(fileEmbedExtension());
Renderizar el segmento

En el template, junto a los demás tipos de segmento:

@case ('file-embed') {
  <ndmk-file-embed
    [path]="segment.path"
    [lang]="segment.lang"
    [ranges]="segment.ranges"
    [lineNumberLabel]="segment.lineNumberLabel"
  />
}
El lector de disco para SSR/prerender (opcional, recomendado)

FileEmbedComponent pide el archivo real por HttpClient -- funciona sin nada más, pero durante el prerender de build (antes de que exista un servidor real escuchando) un self-fetch por HTTP puede colgarse hasta un timeout. FILE_EMBED_DISK_READER evita eso: si está provisto, se usa disco directo en el servidor; si no, cae solo al HttpClient de siempre.

// app.config.server.ts -- SOLO se importa desde acá, nunca desde main.ts (entrada de navegador),
// así "node:fs" nunca llega al bundle del navegador.
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { FILE_EMBED_DISK_READER } from '@ngx-docs-markdown-kit/parser-md-file-embed';

function readFileEmbedFromDisk(publicPath: string): string {
  return readFileSync(resolve(process.cwd(), 'public', publicPath), 'utf-8');
}

const serverConfig: ApplicationConfig = {
  providers: [
    // ...
    { provide: FILE_EMBED_DISK_READER, useValue: readFileEmbedFromDisk },
  ],
};

Ver [El fence ```file-embed](#el-fence-file-embed-de-parser-md-file-embed) para la sintaxis completa, y Rangos de líneas para el detalle de line_ranges.

Uso de parser-md-file-embed

< Índice Docs de parser-md-file-embed


El fence ```file-embed de parser-md-file-embed

< Uso de parser-md-file-embed


Un fence normal (3 backticks) con un lang especial (file-embed), reconocido vía buildSegment() -- cero cambios al núcleo de parser-md. A diferencia de escribir el código a mano dentro del fence (lo que hacen ```code-block/```content-card), acá el fence solo trae un PUNTERO (path, más algunos campos opcionales) -- el contenido real se pide en tiempo de render, siempre el archivo actual, nunca una copia que se desactualiza cuando el archivo real cambia.

Por qué solo archivos de public/

Un navegador solo puede pedir lo que el sitio realmente sirve -- nunca puede leer un archivo arbitrario de tu repositorio, aunque el archivo exista en el mismo proyecto. Angular solo sirve como asset estático lo que está bajo public/ (mismo motivo por el que ContentService, en cualquier sitio de create-ngx-docs-site, pide el cuerpo de cada página por HTTP en vez de leerlo del filesystem del cliente). Por eso path: siempre es relativo a public/ del propio sitio -- path: templates/user-service.cs referencia public/templates/user-service.cs, nunca un archivo de otra parte del repo.

Ejemplo en vivo
path: templates/user-service.cs
line_ranges: 26-30

Esto embebe las líneas 26 a 30 de user-service.cs (un archivo real de public/templates/ de este mismo sitio, ver Rangos de líneas para más ejemplos) tal cual están en disco ahora mismo -- si ese archivo cambia, esta misma página muestra el cambio en el próximo build, sin tocar este .md.

Referencia completa de campos

Todos son opcionales salvo path -- el ejemplo de arriba ya muestra la sintaxis completa del fence en sí (```file-embed seguido de estos mismos campos, uno por línea):

path: templates/user-service.cs
lang: csharp
line_ranges: 26-30
line_number_label: true
Campo Obligatorio Qué hace
path Ruta relativa a public/ del sitio. Único campo obligatorio -- sin él, el fence queda sin reclamar.
lang No Solo se usa si la tabla por extensión (ver Detección de lenguaje) no reconoce el archivo por su nombre.
line_ranges No Uno o más rangos inicio-fin separados por coma (ver Rangos de líneas). Sin este campo, embebe el archivo completo.
line_number_label No (default true) Gutter con los números de línea reales del archivo. line_number_label: false lo apaga.
Cómo funciona por dentro

Dos piezas con una sola responsabilidad cada una, separadas a propósito:

  • fileEmbedExtension() (file-embed-extension.ts) parsea el fence con parseKeyValueLines (reusado de parser-md, el mismo parser que usan image/content-card) y arma un segmento con el puntero SIN RESOLVER -- nunca lee el archivo real. Esto no es una limitación, es deliberado: esta función corre tanto en el servidor (prerender) como en el navegador (navegación cliente-a-cliente entre páginas ya hidratadas), y un navegador no tiene forma de leer un archivo arbitrario -- solo lo que ya está resuelto en el segmento puede viajar de forma segura a ambos lados.
  • FileEmbedComponent es quien de verdad pide el archivo (por HttpClient, con un lector de disco opcional para SSR/prerender -- ver Instalación), corta el/los rango/s pedido/s (ver Rangos de líneas), y arma un <ndmk-code-block> por rango -- nunca reimplementa resaltado, tema, gutter de números, ni botón de copiar: todo eso es 100% trabajo de @ngx-docs-markdown-kit/parser-md-code-block, este paquete ni siquiera depende de highlight.js. Ver Relación con el ecosistema para el detalle completo de esa frontera de responsabilidad.

El texto nunca se reformatea/reindenta -- se corta byte a byte, tal cual está en el archivo real. La única "inteligencia" de este paquete es leer el puntero y cortar el texto; todo lo visual (color, tema, números de línea, copiar al portapapeles) vive en el componente que reusa.

Rangos de líneas de parser-md-file-embed

< Uso de parser-md-file-embed


line_ranges acepta uno o más pares inicio-fin, separados por coma -- cada par es un rango ATÓMICO (nunca 2 arrays paralelos que se puedan desincronizar al reordenar/insertar uno).

Un solo rango
path: templates/user-service.cs
line_ranges: 32-57
Varios rangos disjuntos en un mismo embed

Útil para mostrar, por ejemplo, 2 trabajos de un mismo pipeline sin el trabajo intermedio que no aporta al ejemplo:

path: templates/deploy.yml
line_ranges: 8-16, 33-45

Cada rango se renderiza como su propio <ndmk-code-block>, con un separador visual () entre ellos -- nunca se concatenan en un solo bloque de texto (cada uno mantiene su propio botón de copiar, con SOLO el código de ese rango).

Sintaxis
path: templates/archivo.ts
line_ranges: 1-5, 45-63, 95-98
El sentinel 0

Sin line_ranges, el default es 0-0 -- el archivo completo, pero recortado de líneas en blanco al principio/final (no necesariamente la línea física 1 ni la última línea física). 0 en cualquiera de los 2 lados de un rango individual significa lo mismo:

  • 0 en el lado IZQUIERDO (start) resuelve a la primera línea REAL con texto del archivo.
  • 0 en el lado DERECHO (end) resuelve a la última línea REAL con texto del archivo.

Esto importa porque muchos archivos reales tienen una línea en blanco al final (la mayoría de editores la agregan solo) -- sin este sentinel, embeber "todo el archivo" mostraría esa línea vacía colgando al final, sin ningún valor real.

path: templates/app-config.json

Ese ejemplo de arriba usa el default (0-0) -- muestra app-config.json completo, sin importar si termina o no con una línea en blanco.

Un rango desactualizado nunca rompe la página

Si el archivo real encoge (alguien borra líneas) y un rango queda fuera de límites, se recorta al total real de líneas en vez de fallar -- una documentación con un line_ranges desactualizado sigue mostrando algo razonable, nunca una página rota. Nada se reformatea nunca: el texto sale byte a byte, tal cual está en el archivo real -- ver El fence file-embed para por qué esto es una garantía deliberada, no un detalle de implementación.

Detección de lenguaje de parser-md-file-embed

< Uso de parser-md-file-embed


El lenguaje que se le pasa a <ndmk-code-block> (para el resaltado de sintaxis) se decide en este orden -- el primero que da una respuesta gana:

  1. Tabla por extensión/nombre de archivo (interna, ~50 entradas) -- deriva del path, que es obligatorio y siempre está actualizado. Gana SIEMPRE que tenga una entrada.
  2. lang: explícito en el fence -- solo se usa si la tabla no reconoce la extensión.
  3. Auto-detección de highlight.js -- si ninguno de los 2 anteriores dio un lenguaje, o el lenguaje elegido no está registrado hoy (ver parser-md-code-block), cae ahí -- sigue coloreando, solo que adivinando en vez de con la gramática exacta.
Por qué la tabla gana sobre lang: explícito, no al revés

Si lang: explícito ganara siempre, cambiar path: Foo.cs a path: Foo.json sin acordarse de actualizar lang: csharp dejaría un lenguaje incorrecto pegado, en silencio. Como la tabla se deriva del campo OBLIGATORIO (path), nunca puede quedar desactualizada -- lang: explícito existe solo para el caso real donde la tabla no tiene una entrada (una extensión rara, o un archivo sin extensión que no está en la lista de nombres exactos).

path: templates/app-config.json
line_ranges: 8-16

El ejemplo de arriba nunca declaró lang: -- app-config.json se reconoce solo por su extensión.

Nunca depende de highlight.js

Este paquete no importa highlight.js en ningún momento -- la tabla es solo texto ("cs" -> "csharp", strings planos), nunca una gramática real. Si un lenguaje de la tabla no está REGISTRADO hoy en parser-md-code-block (ver su propio catálogo, DEFAULT_CODE_BLOCK_LANGUAGES), el string igual se le pasa a <ndmk-code-block>, que cae solo a auto-detección -- este paquete nunca necesita saber cuáles gramáticas están cargadas. Ver Relación con el ecosistema para el porqué de este límite de responsabilidad.

La tabla completa
Extensión Lenguaje Extensión Lenguaje
.cs csharp .py python
.ts / .tsx typescript .rb ruby
.js / .jsx / .mjs / .cjs javascript .php php
.json json .pl perl
.html / .htm xml .lua lua
.xml / .svg / .vue xml .java java
.css css .kt / .kts kotlin
.scss scss .scala scala
.less less .go go
.sh / .bash / .zsh bash .rs rust
.ps1 powershell .c / .h c
.yml / .yaml yaml .cpp / .cc / .hpp cpp
.toml / .ini / .cfg ini .fs / .fsx fsharp
.sql sql .vb vbnet
.md / .markdown markdown .dart dart
.txt plaintext .swift swift
.graphql / .gql graphql .m objectivec
.diff / .patch diff .r r
.properties properties .hs haskell
.tex latex .ex / .exs elixir
.groovy groovy .erl erlang
.nginx / .conf nginx .clj clojure
Dockerfile (nombre exacto) dockerfile Makefile (nombre exacto) makefile

Dockerfile/Makefile se reconocen por NOMBRE de archivo exacto (sin extensión), no por extensión -- el resto de la tabla mapea por extensión, tomando siempre la ÚLTIMA (archivo.conf.template usa la extensión .template, no .conf -- una limitación conocida del diseño simple de esta tabla, cubrible con lang: explícito si hace falta).

Ecosistema de parser-md-file-embed

< Índice Docs de parser-md-file-embed


Relación con el ecosistema de parser-md-file-embed

< Ecosistema de parser-md-file-embed


@ngx-docs-markdown-kit/parser-md-file-embed es una extensión de parser-md -- no funciona sola, necesita registrarse con .use(fileEmbedExtension()) sobre un parser ya creado con createParser(). Ver Instalación para el wiring completo.

De qué depende
  • @ngx-docs-markdown-kit/parser-md (peer) -- el motor que extiende. De ahí sale parseKeyValueLines (reusado para parsear el fence) y el propio mecanismo de extensión (buildSegment).
  • @ngx-docs-markdown-kit/parser-md-code-block (dependencia REAL, no peer, ^0.2.0 o superior) -- declarada en ng-package.json bajo allowedNonPeerDependencies. FileEmbedComponent compone <ndmk-code-block> directo, uno por rango -- resaltado, tema, gutter de números de línea, botón de copiar, TODO eso es de ese paquete. parser-md-code-block se instala SIEMPRE junto con parser-md-file-embed, sin importar si el sitio expone o no el fence ```code-block propio de ese paquete.

Nunca depende de highlight.js -- ni directa ni transitivamente en el sentido de necesitar saber algo de él. La tabla de detección de lenguaje (ver Detección de lenguaje) es solo texto plano; el resaltado real lo hace parser-md-code-block por su cuenta, con su propia copia de highlight.js/lib/core.

Por qué una responsabilidad, no dos

Hasta una versión temprana de este paquete, FileEmbedComponent armaba su PROPIO gutter de números de línea al lado de <ndmk-code-block> (2 elementos por separado, tratando de coincidir en altura por CSS) -- un comentario multi-línea real (un solo <span> de highlight.js con varios saltos de línea reales adentro) desalineaba ese 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 los 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.

El fix real fue mover la numeración ADENTRO de parser-md-code-block (lineNumbersVisible/lineNumbersLabelStartLine, ver su propio CHANGELOG) -- número y código de una misma línea ahora viven en la MISMA fila, no en 2 layouts separados. Esto dejó a parser-md-file-embed con una sola responsabilidad real: conseguir el texto del archivo y cortar el rango pedido. Todo lo visual es 100% de parser-md-code-block, sin excepción.

Quién la usa hoy

create-ngx-docs-site (el CLI generador) la trae por default en la plantilla de cualquier sitio nuevo -- se puede omitir con el flag --no-file-embed. Ninguna otra librería del ecosistema depende de parser-md-file-embed.

Alcance conocido

path: solo puede referenciar archivos que YA están dentro de public/ del propio sitio -- nunca otro lugar del repositorio (ver [El fence ```file-embed](#el-fence-file-embed-de-parser-md-file-embed) para el porqué). Si el archivo real que querés documentar vive en otra carpeta de tu proyecto (código fuente de una librería, por ejemplo), tenés que copiarlo/mantenerlo también dentro de public/ -- este paquete no trae ningún mecanismo de build que lo copie automáticamente desde otra parte del repo.

Parser MD File Embed de parser-md-file-embed

REGRESAR A APARTADOS DE parser-md-file-embed


GitHub | Sitio | FrugoCorp

parser-md-file-embed extiende parser-md con un fence ```file-embed que incrusta el contenido REAL de un archivo de public/ (o uno o varios rangos de líneas) dentro de un code-block -- siempre sincronizado con el archivo real, nunca una copia pegada a mano que se desactualiza cada vez que ese archivo cambia.

Por qué esto, en vez de copiar y pegar

Documentar un Dockerfile/docker-compose.yml/config real a mano en un bloque de código es una copia que se desincroniza la primera vez que alguien toca el archivo original y se olvida de actualizar la documentación -- un problema real, no hipotético. Con file-embed, la documentación siempre muestra el archivo tal cual está HOY, sin ningún paso manual.

Qué trae de base

Resaltado de sintaxis real, gutter de números de línea, tema de color, y botón de copiar -- TODO eso reusado de parser-md-code-block, nunca reimplementado acá (este paquete no depende de highlight.js en ningún momento). Su única responsabilidad real: conseguir el texto del archivo real y cortar el rango pedido.

Keywords