From 046501fd33b5e043f676c3ad3a2b247dfdff697c Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Fri, 21 Nov 2025 17:25:47 +0000 Subject: [PATCH] refactor(docs-infra): make docs-alert an inline token Migrate docs-alert to be inline instead of block, this ensures that the content is placed within a

tag as expected. This is important for ensuring that the iconography is placed correctly within the wrapper div generated for the alert. Additionally, we refactor the matcher code to be more efficient, running with fewer loops. --- .../shared/marked/extensions/docs-alert.mts | 71 ++++++++----------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/adev/shared-docs/pipeline/shared/marked/extensions/docs-alert.mts b/adev/shared-docs/pipeline/shared/marked/extensions/docs-alert.mts index 6e77553f072..790db0ced37 100644 --- a/adev/shared-docs/pipeline/shared/marked/extensions/docs-alert.mts +++ b/adev/shared-docs/pipeline/shared/marked/extensions/docs-alert.mts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {RendererThis, Token, TokenizerThis, Tokens} from 'marked'; +import {RendererThis, Token, TokenizerAndRendererExtension, TokenizerThis, Tokens} from 'marked'; /** Enum of all available alert severities. */ export enum AlertSeverityLevel { @@ -24,54 +24,41 @@ export enum AlertSeverityLevel { /** Token for docs-alerts */ interface DocsAlertToken extends Tokens.Generic { type: 'docs-alert'; - body: string; - severityLevel: string; - tokens: Token[]; -} - -interface DocsAlert { - alert: RegExpExecArray | null; severityLevel: string; } -export const docsAlertExtension = { +/** Alert severity level keys. */ +const alertSeverityLevels = Object.keys(AlertSeverityLevel).map((lvl) => `${lvl}`); +const tokenMatcher = new RegExp( + `^\s*(${alertSeverityLevels.join('|')}): (.*?)(?:\n{2,}|\s*$)`, + 's', +); + +export const docsAlertExtension: TokenizerAndRendererExtension = { name: 'docs-alert', - level: 'block' as const, + level: 'inline', tokenizer(this: TokenizerThis, src: string): DocsAlertToken | undefined { - let match: DocsAlert | undefined; - for (const key of Object.keys(AlertSeverityLevel)) { - // Capture group 1: all alert text content after the severity level - const rule = new RegExp('^s*' + key + ': (.*?)(?:\n{2,}|\s*$)', 's'); - const possibleMatch = rule.exec(src); - - if (possibleMatch?.[1]) { - match = { - severityLevel: key, - alert: possibleMatch, - }; - } + const execMatch = tokenMatcher.exec(src); + if (execMatch === null) { + return undefined; } - if (match?.alert) { - const token: DocsAlertToken = { - type: 'docs-alert', - raw: match.alert[0], - body: match.alert[1].trim(), - severityLevel: match.severityLevel.toLowerCase(), - tokens: [], - }; - - token.body = `**${AlertSeverityLevel[match.severityLevel as keyof typeof AlertSeverityLevel]}:** ${token.body}`; - this.lexer.blockTokens(token.body, token.tokens); - return token; - } - return undefined; + const severityLevelKey = execMatch[1] as keyof typeof AlertSeverityLevel; + const severityLevelValue = AlertSeverityLevel[severityLevelKey]; + return { + type: 'docs-alert', + raw: execMatch[0], + severityLevel: severityLevelKey, + tokens: this.lexer.inlineTokens(`**${severityLevelValue}:** ${execMatch[2].trim()}`, []), + }; }, - renderer(this: RendererThis, token: DocsAlertToken) { - return ` -

- ${this.parser.parse(token.tokens)} -
- `; + renderer(this: RendererThis, token: Tokens.Generic) { + if (token.tokens) { + return ` +
+

${this.parser.parseInline(token.tokens)}

+
+ `; + } }, };