mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
75 lines
2.2 KiB
TypeScript
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;
|
|
},
|
|
};
|