2024-07-23 16:50:12 +00:00
|
|
|
/*!
|
|
|
|
|
* @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 {TokenizerThis, RendererThis} from 'marked';
|
2025-05-06 20:59:30 +00:00
|
|
|
import {CodeToken, formatCode} from './format/index.mjs';
|
|
|
|
|
import {FileType, removeEslintComments} from './sanitizers/eslint.mjs';
|
|
|
|
|
import {loadWorkspaceRelativeFile} from '../../utils.mjs';
|
2024-07-23 16:50:12 +00:00
|
|
|
|
|
|
|
|
/** Marked token for a custom docs element. */
|
|
|
|
|
export interface DocsCodeToken extends CodeToken {
|
|
|
|
|
type: 'docs-code';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Capture group 1: all attributes on the opening tag
|
|
|
|
|
// Capture group 2: all content between the open and close tags
|
2024-08-10 12:50:27 +00:00
|
|
|
const singleFileCodeRule =
|
|
|
|
|
/^\s*<docs-code((?:\s+[\w-]+(?:="[^"]*"|='[^']*'|=[^\s>]*)?)*)\s*(?:\/>|>(.*?)<\/docs-code>)/s;
|
2024-07-23 16:50:12 +00:00
|
|
|
|
|
|
|
|
const pathRule = /path="([^"]*)"/;
|
2025-06-22 23:19:35 +00:00
|
|
|
const classRule = /class="([^"]*)"/;
|
2024-07-23 16:50:12 +00:00
|
|
|
const headerRule = /header="([^"]*)"/;
|
|
|
|
|
const linenumsRule = /linenums/;
|
|
|
|
|
const highlightRule = /highlight="([^"]*)"/;
|
|
|
|
|
const diffRule = /diff="([^"]*)"/;
|
|
|
|
|
const languageRule = /language="([^"]*)"/;
|
|
|
|
|
const visibleLinesRule = /visibleLines="([^"]*)"/;
|
|
|
|
|
const visibleRegionRule = /visibleRegion="([^"]*)"/;
|
|
|
|
|
const previewRule = /preview/;
|
|
|
|
|
|
|
|
|
|
export const docsCodeExtension = {
|
|
|
|
|
name: 'docs-code',
|
|
|
|
|
level: 'block' as const,
|
|
|
|
|
start(src: string) {
|
|
|
|
|
return src.match(/^<docs-code\s/)?.index;
|
|
|
|
|
},
|
|
|
|
|
tokenizer(this: TokenizerThis, src: string): DocsCodeToken | undefined {
|
2024-08-10 12:50:27 +00:00
|
|
|
const match = singleFileCodeRule.exec(src);
|
2024-07-23 16:50:12 +00:00
|
|
|
if (match) {
|
|
|
|
|
const attr = match[1].trim();
|
|
|
|
|
|
|
|
|
|
const path = pathRule.exec(attr);
|
|
|
|
|
const header = headerRule.exec(attr);
|
|
|
|
|
const linenums = linenumsRule.exec(attr);
|
|
|
|
|
const highlight = highlightRule.exec(attr);
|
|
|
|
|
const diff = diffRule.exec(attr);
|
|
|
|
|
const language = languageRule.exec(attr);
|
|
|
|
|
const visibleLines = visibleLinesRule.exec(attr);
|
|
|
|
|
const visibleRegion = visibleRegionRule.exec(attr);
|
|
|
|
|
const preview = previewRule.exec(attr) ? true : false;
|
2025-06-22 23:19:35 +00:00
|
|
|
const classes = classRule.exec(attr);
|
2024-07-23 16:50:12 +00:00
|
|
|
|
2024-08-10 12:50:27 +00:00
|
|
|
let code = match[2]?.trim() ?? '';
|
2024-07-23 16:50:12 +00:00
|
|
|
if (path && path[1]) {
|
|
|
|
|
code = loadWorkspaceRelativeFile(path[1]);
|
|
|
|
|
// Remove ESLint Comments
|
|
|
|
|
const fileType: FileType | undefined = path[1]?.split('.').pop() as FileType;
|
|
|
|
|
code = removeEslintComments(code, fileType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const token: DocsCodeToken = {
|
|
|
|
|
type: 'docs-code',
|
|
|
|
|
raw: match[0],
|
|
|
|
|
code: code,
|
|
|
|
|
path: path?.[1],
|
|
|
|
|
header: header?.[1],
|
|
|
|
|
linenums: !!linenums,
|
|
|
|
|
highlight: highlight?.[1],
|
|
|
|
|
diff: diff?.[1],
|
|
|
|
|
language: language?.[1],
|
|
|
|
|
visibleLines: visibleLines?.[1],
|
|
|
|
|
visibleRegion: visibleRegion?.[1],
|
|
|
|
|
preview: preview,
|
2025-06-22 23:19:35 +00:00
|
|
|
classes: classes?.[1]?.split(' '),
|
2024-07-23 16:50:12 +00:00
|
|
|
};
|
|
|
|
|
return token;
|
|
|
|
|
}
|
|
|
|
|
return undefined;
|
|
|
|
|
},
|
|
|
|
|
renderer(this: RendererThis, token: DocsCodeToken) {
|
|
|
|
|
return formatCode(token);
|
|
|
|
|
},
|
|
|
|
|
};
|