Page Processors
Page Processor is a really powerful feature of NgDoc. It allows you to replace HTML elements with Angular components. This is how NgDoc renders different components inside your documentation like demos, playgrounds, icons, etc. Using this API you can create your own components that will make your documentation even more awesome 🎉.
How it works
When NgDoc builder renders your markdown templates to HTML, it leaves special markers in the output HTML. These markers are then replaced by Angular components via Page Processors on the client side. But you can create your own markers by using Markdown or HTML syntax inside your markdown templates, or just use existing HTML elements that you want to improve.
Creating a Page Processor
Page Processor is a simple object that contains CSS selector, component class and function that extracts data from the HTML element and converts it to the component input.
Let's create a simple Page Processor that will replace all <img>
elements with ImageViewerComponent
, first we need to create the ImageViewerComponent
:
import { ChangeDetectionStrategy , Component , Input } from '@angular/core';
import { NgDocTooltipDirective } from '@ng-doc/ui-kit';
@Component ({
selector: 'image-viewer',
standalone: true,
imports: [NgDocTooltipDirective ],
template: `<img [src]="src" [alt]="alt" [ngDocTooltip]="title" [delay ]="0" />`,
styles: [
`
:host {
display: flex;
justify-content: center;
padding: var(--ng-doc-base-gutter);
border: 1px solid var(--ng-doc-base-2);
border-radius: var(--ng-doc-base-gutter);
overflow: hidden;
}
img {
width: 100%;
max-height: 100px;
transition : transform 0.2s ease-in-out;
}
img:hover {
transform: scale(1.1);
}
`,
],
changeDetection: ChangeDetectionStrategy .OnPush,
})
export class ImageViewerComponent {
@Input ()
src: string = '';
@Input ()
alt: string = '';
@Input ()
title?: string;
}
As you can see, it's a simple component that takes src
, alt
and title
as an inputs, renders the image and adds a simple zoom-in animation on hover with a tooltip that shows the image title.
Now we need to create a Page Processor that will replace all <img>
elements with our component:
import { NgDocPageProcessor } from '@ng-doc/app/interfaces';
import { ImageViewerComponent } from './image-viewer.component';
export const imageProcessor : NgDocPageProcessor <ImageViewerComponent> = {
component: ImageViewerComponent,
selector: 'img',
extractOptions: (element: Element) => ({
inputs: {
src: element.getAttribute('src') || '',
alt: element.getAttribute('alt') || '',
title: element.getAttribute('title') || undefined,
},
}),
};
Inside the extractOptions
method we extract the src
, alt
and title
attributes from the <img>
element and define them as inputs for our component.
Now we need to register our Page Processor, you can do it in the ng-doc.page.ts
file, if you want to enable it only for one page, or inside your main.ts
if you want to enable it for all pages:
Be careful when you register your Page Processors,
function uses
providePageProcessor multi: true
, so if you register your Page Processor in theng-doc.page.ts
file and in themain.ts
file, all processors from themain.ts
file will be ignored.
import { NgDocPage } from '@ng-doc/core';
import { providePageProcessor } from '@ng-doc/app';
import { imageProcessor } from './image.processor';
const MyPage: NgDocPage = {
title: `MyPage`,
mdFile: './index.md',
providers: [providePageProcessor (imageProcessor )],
};
export default MyPage;
After that if you use <img>
elements using HTML or Markdown syntax, they will be replaced with the ImageViewerComponent
:
![alt text](assets/images/ng-doc.svg 'Image title')
Wrapping HTML elements
Sometimes you want to wrap HTML elements with your component, for example, you want to wrap all <table>
elements with your custom component that will add some styles to the table. You can do it by playing with nodeToReplace
function and content
property of the PageProcessor
, but first let's create a CustomTableComponent
:
import { ChangeDetectionStrategy , Component , ViewEncapsulation } from '@angular/core';
@Component ({
selector: 'custom-table',
standalone: true,
template: `<ng-content ></ng-content >`,
styles: [
`
custom-table table {
border: 1px solid red;
}
`,
],
changeDetection: ChangeDetectionStrategy .OnPush,
encapsulation: ViewEncapsulation .None,
})
export class CustomTableComponent {}
Now we need to create a Page Processor that will wrap all <table>
elements with our component:
import { Injector , Renderer2 } from '@angular/core';
import { NgDocPageProcessor } from '@ng-doc/app/interfaces';
import { CustomTableComponent } from './custom-table.component';
export const tableProcessor: NgDocPageProcessor <CustomTableComponent> = {
component: CustomTableComponent,
selector: 'table',
nodeToReplace: (element: Element, injector: Injector ) => {
// Get the renderer from the injector
const renderer: Renderer2 = injector.get(Renderer2 );
// Create an anchor element to insert the `CustomTableComponent` in the correct place.
const anchor: Element = renderer.createElement('div');
// Insert the anchor before the table and return it
return element.parentNode?.insertBefore(anchor, element) ?? element;
},
extractOptions: (element: Element) => ({
// Provide the table element as the `ng-content ` of the component.
content: [[element]],
}),
};
After that when you register your processor all <table>
elements will be wrapped with our CustomTableComponent
:
| Syntax | Description |
| --------- | ----------- |
| Header | Title |
| Paragraph | Text |
Syntax | Description |
---|---|
Header | Title |
Paragraph | Text |