UNPKG

@nuxtjs/mdc

Version:
56 lines (55 loc) 1.49 kB
export const unsafeLinkPrefix = [ "javascript:", "data:text/html", "vbscript:", "data:text/javascript", "data:text/vbscript", "data:text/css", "data:text/plain", "data:text/xml" ]; function isAnchorLinkAllowed(value) { const decodedUrl = decodeURIComponent(value); const urlSanitized = decodedUrl.replace(/&#x([0-9a-f]+);?/gi, "").replace(/&#(\d+);?/g, "").replace(/&[a-z]+;?/gi, ""); try { const url = new URL(urlSanitized, "http://example.com"); if (url.origin === "http://example.com") { return true; } if (unsafeLinkPrefix.some((prefix) => url.protocol.toLowerCase().startsWith(prefix))) { return false; } } catch { return false; } return true; } export const validateProp = (attribute, value) => { if (attribute.startsWith("on")) { return false; } if (attribute === "href" || attribute === "src") { return isAnchorLinkAllowed(value); } return true; }; export const validateProps = (type, props) => { if (!props) { return {}; } props = Object.fromEntries( Object.entries(props).filter(([name, value]) => { const isValid = validateProp(name, value); if (!isValid) { console.warn(`[@nuxtjs/mdc] removing unsafe attribute: ${name}="${value}"`); } return isValid; }) ); if (type === "pre") { if (typeof props.highlights === "string") { props.highlights = props.highlights.split(" ").map((i) => Number.parseInt(i)); } } return props; };