Pages
A `.md` file as an Angular component template, with `templateMD`.
A page is an ordinary Angular component whose template is the Markdown file
beside it — declared the way templateUrl declares an .html file.
button.page.ts the component: its fields are what the Markdown binds against
button.page.md the template
button.page.css its stylesheet, which reaches the rendered MarkdownThe shape
import { Component } from '@angular/core';
import templateMD from './button.page.md';
@Component({
selector: 'app-button-page',
templateMD,
styleUrl: './button.page.css',
components: [AppButton],
})
export class ButtonPage {
count = 0;
bump(): void { this.count++; }
}Three things follow from it being an ordinary component:
The class is the binding context.
{{ count }}andbump()are those very members — there is no context object to pass or keep in sync.styleUrlreaches the Markdown. See Page styles.It routes, injects and tests like a component, because it is one.
How templateMD works
Angular's compiler accepts only what it knows: a @Component argument must be a
literal object, its values must be statically evaluable, and an unknown key is
dropped before anything reaches the runtime. A Markdown string imported at build
time is none of those.
So templateMD is a build-time transform, not metadata Angular ever sees.
Before the compiler reads the file, Blasdoc rewrites it into the page you would
otherwise write by hand:
@Component({ selector: 'app-button-page', template: '', styleUrl: './button.page.css' })
export class ButtonPage {
#blasdocPage = blasdocPageInit(this, { templateMD, components: [AppButton] });
count = 0;
}Every edit keeps its line, so a stack trace still lands where you wrote the
code. Runtime-first is untouched: templateMD is still the Markdown string,
parsed when the page renders. Installing it is one line — see
Build integration.
Without a build step
templateMD needs the transform. Where that is not welcome, blasdocPage()
gives the same page as a base class — plain TypeScript, stock ng build, no
editor caveat:
import { blasdocPage } from '@blasdoc/angular';
@Component({
selector: 'app-button-page',
template: '',
styleUrl: './button.page.css',
})
export class ButtonPage extends blasdocPage({
templateMD,
components: [AppButton],
}) {
count = 0;
bump(): void { this.count++; }
}From injected services
Extend BlasdocPage directly when the configuration cannot be a constant:
import { BlasdocPage } from '@blasdoc/angular';
@Component({ selector: 'app-remote-page', template: '' })
export class RemotePage extends BlasdocPage {
private readonly content = inject(ContentService);
readonly templateMD = this.content.markdown();
readonly components = [AppButton];
}Reading a page back
Two functions work on a page written any of the three ways:
import { blasdocPageDiagnostics, blasdocPageHeadings } from '@blasdoc/angular';
blasdocPageDiagnostics(page); // every problem, parse and runtime
blasdocPageHeadings(page); // the outline, from the IR the page parsedThe table of contents on the right of this page is blasdocPageHeadings — read
from the same IR the renderer used, so it cannot describe a document that is not
there.