mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
fix: Handle GitLab Flavored Markdown (#11930)
* fix: Handle GitLab Flavored Markdown * PR feedback * Harden HTML comment stripping against overlapping patterns Loop the replacement until stable to avoid CodeQL's incomplete multi-character sanitization alert — a single pass could leave `<!--` residue for inputs like `<!<!-- x -->-- -->`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -277,6 +277,62 @@ export class GitLabUtils {
|
||||
return palette[projectId % 7];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes GitLab-flavored markdown to standard markdown compatible with
|
||||
* our editor. Strips or converts GitLab-specific syntax that would otherwise
|
||||
* render as raw text in previews.
|
||||
*
|
||||
* Note: This is for display purposes only and is not a security boundary.
|
||||
* Do not rely on this to sanitize untrusted HTML.
|
||||
*
|
||||
* @param text - the markdown text to sanitize.
|
||||
* @returns the sanitized text, or null if input is null/undefined.
|
||||
*/
|
||||
public static sanitizeGitLabMarkdown(
|
||||
text: string | null | undefined
|
||||
): string | null {
|
||||
if (!text) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Strip HTML comments repeatedly in case of overlapping patterns like
|
||||
// `<!<!-- x -->-- -->` that would leave `<!--` after a single pass.
|
||||
let result = text;
|
||||
let prev: string;
|
||||
do {
|
||||
prev = result;
|
||||
result = result.replace(/<!--[\s\S]*?-->/g, "");
|
||||
} while (result !== prev);
|
||||
|
||||
return (
|
||||
result
|
||||
// YAML front matter
|
||||
.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "")
|
||||
// Collapsible sections: extract inner content
|
||||
.replace(
|
||||
/<details>\s*<summary>([\s\S]*?)<\/summary>([\s\S]*?)<\/details>/gi,
|
||||
"**$1**\n$2"
|
||||
)
|
||||
// TOC markers
|
||||
.replace(/\[\[_TOC_\]\]/g, "")
|
||||
.replace(/^\[TOC\]$/gm, "")
|
||||
// Inline diffs
|
||||
.replace(/\{\+([\s\S]*?)\+\}/g, "$1")
|
||||
.replace(/\[-([\s\S]*?)-\]/g, "~~$1~~")
|
||||
// Multiline blockquotes
|
||||
.replace(/^>>>\s*$/gm, "")
|
||||
// Footnote definitions
|
||||
.replace(/^\[\^[^\]]+\]:\s+.*$/gm, "")
|
||||
// Footnote references
|
||||
.replace(/\[\^([^\]]+)\]/g, "")
|
||||
// Include directives
|
||||
.replace(/^::include\{[^}]*\}$/gm, "")
|
||||
// Clean up excessive blank lines left by removals
|
||||
.replace(/\n{3,}/g, "\n\n")
|
||||
.trim() || null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color associated with a given visibility level.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user