El conocimiento es el nuevo dinero.
Aprender es la nueva manera en la que inviertes
Acceso Cursos

Renderizar componentes Angular en Markdown

Este ejemplo demuestra el renderizado de markdown en angular y también cómo renderizar componentes angulares en markdown.

· 2 min de lectura
Renderizar componentes Angular en Markdown

Primero, configuraremos el componente <markdown-render> para renderizar archivos .md. Y luego veremos cómo renderizar componentes angulares.

Renderizador Markdown


Instalar las dependencias necesarias:

npm i highlight.js marked marked-highlight

Paso 1: Crear markdown-renderer/highlight-code-block.ts


Esta función se utilizará para resaltar el código en nuestro archivo markdown

import highlightJs from 'highlight.js';

export function highlightCodeBlock(code: string, language: string | undefined) {
  if (language) {
    return highlightJs.highlight(code, {
      language,
    }).value;
  }
  return code;
}

Paso 2: Crear markdown-renderer/transform-markdown.ts


Esta función se utilizará para convertir markdown a html.

import { marked } from 'marked';
import { markedHighlight } from 'marked-highlight';
import { highlightCodeBlock } from './highlight-code-block';

marked.use(markedHighlight({ highlight: highlightCodeBlock }));
export const markdownToHtml = (content: string) => {
  return marked(content);
};

Paso 3: Crear markdown-renderer/markdown.service.ts


Este servicio se utilizará en el componente para leer el archivo .md desde una ubicación local o externa y luego convertirlo a html.

import { HttpClient } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { map } from 'rxjs';
import { markdownToHtml } from './transform-markdown';
@Injectable({
  providedIn: 'root',
})
export class MarkdownService {
  private httpClient = inject(HttpClient);
  htmlContent(src: string) {
    return this.httpClient.get(src, { responseType: 'text' }).pipe(
      map((markdownContent) => {
        return markdownToHtml(markdownContent);
      })
    );
  }
}

Paso 4: Crear markdown-renderer/markdown-renderer.ts


Finalmente, este será el componente que podremos usar para renderizar archivos markdown.

import { Component, ElementRef, effect, inject, input } from '@angular/core';
import { MarkdownService } from './markdown.service';
import { take } from 'rxjs';
import highlightJs from 'highlight.js';

@Component({
  selector: 'markdown-renderer',
  template: 'Loading document...',
  standalone: true,
})
export class MarkdownRendererComponent {
  src = input.required<string>();
  textContent = '';
  private _elementRef = inject<ElementRef>(ElementRef);
  private markdownService = inject(MarkdownService);
  constructor() {
    effect(() => {
      const src = this.src();
      this.setDataFromSrc(src);
    });
  }
  setDataFromSrc(src: string) {
    this.markdownService
      .htmlContent(src)
      .pipe(take(1))
      .subscribe((htmlContent) => {
        this.updateDocument(htmlContent as string);
      });
  }
  updateDocument(rawHTML: string) {
    this._elementRef.nativeElement.innerHTML = rawHTML;
    this.textContent = this._elementRef.nativeElement.textContent;
    highlightJs.highlightAll();
  }
}

Paso 5: Proporcionar HTTP

bootstrapApplication(App, {
  providers: [
    provideHttpClient(withFetch())
  ],
});

Paso 6: Uso


Ahora, siempre que queramos renderizar markdown, simplemente usaremos <markdown-renderer>:

import { Component } from '@angular/core';
import { MarkdownRendererComponent } from './markdown-renderer/markdown-renderer';
@Component({
  selector: 'article',
  standalone: true,
  template: `<markdown-renderer src="/assets/article.md"></markdown-renderer>`,
  imports: [MarkdownRendererComponent],
})
export class ArticleComponent {}

Componentes Angular en Markdown


Instale las dependencias necesarias:

npm i @angular/elements

Paso 1: Crear custom-elements.service.ts


Este servicio se utilizará para convertir los componentes angulares en elementos personalizados, de modo que podamos utilizar fácilmente los componentes angulares en el archivo .md.

import { inject, Injectable, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { SubscribeComponent } from './components/subscribe';
import { CounterComponent } from './components/counter';
@Injectable({ providedIn: 'root' })
export class CustomElementsService {
  private _injector = inject(Injector);

  setupCustomElements() {
    const subscribeElement = createCustomElement(SubscribeComponent, {
      injector: this._injector,
    });
    customElements.define('subscribe-component', subscribeElement);
    const counterElement = createCustomElement(CounterComponent, {
      injector: this._injector,
    });
    customElements.define('counter-component', counterElement);
  }
}

Paso 2: Llamar a setupCustomElements a través de APP_INITIALIZER


Como queremos que los elementos personalizados estén presentes desde la inicialización, utilizaremos APP_INITIALIZER.

bootstrapApplication(App, {
  providers: [
    provideHttpClient(withFetch()),
    {
      provide: APP_INITIALIZER,
      useFactory: initializeCustomElements,
      multi: true,
      deps: [CustomElementsService],
    },
  ],
});

Paso 3: Uso


Por último, sólo tiene que utilizar su elemento personalizado en el archivo .md para que se muestre el componente angular, como se muestra a continuación:

<subscribe-component></subscribe-component>
<counter-component></counter-component>

Código

Espero que puedas llevar a la práctica lo leído. Nos vemos en el siguiente blog.

Fuente