claude-code-gitea-action/src/github/utils/sanitizer.ts
claude (ops) 32685a740f
Some checks failed
Test Custom Executables / test-custom-executables (push) Has been cancelled
CI / test (push) Has been cancelled
CI / prettier (push) Has been cancelled
CI / typecheck (push) Has been cancelled
Sync Base Action to claude-code-base-action / Sync base-action to claude-code-base-action repository (push) Has been cancelled
Test Claude Code Action / test-inline-prompt (push) Has been cancelled
Test Claude Code Action / test-prompt-file (push) Has been cancelled
Test Claude Env Feature / test-claude-env-with-comments (push) Has been cancelled
Test MCP Servers / test-mcp-integration (push) Has been cancelled
Test MCP Servers / test-mcp-config-flag (push) Has been cancelled
Test Settings Feature / test-settings-inline-allow (push) Has been cancelled
Test Settings Feature / test-settings-inline-deny (push) Has been cancelled
Test Settings Feature / test-settings-file-allow (push) Has been cancelled
Test Settings Feature / test-settings-file-deny (push) Has been cancelled
Forgejo-patched claude-code-gitea-action (View-job URL uses per-repo run index)
Fork of markwylde/claude-code-gitea-action@b744372 (v1.0.21) with the
'View job' link fixed to use GITHUB_RUN_NUMBER (per-repo index) instead of
GITHUB_RUN_ID (global id), because Forgejo routes run pages by per-repo index.
See VENDOR.txt.
2026-07-01 06:42:55 +00:00

65 lines
2.3 KiB
TypeScript

export function stripInvisibleCharacters(content: string): string {
content = content.replace(/[\u200B\u200C\u200D\uFEFF]/g, "");
content = content.replace(
/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g,
"",
);
content = content.replace(/\u00AD/g, "");
content = content.replace(/[\u202A-\u202E\u2066-\u2069]/g, "");
return content;
}
export function stripMarkdownImageAltText(content: string): string {
return content.replace(/!\[[^\]]*\]\(/g, "![](");
}
export function stripMarkdownLinkTitles(content: string): string {
content = content.replace(/(\[[^\]]*\]\([^)]+)\s+"[^"]*"/g, "$1");
content = content.replace(/(\[[^\]]*\]\([^)]+)\s+'[^']*'/g, "$1");
return content;
}
export function stripHiddenAttributes(content: string): string {
content = content.replace(/\salt\s*=\s*["'][^"']*["']/gi, "");
content = content.replace(/\salt\s*=\s*[^\s>]+/gi, "");
content = content.replace(/\stitle\s*=\s*["'][^"']*["']/gi, "");
content = content.replace(/\stitle\s*=\s*[^\s>]+/gi, "");
content = content.replace(/\saria-label\s*=\s*["'][^"']*["']/gi, "");
content = content.replace(/\saria-label\s*=\s*[^\s>]+/gi, "");
content = content.replace(/\sdata-[a-zA-Z0-9-]+\s*=\s*["'][^"']*["']/gi, "");
content = content.replace(/\sdata-[a-zA-Z0-9-]+\s*=\s*[^\s>]+/gi, "");
content = content.replace(/\splaceholder\s*=\s*["'][^"']*["']/gi, "");
content = content.replace(/\splaceholder\s*=\s*[^\s>]+/gi, "");
return content;
}
export function normalizeHtmlEntities(content: string): string {
content = content.replace(/&#(\d+);/g, (_, dec) => {
const num = parseInt(dec, 10);
if (num >= 32 && num <= 126) {
return String.fromCharCode(num);
}
return "";
});
content = content.replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => {
const num = parseInt(hex, 16);
if (num >= 32 && num <= 126) {
return String.fromCharCode(num);
}
return "";
});
return content;
}
export function sanitizeContent(content: string): string {
content = stripHtmlComments(content);
content = stripInvisibleCharacters(content);
content = stripMarkdownImageAltText(content);
content = stripMarkdownLinkTitles(content);
content = stripHiddenAttributes(content);
content = normalizeHtmlEntities(content);
return content;
}
export const stripHtmlComments = (content: string) =>
content.replace(/<!--[\s\S]*?-->/g, "");