feat : 6 astra improve it
This commit is contained in:
+22
-39
@@ -1,3 +1,5 @@
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
|
||||
import { highlightTextSegments, type TextHighlight } from "@/lib/guides/highlights";
|
||||
|
||||
const ALLOWED_TAGS = new Set([
|
||||
@@ -17,10 +19,6 @@ const ALLOWED_TAGS = new Set([
|
||||
"ul",
|
||||
]);
|
||||
|
||||
const BLOCKED_CONTENT = /<(script|style|iframe|object|embed|svg|math|template)\b[^>]*>[\s\S]*?<\/\1\s*>/gi;
|
||||
const HTML_COMMENT = /<!--[\s\S]*?-->/g;
|
||||
const TAG = /<\/?([a-zA-Z][a-zA-Z0-9-]*)([^>]*)>/g;
|
||||
const ATTRIBUTE = /([a-zA-Z_:][a-zA-Z0-9_:.-]*)\s*=\s*("[^"]*"|'[^']*'|[^\s"'=<>`]+)/g;
|
||||
const HEX_COLOR = /^#[0-9a-fA-F]{6}$/;
|
||||
const RGB_COLOR = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i;
|
||||
|
||||
@@ -67,44 +65,29 @@ function escapeHtml(value: string): string {
|
||||
return escapeAttribute(value).replaceAll("'", "'");
|
||||
}
|
||||
|
||||
function attributeValue(rawAttributes: string, name: string): string {
|
||||
for (const match of rawAttributes.matchAll(ATTRIBUTE)) {
|
||||
if (match[1].toLowerCase() === name) {
|
||||
return match[2].replace(/^['"]|['"]$/g, "");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
export function sanitizeRichTextHtml(value: string): string {
|
||||
return value
|
||||
.replace(BLOCKED_CONTENT, "")
|
||||
.replace(HTML_COMMENT, "")
|
||||
.replace(TAG, (tag, rawName: string, rawAttributes: string) => {
|
||||
const name = rawName.toLowerCase();
|
||||
if (!ALLOWED_TAGS.has(name)) return "";
|
||||
if (tag.startsWith("</")) return name === "br" ? "" : `</${name}>`;
|
||||
if (name === "br") return "<br>";
|
||||
|
||||
if (name === "a") {
|
||||
const href = sanitizeRichTextUrl(attributeValue(rawAttributes, "href"));
|
||||
return href
|
||||
? `<a href="${escapeAttribute(href)}" target="_blank" rel="noopener noreferrer">`
|
||||
: "<a>";
|
||||
}
|
||||
|
||||
if (name === "span") {
|
||||
const style = attributeValue(rawAttributes, "style");
|
||||
return sanitizeHtml(value, {
|
||||
allowedTags: [...ALLOWED_TAGS],
|
||||
allowedAttributes: { a: ["href", "target", "rel"], span: ["style"] },
|
||||
allowedSchemes: ["http", "https", "mailto"],
|
||||
allowProtocolRelative: false,
|
||||
nonTextTags: ["script", "style", "textarea", "option", "iframe", "object", "embed", "svg", "math", "template"],
|
||||
transformTags: {
|
||||
a: (_name, attributes): sanitizeHtml.Tag => {
|
||||
const href = sanitizeRichTextUrl(attributes.href ?? "");
|
||||
return { tagName: "a", attribs: href
|
||||
? { href, target: "_blank", rel: "noopener noreferrer" } : {} };
|
||||
},
|
||||
span: (_name, attributes): sanitizeHtml.Tag => {
|
||||
const color = normalizeRichTextColor(
|
||||
style.match(/(?:^|;)\s*color\s*:\s*([^;]+?)\s*(?:;|$)/i)?.[1] ?? "",
|
||||
(attributes.style ?? "").match(/(?:^|;)\s*color\s*:\s*([^;]+?)\s*(?:;|$)/i)?.[1] ?? "",
|
||||
);
|
||||
return color
|
||||
? `<span style="color: ${color}">`
|
||||
: "<span>";
|
||||
}
|
||||
|
||||
return `<${name}>`;
|
||||
});
|
||||
return { tagName: "span", attribs: color ? { style: `color: ${color}` } : {} };
|
||||
},
|
||||
},
|
||||
// Colors have already been normalized against our strict hex/RGB parser.
|
||||
parseStyleAttributes: false,
|
||||
}).replace(/<br\s*\/>/g, "<br>");
|
||||
}
|
||||
|
||||
function isRichTextHtml(value: string): boolean {
|
||||
|
||||
Reference in New Issue
Block a user