angular/adev/shared-docs/pipeline/guides/extensions/docs-code/docs-code-multifile.mts
Joey Perrott 5f1c08d75f build: migrate adev shared-docs package to use ts_project (#61193)
Migrate the build rules for shared docs to use ts_project

PR Close #61193
2025-05-09 16:30:05 +00:00

75 lines
2.2 KiB
TypeScript

/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {Tokens, Token, TokenizerThis, RendererThis} from 'marked';
import {JSDOM} from 'jsdom';
/** Marked token for a multifile custom docs element. */
export interface DocsCodeMultifileToken extends Tokens.Generic {
type: 'docs-code-multifile';
// The example path used for linking to Stackblitz or rendering a preview
path: string | undefined;
// The raw nested Markdown of <docs-code> examples in the multifile example
panes: string;
// The DocsCodeToken of the nested <docs-code> examples
paneTokens: Token[];
// True if we should display preview
preview: boolean;
}
// Capture group 1: all attributes on the opening tag
// Capture group 2: all content between the open and close tags
const multiFileCodeRule = /^\s*<docs-code-multifile(.*?)>(.*?)<\/docs-code-multifile>/s;
const pathRule = /path="([^"]*)"/;
const previewRule = /preview/;
export const docsCodeMultifileExtension = {
name: 'docs-code-multifile',
level: 'block' as const,
start(src: string) {
return src.match(/^\s*<docs-code-multifile/)?.index;
},
tokenizer(this: TokenizerThis, src: string): DocsCodeMultifileToken | undefined {
const match = multiFileCodeRule.exec(src);
if (match) {
const attr = match[1].trim();
const path = pathRule.exec(attr);
const preview = previewRule.exec(attr) ? true : false;
const token: DocsCodeMultifileToken = {
type: 'docs-code-multifile',
raw: match[0],
path: path?.[1],
panes: match[2].trim(),
paneTokens: [],
preview: preview,
};
this.lexer.blockTokens(token.panes, token.paneTokens);
return token;
}
return undefined;
},
renderer(this: RendererThis, token: DocsCodeMultifileToken) {
const el = JSDOM.fragment(`
<div class="docs-code-multifile">
${this.parser.parse(token.paneTokens)}
</div>
`).firstElementChild!;
if (token.path) {
el.setAttribute('path', token.path);
}
if (token.preview) {
el.setAttribute('preview', `${token.preview}`);
}
return el.outerHTML;
},
};