url-sanitizer 5.2.0 → 5.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../bundle_wo_dompurify/mjs/constant.js", "../bundle_wo_dompurify/mjs/common.js", "../bundle_wo_dompurify/mjs/dompurify.js", "../bundle_wo_dompurify/mjs/regexp.js", "../bundle_wo_dompurify/lib/file/text-chars.json", "../bundle_wo_dompurify/mjs/text-chars.js", "../bundle_wo_dompurify/mjs/utility.js", "../bundle_wo_dompurify/mjs/filter.js", "../bundle_wo_dompurify/lib/iana/uri-schemes.json", "../bundle_wo_dompurify/mjs/scheme.js", "../bundle_wo_dompurify/mjs/sanitize.js", "../bundle_wo_dompurify/index.js"],
4
- "sourcesContent": ["/**\n * constant.js\n */\n\n/**\n * The total number of 8-bit byte values (0x00\u20130xFF).\n * @type {number}\n */\nexport const BYTE_RANGE = 256;\n\n/**\n * Chunk size (8KB) used when processing byte arrays to avoid stack overflow.\n * @type {number}\n */\nexport const CHUNK_SIZE = 8 * 1024;\n\n/**\n * Decimal radix used for numeric string conversion.\n * @type {number}\n */\nexport const DECI = 10;\n\n/**\n * Hexadecimal radix used for numeric string conversion.\n * @type {number}\n */\nexport const HEX = 16;\n\n/**\n * Maximum allowed Blob size (16MB).\n * @type {number}\n */\nexport const MAX_BLOB_SIZE = 16 * 1024 * 1024;\n\n/**\n * Maximum recursion depth allowed for nested parsing.\n * @type {number}\n */\nexport const MAX_NEST = 16;\n\n/**\n * Maximum URL length (64KB).\n * @type {number}\n */\nexport const MAX_URL_LENGTH = 64 * 1024;\n\n/**\n * Length used for truncating string.\n * @type {number}\n */\nexport const TRUNCATE_LENGTH = 64;\n\n/**\n * Start index used to extract the type name from Object.prototype.toString().\n * (e.g. removes \"[object \" prefix)\n * @type {number}\n */\nexport const TYPE_FROM = 8;\n\n/**\n * End index used to extract the type name from Object.prototype.toString().\n * (e.g. removes trailing \"]\")\n * @type {number}\n */\nexport const TYPE_TO = -1;\n\n/**\n * The dummy base URL.\n * @type {string}\n */\nexport const DUMMY_BASE = 'http://dummy.local';\n", "/**\n * common.js\n */\n\n/* shared */\nimport { TYPE_FROM, TYPE_TO } from './constant.js';\n\n/**\n * Gets the type of the given object.\n * Returns the object class name (e.g., \"String\", \"Array\", \"Null\", \"Undefined\").\n * @param {unknown} o - The object to check.\n * @returns {string} The specific type of the object.\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * Checks if the given value is a string.\n * @param {unknown} o - The value to check.\n * @returns {boolean} True if the value is a string, false otherwise.\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n\n/**\n * Debug logger.\n * @param {string} message - The message to output.\n * @param {Error} [error] - The caught error object, if any.\n * @returns {void}\n */\nexport const logDebug = (message, error) => {\n console.warn(`[URLSanitizer Debug] ${message}`, error);\n};\n", "/**\n * dompurify.js (for wo-dompurify build)\n */\n\n/* constants */\nconst PROPERTIES = Object.freeze([\n 'addHook',\n 'removeHook',\n 'removeAllHooks',\n 'setConfig'\n]);\n\nconst hookQueue = [];\nexport const domPurify = new Proxy({}, {\n get(target, prop, receiver) {\n const purifier = globalThis.DOMPurify || globalThis.window?.DOMPurify;\n if (purifier) {\n if (hookQueue.length) {\n for (const { prop: p, args } of hookQueue) {\n if (typeof purifier[p] === 'function') {\n purifier[p](...args);\n }\n }\n hookQueue.length = 0;\n }\n const value = purifier[prop];\n return typeof value === 'function' ? value.bind(purifier) : value;\n }\n return (...args) => {\n if (PROPERTIES.includes(prop)) {\n hookQueue.push({ prop, args });\n return receiver;\n }\n throw new Error('DOMPurify is not available. Ensure DOMPurify is exposed globally (e.g., window.DOMPurify).');\n };\n }\n});\n", "/**\n * regexp.js\n */\n\n/**\n * Matches HTML-encoded ampersands.\n * @type {RegExp}\n */\nexport const REG_AMP = /&amp;/gi;\n\n/**\n * Matches ampersand that may begin an HTML entity reference.\n * @type {RegExp}\n */\nexport const REG_AMP_ENC = /&(?=[#a-z0-9])(?![a-z0-9]+=)/i;\n\n/**\n * Matches and captures the charset parameter in a media type string.\n * @type {RegExp}\n */\nexport const REG_CHARSET = /^charset\\s*=\\s*([\"']?)(?<name>[\\w:-]+)\\1$/;\n\n/**\n * Matches a trailing empty fragment identifier (#).\n * @type {RegExp}\n */\nexport const REG_HASH = /#$/;\n\n/**\n * Matches MIME types that contain DOM-parsable content (HTML, XML, SVG).\n * @type {RegExp}\n */\nexport const REG_MIME_DOM =\n /^(?:application\\/(?:[\\w.-]+\\+)?xml|image\\/svg\\+xml|text\\/(?:html|xml))(?:\\s*;\\s*|$)/i;\n\n/**\n * Matches general text MIME types.\n * @type {RegExp}\n */\nexport const REG_MIME_TEXT = /^text\\/[\\w#&.;+-]+/i;\n\n/**\n * Matches non-ASCII character.\n * @type {RegExp}\n */\nexport const REG_NON_ASCII = /\\P{ASCII}/u;\n\n/**\n * Matches numeric character references (hex or decimal).\n * @type {RegExp}\n */\nexport const REG_NUM_REF = /&#(x0*[\\dA-F]{1,2}|0*\\d{1,3});?/gi;\n\n/**\n * Matches one or more consecutive percent-encoded sequences (%20, %E3%81%82).\n * @type {RegExp}\n */\nexport const REG_PCT_ENC = /(?:%[\\dA-F]{2})+/gi;\n\n/**\n * Matches a trailing empty query string (?), ensuring it is not part of a hash.\n * @type {RegExp}\n */\nexport const REG_QUERY = /^((?:[^#%]|%(?!23))*)\\?$/;\n\n/**\n * Validates a string against standard IANA URI scheme syntax.\n * @type {RegExp}\n */\nexport const REG_SCHEME = /^[a-z][\\da-z+.-]*$/;\n\n/**\n * Matches web custom schemes (`web+`) or application-specific schemes (`ext+`).\n * - `web+` schemes comply with the HTML Standard.\n * - `ext+` schemes comply with RFC 3986 but disallow `+` in the suffix.\n * @type {RegExp}\n */\nexport const REG_SCHEME_EXT = /^(?:web\\+[a-z]+|ext\\+[a-z][\\da-z.-]*)$/;\n\n/**\n * Matches executable script schemes (javascript or vbscript).\n * @type {RegExp}\n */\nexport const REG_SCRIPT = /^(?:java|vb)script$/i;\n\n/**\n * Matches script-executing or data-fetching schemes.\n * @type {RegExp}\n */\nexport const REG_SCRIPT_OR_BLOB = /^(?:(?:java|vb)script|blob)$/i;\n\n/**\n * Matches HTML-sensitive characters and their encoded variants.\n * @type {RegExp}\n */\nexport const REG_TAG_QUOT =\n /[\"'<>]|%(?:22|27|3C|3E)|&(?:apos|lt|gt|quot|#0*(?:34|39|60|62)|#x0*(?:22|27|3C|3E));/i;\n\n/**\n * Matches a percent-encoded character (%XX).\n * @type {RegExp}\n */\nexport const REG_URL_ENC = /^%[\\dA-F]{2}$/i;\n\n/**\n * Matches invalid relative URL patterns.\n * @type {RegExp}\n */\nexport const REG_VERIFY_RELATIVE = /^(?:\\/{2,}|\\\\|[a-z][a-z\\d+\\-.]*:[^/])/i;\n", "[9,10,13,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]\n", "/**\n * text-chars.js\n */\n\n/* shared */\nimport textChars from '../lib/file/text-chars.json' with { type: 'json' };\nimport { BYTE_RANGE, HEX } from './constant.js';\n\n/**\n * A set of valid text character codes.\n * @type {Set<number>}\n */\nexport const TEXT_CHAR_CODES = new Set(textChars);\n\n/**\n * A map of Windows-1252 codes and their corresponding Unicode code points.\n * @type {Map<number, number>}\n */\nexport const WINDOWS1252_TO_UNICODE = new Map([\n [128, 0x20ac],\n [130, 0x201a],\n [131, 0x0192],\n [132, 0x201e],\n [133, 0x2026],\n [134, 0x2020],\n [135, 0x2021],\n [136, 0x02c6],\n [137, 0x2030],\n [138, 0x0160],\n [139, 0x2039],\n [140, 0x0152],\n [142, 0x017d],\n [145, 0x2018],\n [146, 0x2019],\n [147, 0x201c],\n [148, 0x201d],\n [149, 0x2022],\n [150, 0x2013],\n [151, 0x2014],\n [152, 0x02dc],\n [153, 0x2122],\n [154, 0x0161],\n [155, 0x203a],\n [156, 0x0153],\n [158, 0x017e],\n [159, 0x0178]\n]);\n\n/**\n * Generates hexadecimal escape strings for non-text codes.\n * @private\n * @returns {Map<number, string>} The map of non-text codes and hexadicimal escape strings.\n */\nconst generateNonTextCharCodes = () => {\n const charCodes = new Map();\n for (let i = 0; i < BYTE_RANGE; i++) {\n if (!TEXT_CHAR_CODES.has(i) && !WINDOWS1252_TO_UNICODE.has(i)) {\n charCodes.set(i, `\\\\x${i.toString(HEX).padStart(2, '0').toUpperCase()}`);\n }\n }\n return charCodes;\n};\n\n/**\n * A map of non-text codes and their hexadecimal escape strings.\n * @type {Map<number, string>}\n */\nexport const NON_TEXT_CHAR_CODES = generateNonTextCharCodes();\n", "/**\n * utility.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\n\n/* constants */\nimport {\n BYTE_RANGE,\n CHUNK_SIZE,\n DECI,\n HEX,\n MAX_NEST,\n MAX_URL_LENGTH,\n TRUNCATE_LENGTH\n} from './constant.js';\nimport {\n REG_AMP,\n REG_HASH,\n REG_NON_ASCII,\n REG_NUM_REF,\n REG_PCT_ENC,\n REG_QUERY,\n REG_URL_ENC\n} from './regexp.js';\nimport {\n NON_TEXT_CHAR_CODES,\n TEXT_CHAR_CODES,\n WINDOWS1252_TO_UNICODE\n} from './text-chars.js';\nconst [ENC_AMP, ENC_NUM, ENC_LT, ENC_GT, ENC_QUOT, ENC_APOS] = [\n '&',\n '#',\n '<',\n '>',\n '\"',\n \"'\"\n].map(ch => `%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\nconst ESCAPE_MAP = {\n [ENC_AMP]: `${ENC_AMP}amp;`,\n [ENC_LT]: `${ENC_AMP}lt;`,\n [ENC_GT]: `${ENC_AMP}gt;`,\n [ENC_QUOT]: `${ENC_AMP}quot;`,\n [ENC_APOS]: `${ENC_AMP}${ENC_NUM}39;`\n};\nconst HEX_TABLE = Array.from(\n { length: BYTE_RANGE },\n (_, i) => `%${i.toString(HEX).padStart(2, '0').toUpperCase()}`\n);\nconst IS_NODE = globalThis.process?.versions?.node !== undefined;\nconst NON_TEXT_PATTERN = `[${[...NON_TEXT_CHAR_CODES.values()].join('')}]`;\nconst REG_NON_TEXT = new RegExp(NON_TEXT_PATTERN);\nconst REG_NON_TEXT_G = new RegExp(NON_TEXT_PATTERN, 'g');\nconst SHARED_BUFFER = new Uint8Array(MAX_URL_LENGTH);\n\n/* typedef */\n/**\n * The extracted Data URL components.\n * @typedef {object} DataURLComponents\n * @property {string} data - The actual data part of the Data URL.\n * @property {boolean} isBase64 - Indicates whether the data is base64-encoded.\n * @property {string} mediaType - The MIME type of the data.\n * @property {string[]} mediaTypes - The array of parsed media types.\n */\n\n/* encoder / decoder */\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder('utf-8', { fatal: true });\n\n/**\n * Normalizes the URL string using NFKC.\n * @param {string} url - The URL string to normalize.\n * @param {boolean} [isScheme] - True if the given `url` is a scheme.\n * @returns {string|null} The normalized URL string, or null.\n */\nexport const normalizeURL = (url, isScheme = false) => {\n if (!isString(url)) {\n return null;\n }\n const normalized = REG_NON_ASCII.test(url) ? url.normalize('NFKC') : url;\n if (isScheme) {\n return normalized.trim().toLowerCase().replace(/:$/, '');\n }\n return normalized;\n};\n\n/**\n * Parses a URL string with a fallback.\n * @param {string} url - The URL string to parse.\n * @param {string} [base] - The base URL string.\n * @param {boolean} [normalize] - Indicates whether to normalize the URI.\n * @returns {URL|null} The parsed URL object, or null.\n */\nexport const parseURL = (url, base, normalize = false) => {\n if (!isString(url) || url === '') {\n return null;\n }\n let urlStr = url;\n let baseStr = base && isString(base) ? base : '';\n if (normalize) {\n urlStr = normalizeURL(urlStr);\n if (baseStr) {\n baseStr = normalizeURL(baseStr);\n }\n }\n if (typeof URL.parse === 'function') {\n return baseStr ? URL.parse(urlStr, baseStr) : URL.parse(urlStr);\n }\n try {\n return baseStr ? new URL(urlStr, baseStr) : new URL(urlStr);\n } catch {\n return null;\n }\n};\n\n/**\n * Extracts an array of schemes.\n * @param {string} protocol - The URL protocol (e.g., \"data:\", \"git+https:\").\n * @returns {string[]} An array of scheme parts.\n */\nexport const getSchemeParts = protocol => {\n if (!isString(protocol)) {\n return [];\n }\n return protocol.replace(/:$/, '').split('+');\n};\n\n/**\n * Gets the URL-encoded representation of a given string.\n * @param {string} str - The target string.\n * @returns {string} The URL-encoded string.\n */\nexport const getURLEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const bytes = encoder.encode(str);\n const encoded = new Array(bytes.length);\n for (let i = 0; i < bytes.length; i++) {\n encoded[i] = HEX_TABLE[bytes[i]];\n }\n return encoded.join('');\n};\n\n/**\n * Escapes URL-encoded HTML special characters.\n * @param {string} ch - A URL-encoded (percent-encoded) character.\n * @returns {string} The escaped HTML special character, or the given character.\n */\nexport const escapeURLEncodedHTMLChars = ch => {\n if (!isString(ch)) {\n return ch;\n }\n const target = REG_URL_ENC.test(ch) ? ch.toUpperCase() : ch;\n return ESCAPE_MAP[target] ?? ch;\n};\n\n/**\n * Truncates the URL string.\n * @param {string|unknown} url - A URL string.\n * @returns {string} The truncated string.\n */\nexport const truncateURL = url => {\n const str = isString(url) ? url : String(url);\n const truncated =\n str.length > TRUNCATE_LENGTH ? `${str.slice(0, TRUNCATE_LENGTH)}...` : str;\n return truncated;\n};\n\n/**\n * Removes a trailing empty hash and an empty query string from a URL.\n * @param {string} url - The target URL string to be cleaned.\n * @returns {string} The cleaned URL string or the original input.\n */\nexport const trimTrailingEmptyQueryAndHash = url => {\n if (!isString(url)) {\n return url;\n }\n return url.replace(REG_HASH, '').replace(REG_QUERY, '$1');\n};\n\n/**\n * Replaces URL-encoded numeric character references.\n * @param {string} match - The matched substring.\n * @param {string} value - The captured numeric value.\n * @returns {string} The resolved character or the original match.\n */\nexport const replaceNumCharRef = (match, value) => {\n const num = /^x/i.test(value)\n ? Number.parseInt(value.slice(1), HEX)\n : Number.parseInt(value, DECI);\n if (!Number.isInteger(num) || num < 0 || num >= BYTE_RANGE) {\n return match;\n }\n if (NON_TEXT_CHAR_CODES.has(num)) {\n return '';\n }\n if (TEXT_CHAR_CODES.has(num)) {\n return String.fromCharCode(num);\n }\n const codePoint = WINDOWS1252_TO_UNICODE.get(num);\n return String.fromCodePoint(codePoint);\n};\n\n/**\n * Parses URL-encoded numeric character references.\n * @param {string} str - The target string to parse.\n * @param {number} [nest] - The current nesting depth for recursive parsing.\n * @returns {string} The decoded and parsed string.\n */\nexport const parseURLEncodedNumCharRef = (str, nest = 0) => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n if (!Number.isInteger(nest)) {\n throw new TypeError(`Expected Number but got ${getType(nest)}.`);\n }\n let res;\n try {\n res = decodeURIComponent(str);\n } catch {\n // Fallback: decode only valid multi-byte %XX sequences.\n res = str.replace(REG_PCT_ENC, match => {\n try {\n return decodeURIComponent(match);\n } catch {\n return match;\n }\n });\n }\n res = res.replace(REG_NON_TEXT_G, '');\n let depth = 0;\n for (; depth + nest < MAX_NEST; depth++) {\n const previousRes = res;\n // Decode '&amp;' before decoding numeric references.\n res = res.replace(REG_AMP, '&').replace(REG_NUM_REF, replaceNumCharRef);\n if (res === previousRes) {\n break;\n }\n }\n if (depth + nest >= MAX_NEST && /&#/.test(res)) {\n throw new Error('Character references nested too deeply.');\n }\n return res;\n};\n\n/**\n * Extracts the components of a parsed Data URL.\n * @param {string} pathname - The pathname of the URL.\n * @param {string} [search] - The search (query) string of the URL.\n * @param {string} [hash] - The hash (fragment) of the URL.\n * @returns {DataURLComponents} The DataURLComponents object.\n */\nexport const extractDataURLComponents = (pathname, search = '', hash = '') => {\n if (!isString(pathname)) {\n return { mediaType: '', mediaTypes: [], data: '', isBase64: false };\n }\n const comma = pathname.indexOf(',');\n if (comma === -1) {\n return {\n mediaType: pathname,\n mediaTypes: pathname.split(';'),\n data: '',\n isBase64: false\n };\n }\n const mediaType = pathname.substring(0, comma);\n const dataPart = pathname.substring(comma + 1);\n const data =\n search === '' && hash === '' ? dataPart : dataPart + search + hash;\n const mediaTypes = mediaType.split(';');\n const lastType = mediaTypes.at(-1);\n const isBase64 =\n lastType !== undefined &&\n lastType.length === 6 &&\n lastType.toLowerCase() === 'base64';\n\n return { mediaType, mediaTypes, data, isBase64 };\n};\n\n/**\n * Parses base64-encoded data.\n * @param {string} data - The base64-encoded string.\n * @returns {string} The parsed text, or the original base64 if binary.\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n }\n let binStr;\n let cleanData = data;\n try {\n binStr = atob(data);\n } catch {\n cleanData = data.replace(/\\s/g, '');\n try {\n binStr = atob(cleanData);\n } catch {\n throw new Error(`Invalid base64 data: ${truncateURL(data)}`);\n }\n }\n let bytes;\n if (IS_NODE && globalThis.Buffer) {\n // Use 'latin1' to correctly map the binary string directly to bytes.\n // @see https://nodejs.org/docs/latest/api/buffer.html#buffers-and-character-encodings\n bytes = globalThis.Buffer.from(binStr, 'latin1');\n } else {\n const len = binStr.length;\n if (len > MAX_URL_LENGTH) {\n bytes = new Uint8Array(len);\n } else {\n bytes = SHARED_BUFFER.subarray(0, len);\n }\n for (let i = 0; i < len; i++) {\n bytes[i] = binStr.charCodeAt(i);\n }\n }\n try {\n const text = decoder.decode(bytes);\n if (REG_NON_TEXT.test(text)) {\n return cleanData;\n }\n return text;\n } catch {\n return cleanData;\n }\n};\n\n/**\n * Encodes an ArrayBuffer to a Base64 string.\n * @private\n * @param {ArrayBuffer} buffer - The buffer to encode.\n * @returns {string} The Base64 string.\n */\nexport const encodeBufferToBase64 = buffer => {\n if (IS_NODE && globalThis.Buffer) {\n return globalThis.Buffer.from(buffer).toString('base64');\n }\n const uint8arr = new Uint8Array(buffer);\n if (typeof uint8arr.toBase64 === 'function') {\n return uint8arr.toBase64();\n }\n const chunks = [];\n for (let i = 0; i < uint8arr.length; i += CHUNK_SIZE) {\n chunks.push(String.fromCharCode(...uint8arr.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(chunks.join(''));\n};\n", "/**\n * filter.js\n */\n\n/* shared */\nimport { logDebug, isString } from './common.js';\nimport { domPurify } from './dompurify.js';\nimport {\n encodeBufferToBase64,\n escapeURLEncodedHTMLChars,\n extractDataURLComponents,\n getSchemeParts,\n normalizeURL,\n parseBase64,\n parseURL,\n parseURLEncodedNumCharRef,\n trimTrailingEmptyQueryAndHash,\n truncateURL\n} from './utility.js';\n\n/* constants */\nimport { DUMMY_BASE, MAX_NEST } from './constant.js';\nimport {\n REG_AMP_ENC,\n REG_MIME_DOM,\n REG_SCHEME,\n REG_SCRIPT,\n REG_SCRIPT_OR_BLOB,\n REG_TAG_QUOT,\n REG_VERIFY_RELATIVE\n} from './regexp.js';\n\n/**\n * Context manager for the sanitization process.\n */\nexport class SanitizeContext {\n /**\n * @param {object} opt - Sanitization options.\n * @param {object} domPurifyInstance - The DOMPurify instance.\n */\n constructor(opt, domPurifyInstance) {\n this.domPurify = domPurifyInstance;\n this.nest = 0;\n this.recurse = new Set();\n this.restrictScheme = false;\n this.schemeMap = new Map([\n ['blob', false],\n ['data', false],\n ['file', false],\n ['javascript', false],\n ['vbscript', false]\n ]);\n this.#compileRules(opt);\n }\n\n /**\n * Compiles allow, deny, and only rules into the context.\n * @private\n * @param {object} opt - Sanitization options.\n */\n #compileRules(opt = {}) {\n const { allowRelative, debug, schemes, allow, deny, only } = opt;\n this.allowRelative = !!allowRelative;\n this.debug = !!debug;\n if (Array.isArray(only) && only.length) {\n this.schemes = new Set();\n this.restrictScheme = true;\n for (const scheme of only) {\n this.#registerScheme(scheme);\n }\n } else {\n this.schemes = new Set(schemes || []);\n if (Array.isArray(allow) && allow.length) {\n for (const scheme of allow) {\n this.#registerScheme(scheme);\n }\n }\n if (Array.isArray(deny) && deny.length) {\n for (const scheme of deny) {\n const normalized = normalizeURL(scheme, true);\n if (normalized) {\n this.schemeMap.set(normalized, false);\n }\n }\n }\n }\n }\n\n /**\n * Register schemes for the 'allow' or 'only' options.\n * @private\n * @param {string} scheme - The scheme to register.\n * @returns {boolean} True if the scheme is successfully registered.\n */\n #registerScheme(scheme) {\n const normalizedScheme = normalizeURL(scheme, true);\n if (\n !normalizedScheme ||\n REG_SCRIPT_OR_BLOB.test(normalizedScheme) ||\n !REG_SCHEME.test(normalizedScheme)\n ) {\n return false;\n }\n if (normalizedScheme.includes('+')) {\n const isScript = normalizedScheme\n .split('+')\n .some(s => REG_SCRIPT.test(s));\n if (isScript) {\n return false;\n }\n }\n this.schemeMap.set(normalizedScheme, true);\n this.schemes.add(normalizedScheme);\n return true;\n }\n\n /**\n * Tracks the URL to prevent circular references.\n * @param {string} url - The URL being processed.\n * @returns {boolean} True if safe to proceed, false otherwise.\n */\n enter(url) {\n if (this.recurse.has(url)) {\n if (this.debug) {\n logDebug(`Circular Data URL detected and skipped: ${truncateURL(url)}`);\n }\n return false;\n }\n this.nest++;\n this.recurse.add(url);\n return true;\n }\n\n /**\n * Cleans up the tracking state after processing the URL.\n * @param {string} url - The URL that finished processing.\n */\n leave(url) {\n this.nest--;\n this.recurse.delete(url);\n }\n}\n\n/**\n * An executor for sanitization filters.\n */\nexport class SanitizeFilter {\n /* private fields */\n #defaultOpts;\n\n /**\n * @param {object} options - The default sanitization options.\n */\n constructor(options) {\n this.#defaultOpts = options;\n }\n\n /**\n * Process recursive method for sanitization.\n * @private\n * @param {string} url - The URL string to sanitize.\n * @param {SanitizeContext} ctx - The sanitization context.\n * @returns {string|null} The sanitized URL, or null.\n */\n #process(url, ctx) {\n if (ctx.nest > MAX_NEST) {\n throw new Error('Data URLs nested too deeply.');\n }\n const urlObj = parseURL(url, null, true);\n if (!urlObj) {\n if (ctx.allowRelative && !REG_VERIFY_RELATIVE.test(url)) {\n const dummyURL = parseURL(url, DUMMY_BASE);\n if (dummyURL) {\n const { protocol, hostname, pathname, search, hash } = dummyURL;\n if (protocol === 'http:' && hostname === 'dummy.local') {\n return this.#sanitizeStandardURL(`${pathname}${search}${hash}`);\n }\n }\n }\n return null;\n }\n const scheme = normalizeURL(urlObj.protocol, true);\n if (ctx.restrictScheme && !ctx.schemeMap.has(scheme)) {\n return null;\n }\n if (scheme.includes('+')) {\n const schemeParts = scheme.split('+');\n if (\n ctx.schemeMap.get(scheme) === false ||\n schemeParts.some(part => ctx.schemeMap.get(part) === false)\n ) {\n return null;\n }\n } else if (ctx.schemeMap.get(scheme) === false) {\n return null;\n }\n if (scheme === 'data') {\n return this.#sanitizeDataURL(urlObj, ctx);\n }\n return this.#sanitizeStandardURL(urlObj.href);\n }\n\n /**\n * Decodes, verifies inner protocols, and purifies Data URLs.\n * @private\n * @param {URL} urlObj - The URL object.\n * @param {SanitizeContext} ctx - The sanitization context.\n * @returns {string|null} Sanitized Data URL or null.\n */\n #sanitizeDataURL(urlObj, ctx) {\n const { mediaType, mediaTypes, data, isBase64 } = extractDataURLComponents(\n urlObj.pathname,\n urlObj.search,\n urlObj.hash\n );\n let parsedData = data;\n if (isBase64) {\n try {\n parsedData = parseBase64(data);\n } catch (e) {\n if (ctx.debug) {\n logDebug('Failed to parse base64 data.', e);\n }\n return null;\n }\n }\n try {\n const decodedData = parseURLEncodedNumCharRef(parsedData).trim();\n const parsedURL = parseURL(decodedData, DUMMY_BASE);\n if (!parsedURL) {\n return null;\n }\n const dataSchemeParts = getSchemeParts(parsedURL.protocol);\n if (dataSchemeParts.some(s => REG_SCRIPT_OR_BLOB.test(s))) {\n return null;\n }\n } catch (e) {\n if (ctx.debug) {\n logDebug('Failed to parse inner data URL protocol.', e);\n }\n return null;\n }\n if (!mediaType || REG_MIME_DOM.test(mediaType)) {\n parsedData = this.#purify(parsedData, ctx);\n }\n if (parsedData) {\n if (isBase64 && parsedData !== data) {\n mediaTypes.pop();\n }\n return `data:${mediaTypes.join(';')},${parsedData}`;\n }\n return null;\n }\n\n /**\n * Purifies a URL-encoded DOM string to prevent XSS.\n * @private\n * @param {string} dom - The URL-encoded DOM string.\n * @param {SanitizeContext} ctx - The sanitization context.\n * @returns {string} The purified DOM string.\n */\n #purify(dom, ctx) {\n let decodedDom = dom;\n try {\n decodedDom = decodeURIComponent(dom);\n } catch {\n // fall through\n }\n let purifiedDom;\n try {\n ctx.domPurify.addHook('uponSanitizeAttribute', (node, evt) =>\n this.#handleSanitizeAttribute(node, evt, ctx)\n );\n purifiedDom = ctx.domPurify.sanitize(decodedDom);\n } finally {\n ctx.domPurify.removeHook('uponSanitizeAttribute');\n }\n purifiedDom = trimTrailingEmptyQueryAndHash(purifiedDom);\n try {\n return encodeURI(purifiedDom);\n } catch {\n return purifiedDom;\n }\n }\n\n /**\n * Internal handler for the DOMPurify hook.\n * @private\n * @param {Node} node - The DOM node.\n * @param {object} evt - The event object.\n * @param {SanitizeContext} ctx - The sanitization context.\n */\n #handleSanitizeAttribute(node, evt, ctx) {\n if (!evt.attrValue || !/^\\s*data:/i.test(evt.attrValue)) {\n return;\n }\n const urlObj = parseURL(evt.attrValue, null, true);\n if (!urlObj || urlObj.protocol !== 'data:') {\n return;\n }\n const originalURL = evt.attrValue;\n if (!ctx.enter(originalURL)) {\n evt.attrValue = '';\n return;\n }\n try {\n const sanitized = this.#process(originalURL, ctx);\n evt.attrValue = sanitized || '';\n } finally {\n ctx.leave(originalURL);\n }\n }\n\n /**\n * Sanitizes URLs by stripping out problematic characters.\n * @private\n * @param {string} urlToSanitize - The absolute/relative URL.\n * @returns {string} The sanitized URL.\n */\n #sanitizeStandardURL(urlToSanitize) {\n const len = urlToSanitize.length;\n let truncateIndex = len;\n const matchTagQuot = REG_TAG_QUOT.exec(urlToSanitize);\n if (matchTagQuot) {\n truncateIndex = matchTagQuot.index;\n }\n if (urlToSanitize.indexOf('&') > -1) {\n const matchAmp = REG_AMP_ENC.exec(urlToSanitize);\n if (matchAmp) {\n const matchAmpIndex = matchAmp.index;\n if (matchAmpIndex < truncateIndex) {\n truncateIndex = matchAmpIndex;\n }\n }\n }\n if (truncateIndex === len) {\n return urlToSanitize;\n }\n const lastChar = urlToSanitize.charCodeAt(truncateIndex - 1);\n if (lastChar === 63 /* ? */ || lastChar === 38 /* & */) {\n truncateIndex--;\n }\n return urlToSanitize.substring(0, truncateIndex);\n }\n\n /**\n * Sanitizes the URL.\n * @param {string} url - The URL string to sanitize.\n * @param {object} options - Sanitization options.\n * @returns {string|null} The sanitized URL, or null.\n */\n sanitize(url, options = this.#defaultOpts) {\n if (!url || !isString(url)) {\n return null;\n }\n const { deny, maxLength, only, allowRelative } = options;\n if (Number.isInteger(maxLength) && url.length > maxLength) {\n const msg = `URL length ${url.length} exceeds max length ${maxLength}.`;\n throw new RangeError(msg);\n }\n const hasRestrictiveRules =\n (Array.isArray(deny) && deny.length > 0) ||\n (Array.isArray(only) && only.length > 0) ||\n allowRelative;\n // Early return for standard HTTP/HTTPS URLs without restrictive rules.\n if (\n !hasRestrictiveRules &&\n (url.startsWith('https://') || url.startsWith('http://')) &&\n !REG_TAG_QUOT.test(url) &&\n !url.includes('data:')\n ) {\n const urlObj = parseURL(url, null, true);\n if (urlObj && options.schemes.has(urlObj.protocol.replace(/:$/, ''))) {\n return urlObj.href.replace(/%26/g, escapeURLEncodedHTMLChars);\n }\n return null;\n }\n const ctx = new SanitizeContext(options, domPurify);\n return this.#process(url, ctx);\n }\n\n /**\n * Asynchronously sanitizes an ArrayBuffer and converts it to a Data URL.\n * @param {ArrayBuffer} buffer - The target buffer.\n * @param {string} mimeType - The MIME type of the buffer.\n * @param {object} options - Sanitization options.\n * @returns {Promise<string|null>} The sanitized Data URL, or null.\n */\n async sanitizeBuffer(buffer, mimeType, options = this.#defaultOpts) {\n if (!(buffer instanceof ArrayBuffer)) {\n return null;\n }\n const base64Data = encodeBufferToBase64(buffer);\n const dataUrl = `data:${mimeType ? `${mimeType};base64` : 'base64'},${base64Data}`;\n if (\n Number.isInteger(options.maxLength) &&\n dataUrl.length > options.maxLength\n ) {\n throw new RangeError(\n `URL length ${dataUrl.length} exceeds max length ${options.maxLength}.`\n );\n }\n const ctx = new SanitizeContext(options, domPurify);\n if (!ctx.schemeMap.get('data')) {\n return null;\n }\n const urlObj = parseURL(dataUrl);\n if (!urlObj) {\n return null;\n }\n return this.#sanitizeDataURL(urlObj, ctx);\n }\n\n /**\n * Asynchronously sanitizes the Data URL.\n * @param {string} url - The URL string to sanitize.\n * @param {object} options - Sanitization options.\n * @returns {Promise<string|null>} The sanitized Data URL, or null.\n */\n async sanitizeDataURL(url, options = this.#defaultOpts) {\n if (!url || !isString(url)) {\n return null;\n }\n const { maxLength } = options;\n if (Number.isInteger(maxLength) && url.length > maxLength) {\n throw new RangeError(\n `URL length ${url.length} exceeds max length ${maxLength}.`\n );\n }\n const urlObj = parseURL(url);\n if (!urlObj) {\n return null;\n }\n const scheme = normalizeURL(urlObj.protocol, true);\n if (scheme !== 'data') {\n return null;\n }\n const ctx = new SanitizeContext(options, domPurify);\n if (!ctx.schemeMap.get(scheme)) {\n return null;\n }\n return this.#sanitizeDataURL(urlObj, ctx);\n }\n}\n", "[\"aaa\",\"aaas\",\"about\",\"acap\",\"acct\",\"acd\",\"acr\",\"adiumxtra\",\"adt\",\"aet\",\"afp\",\"afs\",\"agtp\",\"aim\",\"amss\",\"android\",\"appdata\",\"apt\",\"ar\",\"ari\",\"ark\",\"ars\",\"at\",\"attachment\",\"aw\",\"barion\",\"beshare\",\"bitcoin\",\"bitcoincash\",\"bl\",\"blob\",\"bluetooth\",\"bolo\",\"brid\",\"browserext\",\"cabal\",\"caip\",\"calculator\",\"callto\",\"cap\",\"cast\",\"casts\",\"chrome\",\"chrome-extension\",\"cid\",\"cm\",\"coap\",\"coaps\",\"com-eventbrite-attendee\",\"content\",\"content-type\",\"crid\",\"cstr\",\"cttps\",\"cvs\",\"dab\",\"dat\",\"data\",\"dav\",\"dhttp\",\"diaspora\",\"dict\",\"did\",\"dilithium3\",\"dis\",\"dlna-playcontainer\",\"dlna-playsingle\",\"dnp\",\"dns\",\"dntp\",\"doi\",\"donau\",\"dpp\",\"drm\",\"dtmi\",\"dtn\",\"dvb\",\"dvx\",\"dweb\",\"ed2k\",\"eid\",\"elsi\",\"embedded\",\"ens\",\"esim\",\"ethereum\",\"example\",\"ez\",\"facetime\",\"feed\",\"feedready\",\"fido\",\"file\",\"finger\",\"first-run-pen-experience\",\"fish\",\"fm\",\"ftp\",\"fuchsia-pkg\",\"gcx\",\"gdsi\",\"geo\",\"gg\",\"git\",\"gitoid\",\"gizmoproject\",\"go\",\"gopher\",\"graph\",\"gtalk\",\"h323\",\"ham\",\"hcap\",\"hcp\",\"hs20\",\"http\",\"https\",\"hxxp\",\"hxxps\",\"hydrazone\",\"hyper\",\"i0\",\"iax\",\"ibi\",\"ibi-\",\"icap\",\"icon\",\"ilstring\",\"im\",\"imap\",\"info\",\"interaction\",\"iotdisco\",\"ipfs\",\"ipn\",\"ipns\",\"ipp\",\"ipps\",\"irc\",\"irc6\",\"ircs\",\"iris\",\"iris.beep\",\"iris.lwz\",\"iris.xpc\",\"iris.xpcs\",\"isostore\",\"itms\",\"jabber\",\"jar\",\"jms\",\"keyparc\",\"lastfm\",\"lbry\",\"ldap\",\"ldaps\",\"leaptofrogans\",\"lid\",\"linkid\",\"lorawan\",\"lpa\",\"lvlt\",\"machineProvisioningProgressReporter\",\"magnet\",\"mailto\",\"maps\",\"market\",\"matrix\",\"mdoc\",\"mdoc-openid4vp\",\"message\",\"microsoft.windows.camera\",\"microsoft.windows.camera.multipicker\",\"microsoft.windows.camera.picker\",\"mid\",\"mms\",\"mongodb\",\"moz\",\"moz-extension\",\"mqtt\",\"mqtts\",\"ms-access\",\"ms-appinstaller\",\"ms-browser-extension\",\"ms-calculator\",\"ms-drive-to\",\"ms-enrollment\",\"ms-excel\",\"ms-eyecontrolspeech\",\"ms-gamebarservices\",\"ms-gamingoverlay\",\"ms-getoffice\",\"ms-help\",\"ms-infopath\",\"ms-inputapp\",\"ms-launchremotedesktop\",\"ms-lockscreencomponent-config\",\"ms-media-stream-id\",\"ms-meetnow\",\"ms-mixedrealitycapture\",\"ms-mobileplans\",\"ms-newsandinterests\",\"ms-officeapp\",\"ms-people\",\"ms-personacard\",\"ms-powerpoint\",\"ms-project\",\"ms-publisher\",\"ms-recall\",\"ms-remotedesktop\",\"ms-remotedesktop-launch\",\"ms-restoretabcompanion\",\"ms-screenclip\",\"ms-screensketch\",\"ms-search\",\"ms-search-repair\",\"ms-secondary-screen-controller\",\"ms-secondary-screen-setup\",\"ms-settings\",\"ms-settings-airplanemode\",\"ms-settings-bluetooth\",\"ms-settings-camera\",\"ms-settings-cellular\",\"ms-settings-cloudstorage\",\"ms-settings-connectabledevices\",\"ms-settings-displays-topology\",\"ms-settings-emailandaccounts\",\"ms-settings-language\",\"ms-settings-location\",\"ms-settings-lock\",\"ms-settings-nfctransactions\",\"ms-settings-notifications\",\"ms-settings-power\",\"ms-settings-privacy\",\"ms-settings-proximity\",\"ms-settings-screenrotation\",\"ms-settings-wifi\",\"ms-settings-workplace\",\"ms-spd\",\"ms-stickers\",\"ms-sttoverlay\",\"ms-transit-to\",\"ms-useractivityset\",\"ms-uup\",\"ms-virtualtouchpad\",\"ms-visio\",\"ms-walk-to\",\"ms-whiteboard\",\"ms-whiteboard-cmd\",\"ms-widgetboard\",\"ms-widgets\",\"ms-word\",\"msnim\",\"msrp\",\"msrps\",\"mss\",\"mt\",\"mtqp\",\"mtrust\",\"mumble\",\"mupdate\",\"musik\",\"mvn\",\"mvrp\",\"mvrps\",\"news\",\"nfs\",\"ni\",\"nih\",\"nntp\",\"nostr\",\"notes\",\"npamp\",\"num\",\"ocf\",\"oid\",\"onenote\",\"onenote-cmd\",\"opaquelocktoken\",\"openid\",\"openpgp4fpr\",\"otpauth\",\"palm\",\"paparazzi\",\"payto\",\"pkcs11\",\"pkg\",\"platform\",\"pop\",\"pres\",\"proxy\",\"psyc\",\"pttp\",\"pwid\",\"qb\",\"query\",\"quic-transport\",\"redis\",\"rediss\",\"reload\",\"res\",\"resource\",\"rmi\",\"rsync\",\"rtmfp\",\"rtmp\",\"rtsp\",\"rtsps\",\"rtspu\",\"sarif\",\"secondlife\",\"secret-token\",\"service\",\"session\",\"sftp\",\"sgn\",\"shc\",\"shelter\",\"sieve\",\"simpleledger\",\"simplex\",\"sip\",\"sips\",\"skype\",\"smb\",\"smp\",\"sms\",\"smtp\",\"snmp\",\"soap.beep\",\"soap.beeps\",\"soldat\",\"spacify\",\"spiffe\",\"spotify\",\"ssb\",\"ssh\",\"sss\",\"starknet\",\"steam\",\"stun\",\"stuns\",\"submit\",\"svn\",\"swh\",\"swid\",\"swidpath\",\"tag\",\"taler\",\"teamspeak\",\"teapot\",\"teapots\",\"tel\",\"teliaeid\",\"telnet\",\"tftp\",\"things\",\"thismessage\",\"tip\",\"tn3270\",\"tool\",\"tttps\",\"turn\",\"turns\",\"tv\",\"udp\",\"unreal\",\"upn\",\"urn\",\"ust\",\"ut2004\",\"uuaid\",\"uuid-in-package\",\"v-event\",\"vemmi\",\"ventrilo\",\"ves\",\"view-source\",\"vnc\",\"vscode\",\"vscode-insiders\",\"vsls\",\"w3\",\"wasm\",\"wasm-js\",\"wcr\",\"web3\",\"webcal\",\"wifi\",\"ws\",\"wss\",\"wtai\",\"wyciwyg\",\"xcompute\",\"xcon\",\"xcon-userid\",\"xfire\",\"xftp\",\"xmlrpc.beep\",\"xmlrpc.beeps\",\"xmpp\",\"xrcp\",\"xri\",\"ymsgr\",\"z39.50r\",\"z39.50s\",\"ztdnaid\"]\n", "/**\n * scheme.js\n */\n\n/* shared */\nimport uriSchemes from '../lib/iana/uri-schemes.json' with { type: 'json' };\nimport { isString } from './common.js';\nimport { normalizeURL, parseURL } from './utility.js';\n\n/* constants */\nimport { REG_SCHEME_EXT, REG_SCRIPT } from './regexp.js';\n\n/**\n * URI schemes\n */\nexport class URISchemes {\n /* private fields */\n #schemes = new Set(uriSchemes);\n\n /**\n * Gets the list of registered URI schemes.\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes are omitted.\n * - The 'moz-extension' scheme is added by default.\n * @returns {string[]} An array of registered schemes.\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * Extracts the scheme from URI.\n * @param {string} uri - The URI string.\n * @returns {string|null} The extracted scheme, or null.\n */\n getScheme(uri) {\n if (!isString(uri)) {\n return null;\n }\n const parsed = this.parse(uri);\n if (parsed) {\n return this.normalize(parsed.protocol, true);\n }\n return null;\n }\n\n /**\n * Checks if the specified scheme is currently registered.\n * @param {string} scheme - The target scheme.\n * @returns {boolean} True if the scheme is registered.\n */\n has(scheme) {\n const normalized = this.normalize(scheme, true);\n if (normalized) {\n return this.#schemes.has(normalized);\n }\n return false;\n }\n\n /**\n * Normalizes the URI string using NFKC.\n * @param {string} uri - The URI string to normalize.\n * @param {boolean} [isScheme] - True if the URI is a scheme.\n * @returns {string|null} The normalized URI string, or null.\n */\n normalize(uri, isScheme = false) {\n return normalizeURL(uri, isScheme);\n }\n\n /**\n * Normalizes an array of scheme strings.\n * Filters out non-string items and trims/lowercases valid schemes.\n * @param {string[]} schemes - An array of scheme strings to normalize.\n * @returns {string[]} An array of normalized scheme strings, or an empty array if invalid.\n */\n normalizeSchemes(schemes) {\n if (Array.isArray(schemes)) {\n const normalizedSchemes = [];\n for (const scheme of schemes) {\n const normalized = normalizeURL(scheme, true);\n if (normalized) {\n normalizedSchemes.push(normalized);\n }\n }\n return normalizedSchemes;\n }\n return [];\n }\n\n /**\n * Parses the URI/URL string.\n * @param {string} uri - The URI/URL string.\n * @param {string} [base] - The base URL string.\n * @param {boolean} [normalize] - Indicates whether to normalize the URI.\n * @returns {URL|null} The parsed URL object, or null.\n */\n parse(uri, base, normalize = false) {\n return parseURL(uri, base, normalize);\n }\n\n /**\n * Verifies if the given URI is valid and its scheme is allowed.\n * @param {string} uri - The URI string to verify.\n * @param {Set<string>} [schemes] - The set of allowed schemes.\n * @returns {boolean} True if the URI is valid and permitted.\n */\n verifyURI(uri, schemes) {\n if (!isString(uri)) {\n return false;\n }\n const parsedUrl = this.parse(uri);\n if (!parsedUrl) {\n return false;\n }\n return this.verifyScheme(parsedUrl.protocol, schemes, true);\n }\n\n /**\n * Verifies if the scheme is valid and allowed.\n * @param {string} scheme - A scheme or URL.protocol to verify.\n * @param {Set<string>} [schemes] - The set of allowed schemes.\n * @param {boolean} [allowCustom] - True if web+*, ext+* schemes are allowed.\n * @returns {boolean} True if the parsed URL is valid and permitted.\n */\n verifyScheme(scheme, schemes, allowCustom = false) {\n if (!isString(scheme)) {\n return false;\n }\n const normalized = this.normalize(scheme, true);\n const targetSchemes = schemes || this.#schemes;\n if (!normalized.includes('+')) {\n if (REG_SCRIPT.test(normalized)) {\n return false;\n }\n return targetSchemes.has(normalized);\n }\n const parts = normalized.split('+');\n const isScript = parts.some(s => REG_SCRIPT.test(s));\n if (isScript) {\n return false;\n }\n if (targetSchemes.has(normalized)) {\n return true;\n }\n return (\n (allowCustom && REG_SCHEME_EXT.test(normalized)) ||\n parts.every(s => targetSchemes.has(s))\n );\n }\n}\n", "/**\n * sanitize.js\n */\n\n/* shared */\nimport { getType, logDebug, isString } from './common.js';\nimport { SanitizeFilter } from './filter.js';\nimport { URISchemes } from './scheme.js';\nimport {\n encodeBufferToBase64,\n extractDataURLComponents,\n normalizeURL,\n parseURL,\n truncateURL\n} from './utility.js';\n\n/* constants */\nimport { DECI, MAX_BLOB_SIZE, MAX_URL_LENGTH } from './constant.js';\nimport { REG_SCHEME, REG_SCRIPT, REG_SCRIPT_OR_BLOB } from './regexp.js';\nconst URL_PROPS = Object.freeze([\n 'href',\n 'origin',\n 'protocol',\n 'username',\n 'password',\n 'host',\n 'hostname',\n 'port',\n 'pathname',\n 'search',\n 'hash'\n]);\nconst DEFAULT_OPTS = Object.freeze({\n allow: Object.freeze([]),\n deny: Object.freeze([]),\n only: Object.freeze([]),\n allowRelative: false,\n debug: false,\n revokeObjectURL: false,\n maxBlobSize: MAX_BLOB_SIZE,\n maxLength: MAX_URL_LENGTH\n});\n\n/* typedef */\n/**\n * The parsed result of a Data URL.\n * @typedef {object} InspectedDataURL\n * @property {boolean} base64 - Indicates whether the data is base64-encoded.\n * @property {string} data - The actual data part of the Data URL.\n * @property {string} mime - The MIME type of the data.\n */\n\n/**\n * The result of an inspected URL, extending the standard URL API.\n * The properties except for input and valid are omitted for invalid URLs.\n * @typedef {object} InspectedURLResult\n * @property {string} input - The original URL input.\n * @property {boolean} valid - Indicates whether the sanitized URL (href) is a valid absolute URL.\n * @property {string|null} href - The sanitized URL, or null.\n * @property {boolean} [relative] - Indicates whether the sanitized URL (href) is a valid relative URL.\n * @property {string} [reason] - The reason why the URL is invalid.\n * @property {InspectedDataURL|null} [data] - The parsed result of a Data URL, or null.\n * @property {string} [origin] - The scheme, domain, and port.\n * @property {string} [protocol] - The protocol scheme.\n * @property {string} [username] - The specified username.\n * @property {string} [password] - The specified password.\n * @property {string} [host] - The domain and port.\n * @property {string} [hostname] - The domain.\n * @property {string} [port] - The port number.\n * @property {string} [pathname] - The path.\n * @property {string} [search] - The query string.\n * @property {string} [hash] - The fragment identifier.\n */\n\n/* blob handlers */\n/**\n * Reads a stream in chunks and generates an ArrayBuffer.\n * @private\n * @param {Response} response - The Response instance.\n * @param {number} maxSize - The maximum allowed size in bytes.\n * @returns {Promise<ArrayBuffer>} A promise resolving to the generated ArrayBuffer.\n */\nconst readStreamInChunksAsArrayBuffer = async (response, maxSize) => {\n const reader = response.body.getReader();\n const chunks = [];\n try {\n let accumulatedSize = 0;\n while (accumulatedSize <= maxSize) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n accumulatedSize += value.byteLength;\n if (accumulatedSize > maxSize) {\n await reader.cancel('Size limit exceeded');\n throw new DOMException(\n `Payload (${accumulatedSize} bytes) exceeds max (${maxSize} bytes).`,\n 'NotReadableError'\n );\n }\n chunks.push(value);\n }\n const combined = new Uint8Array(accumulatedSize);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return combined.buffer;\n } finally {\n reader.releaseLock();\n }\n};\n\n/**\n * Fetches a Blob URL and extracts its ArrayBuffer and MIME type.\n * @param {string} url - The Blob URL to fetch.\n * @param {number} [maxBlobSize] - The maximum allowed Blob size in bytes.\n * @returns {Promise<{ buffer: ArrayBuffer, mimeType: string }>} A promise resolving to the buffer and MIME type.\n */\nconst fetchBlobAsArrayBuffer = async (url, maxBlobSize) => {\n let maxSize = MAX_BLOB_SIZE;\n if (Number.isInteger(maxBlobSize) && maxBlobSize > 0) {\n maxSize = maxBlobSize;\n }\n const response = await fetch(url);\n if (!response.ok) {\n const truncatedURL = truncateURL(url);\n let msg = `Failed to fetch ${truncatedURL}`;\n if (Number.isInteger(response.status)) {\n if (response.statusText) {\n msg += `: ${response.status} ${response.statusText}`;\n } else {\n msg += `: ${response.status}`;\n }\n }\n throw new Error(msg);\n }\n const contentLength = response.headers.get('content-length');\n if (contentLength) {\n const parsedLength = Number.parseInt(contentLength, DECI);\n if (Number.isInteger(parsedLength) && parsedLength > maxSize) {\n throw new DOMException(\n `Payload (${parsedLength} bytes) exceeds max (${maxSize} bytes).`,\n 'NotReadableError'\n );\n }\n }\n const mimeType = response.headers.get('content-type') || '';\n let buffer;\n if (response.body) {\n buffer = await readStreamInChunksAsArrayBuffer(response, maxSize);\n } else {\n const blob = await response.blob();\n if (blob.size > maxSize) {\n throw new DOMException(\n `Payload (${blob.size} bytes) exceeds max (${maxSize} bytes).`,\n 'NotReadableError'\n );\n }\n buffer = await blob.arrayBuffer();\n }\n return { buffer, mimeType };\n};\n\n/**\n * URL sanitizer\n */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #allowedSchemes;\n #defaultOpts;\n #filter;\n\n constructor() {\n super();\n this.#allowedSchemes = new Set(super.get());\n this.#defaultOpts = {\n ...DEFAULT_OPTS,\n schemes: this.#allowedSchemes\n };\n this.#filter = new SanitizeFilter(this.#defaultOpts);\n }\n\n /**\n * Validates if a normalized URI scheme is syntactically correct.\n * @private\n * @param {string} normalizedScheme - The normalized URI scheme to validate.\n * @returns {boolean} True if the scheme satisfies the syntax and requirements.\n */\n #isWellFormedScheme(normalizedScheme) {\n if (\n !isString(normalizedScheme) ||\n REG_SCRIPT_OR_BLOB.test(normalizedScheme)\n ) {\n return false;\n }\n if (normalizedScheme.includes('+')) {\n const isScript = normalizedScheme\n .split('+')\n .some(s => REG_SCRIPT.test(s));\n if (isScript) {\n return false;\n }\n }\n return REG_SCHEME.test(normalizedScheme);\n }\n\n /**\n * Normalizes options and evaluates preliminary scheme routing.\n * @private\n * @param {string} url - The URL string.\n * @param {object} opt - User options.\n * @returns {{ isValid: boolean|undefined, options: object, scheme: string|null }} Nomalized options, scheme, and isValid.\n */\n #normalizeOptions(url, opt = {}) {\n if (!url || !isString(url)) {\n return { isValid: false };\n }\n const options = {\n ...this.#defaultOpts,\n ...opt,\n allow: this.normalizeSchemes(opt.allow),\n deny: this.normalizeSchemes(opt.deny),\n only: this.normalizeSchemes(opt.only),\n schemes: this.#allowedSchemes\n };\n const scheme = this.getScheme(url);\n if (scheme === null && !options.allowRelative) {\n return { isValid: false };\n }\n return { options, scheme };\n }\n\n /**\n * Inspects, parses, and sanitizes the given URL.\n * @private\n * @param {string} url - The URL string to parse.\n * @returns {InspectedURLResult} The result of an inspected URL.\n */\n #inspect(url) {\n const inspectedURL = {\n input: url,\n href: null,\n valid: false\n };\n if (!isString(url)) {\n inspectedURL.reason = `Invalid URL input: ${truncateURL(url)}`;\n return inspectedURL;\n }\n if (url === '') {\n inspectedURL.reason = 'Invalid URL input: (empty string)';\n return inspectedURL;\n }\n let sanitizedURL;\n let invalidReason = null;\n try {\n sanitizedURL = this.#filter.sanitize(url, {\n ...this.#defaultOpts,\n allow: ['data'],\n allowRelative: true\n });\n if (!sanitizedURL) {\n invalidReason =\n 'Sanitization failed (blocked by allowed schemes or rules).';\n }\n } catch (e) {\n invalidReason = e.message;\n }\n if (sanitizedURL) {\n // Reparse the sanitized string to safely extract updated properties.\n const urlObj = parseURL(sanitizedURL);\n inspectedURL.valid = true;\n if (urlObj) {\n const scheme = normalizeURL(urlObj.protocol, true);\n if (scheme === 'data') {\n const { mediaTypes, data, isBase64 } = extractDataURLComponents(\n urlObj.pathname,\n urlObj.search,\n urlObj.hash\n );\n if (isBase64) {\n mediaTypes.pop();\n }\n inspectedURL.data = {\n mime: mediaTypes.join(';'),\n base64: isBase64,\n data\n };\n } else {\n inspectedURL.data = null;\n }\n for (const key of URL_PROPS) {\n const value = urlObj[key];\n if (isString(value)) {\n inspectedURL[key] = value;\n }\n }\n } else {\n // URL which is invalid as an absolute URL, but valid as a relative URL.\n inspectedURL.valid = false;\n inspectedURL.relative = true;\n inspectedURL.href = sanitizedURL;\n inspectedURL.reason =\n 'Invalid as an absolute URL, but valid as a relative URL.';\n }\n } else {\n inspectedURL.reason = invalidReason;\n }\n return inspectedURL;\n }\n\n /**\n * Gets the list of registered URI schemes.\n * @returns {string[]} An array of registered schemes.\n */\n get() {\n return [...this.#allowedSchemes];\n }\n\n /**\n * Checks if the specified scheme is currently registered.\n * @param {string} scheme - The target scheme.\n * @returns {boolean} True if the scheme is registered.\n */\n has(scheme) {\n const normalizedScheme = normalizeURL(scheme, true);\n if (normalizedScheme) {\n return this.#allowedSchemes.has(normalizedScheme);\n }\n return false;\n }\n\n /**\n * Adds a new scheme to the allowed list.\n * @param {string} scheme - The scheme to add.\n * @returns {string[]} The updated array of registered schemes.\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n }\n const normalizedScheme = normalizeURL(scheme, true);\n if (!this.#isWellFormedScheme(normalizedScheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#allowedSchemes.add(normalizedScheme);\n return [...this.#allowedSchemes];\n }\n\n /**\n * Removes a scheme from the allowed list.\n * @param {string} scheme - The scheme to remove.\n * @returns {boolean} True if the scheme was successfully removed.\n */\n remove(scheme) {\n if (!isString(scheme)) {\n return false;\n }\n const normalizedScheme = normalizeURL(scheme, true);\n return this.#allowedSchemes.delete(normalizedScheme);\n }\n\n /**\n * Resets the registered schemes back to the default initial list.\n * @returns {void}\n */\n reset() {\n this.#allowedSchemes = new Set(super.get());\n }\n\n /**\n * Asynchronously sanitizes the given URL.\n * NOTE: `blob`, `data`, and `file` schemes must be explicitly allowed.\n * Given a `blob` URL, it securely converts and returns a sanitized `data` URL.\n * @param {string} url - URL.\n * @param {object} [opt] - options.\n * @param {string[]} [opt.allow] - The array of schemes to allow.\n * @param {string[]} [opt.deny] - The array of schemes to deny.\n * @param {string[]} [opt.only] - The array of specific schemes to allow.\n * @param {boolean} [opt.allowRelative] - Allow relative URLs.\n * @param {boolean} [opt.debug] - Enable debug mode.\n * @param {boolean} [opt.revokeObjectURL] - Revokes the Blob URL after sanitization.\n * @param {number} [opt.maxBlobSize] - The maximum allowed Blob size in bytes.\n * @param {number} [opt.maxLength] - The maximum allowed URL length.\n * @returns {Promise<string|null>} A promise resolving to the sanitized URL, or null.\n */\n async sanitizeURL(url, opt) {\n const { isValid, options, scheme } = this.#normalizeOptions(url, opt);\n if (isValid === false) {\n return null;\n }\n if (scheme === 'blob') {\n const { allow, deny, only } = options;\n let sanitizedData = null;\n if (\n (allow.includes('blob') && !deny.includes('blob')) ||\n only.includes('blob')\n ) {\n let fetchedBuffer = null;\n let fetchedMimeType = '';\n try {\n const fetchResult = await fetchBlobAsArrayBuffer(\n url,\n options.maxBlobSize\n );\n fetchedBuffer = fetchResult.buffer;\n fetchedMimeType = fetchResult.mimeType;\n } catch (e) {\n if (options.debug) {\n logDebug(\n `Failed to fetch and convert blob URL: ${truncateURL(url)}`,\n e\n );\n }\n }\n if (fetchedBuffer) {\n if (only.length) {\n if (!only.includes('data')) {\n options.only = [...only, 'data'];\n }\n } else {\n if (!allow.includes('data')) {\n options.allow = [...allow, 'data'];\n }\n options.deny = deny.filter(s => s !== 'data');\n }\n sanitizedData = await this.#filter.sanitizeBuffer(\n fetchedBuffer,\n fetchedMimeType,\n options\n );\n }\n }\n if (options.revokeObjectURL) {\n URL.revokeObjectURL(url);\n }\n return sanitizedData;\n } else if (scheme === 'data') {\n return this.#filter.sanitizeDataURL(url, options);\n }\n return this.#filter.sanitize(url, options);\n }\n\n /**\n * Synchronously sanitizes the given URL.\n * NOTE: `data` and `file` schemes must be explicitly allowed.\n * The `blob` scheme is not supported and will return `null`.\n * @param {string} url - URL.\n * @param {object} [opt] - options.\n * @param {string[]} [opt.allow] - The array of schemes to allow.\n * @param {string[]} [opt.deny] - The array of schemes to deny.\n * @param {string[]} [opt.only] - The array of specific schemes to allow.\n * @param {boolean} [opt.allowRelative] - Allow relative URLs.\n * @param {boolean} [opt.debug] - Enable debug mode.\n * @param {boolean} [opt.revokeObjectURL] - Revokes the Blob URL.\n * @param {number} [opt.maxLength] - The maximum allowed URL length.\n * @returns {string|null} The sanitized URL, or null if denied.\n */\n sanitizeURLSync(url, opt) {\n const { isValid, options, scheme } = this.#normalizeOptions(url, opt);\n if (isValid === false) {\n return null;\n }\n if (scheme === 'blob') {\n if (options.revokeObjectURL) {\n URL.revokeObjectURL(url);\n }\n return null;\n }\n return this.#filter.sanitize(url, options);\n }\n\n /**\n * Sanitizes the given URL and returns its parsed components.\n * NOTE: Blob URLs are not revoked after inspection.\n * @param {string} url - The URL string to inspect.\n * @returns {Promise<InspectedURLResult>} A promise resolving to the inspected URL result.\n */\n async inspectURL(url) {\n if (isString(url)) {\n const parsedURL = parseURL(url, null, true);\n if (parsedURL?.protocol === 'blob:') {\n try {\n const { buffer, mimeType } = await fetchBlobAsArrayBuffer(\n parsedURL.href\n );\n const base64Data = encodeBufferToBase64(buffer);\n const dataURL = `data:${mimeType ? `${mimeType};base64` : 'base64'},${base64Data}`;\n const inspectedURLResult = this.#inspect(dataURL);\n inspectedURLResult.input = url;\n return inspectedURLResult;\n } catch (e) {\n return { input: url, valid: false, reason: e.message };\n }\n }\n }\n return this.#inspect(url);\n }\n\n /**\n * Verifies if the given URI is valid and its scheme is allowed.\n * @param {string} uri - The URI string to verify.\n * @returns {boolean} True if the URI is syntactically valid and permitted.\n */\n isValidURI(uri) {\n return super.verifyURI(uri, this.#allowedSchemes);\n }\n}\n", "/*!\n * URL Sanitizer\n *\n * @license MIT\n * @copyright asamuzaK (Kazz)\n * @see {@link https://github.com/asamuzaK/urlSanitizer/blob/main/LICENSE}\n */\n\nimport { URLSanitizer } from './mjs/sanitize.js';\n\n/**\n * @typedef {import('./mjs/sanitize.js').InspectedURLResult} InspectedURLResult\n */\n\nexport { URLSanitizer };\n\n/* URLSanitizer instance */\nconst sanitizer = new URLSanitizer();\n\n/* aliases */\n/**\n * Asynchronously sanitizes the given URL.\n * NOTE: `blob`, `data`, and `file` schemes must be explicitly allowed.\n * Given a `blob` URL, it securely converts and returns a sanitized `data` URL.\n * @param {string} url - URL.\n * @param {object} [opt] - options.\n * @param {string[]} [opt.allow] - The array of schemes to allow.\n * @param {string[]} [opt.deny] - The array of schemes to deny.\n * @param {string[]} [opt.only] - The array of specific schemes to allow.\n * @param {boolean} [opt.allowRelative] - Allow relative URLs.\n * @param {boolean} [opt.debug] - Enable debug mode.\n * @param {boolean} [opt.revokeObjectURL] - Revokes the Blob URL after sanitization.\n * @param {number} [opt.maxBlobSize] - The maximum allowed Blob size in bytes.\n * @param {number} [opt.maxLength] - The maximum allowed URL length.\n * @returns {Promise<string|null>} A promise resolving to the sanitized URL, or null.\n */\nexport const sanitizeURL = async (url, opt) => sanitizer.sanitizeURL(url, opt);\n\n/**\n * Synchronously sanitizes the given URL.\n * NOTE: `data` and `file` schemes must be explicitly allowed.\n * The `blob` scheme is not supported and will return `null`.\n * @param {string} url - URL.\n * @param {object} [opt] - options.\n * @param {string[]} [opt.allow] - The array of schemes to allow.\n * @param {string[]} [opt.deny] - The array of schemes to deny.\n * @param {string[]} [opt.only] - The array of specific schemes to allow.\n * @param {boolean} [opt.allowRelative] - Allow relative URLs.\n * @param {boolean} [opt.debug] - Enable debug mode.\n * @param {boolean} [opt.revokeObjectURL] - Revokes the Blob URL.\n * @param {number} [opt.maxLength] - The maximum allowed URL length.\n * @returns {string|null} The sanitized URL, or null if denied.\n */\nexport const sanitizeURLSync = (url, opt) =>\n sanitizer.sanitizeURLSync(url, opt);\n\n/**\n * Sanitizes the given URL and returns its parsed components.\n * NOTE: Blob URLs are not revoked after inspection.\n * @param {string} url - The URL string to inspect.\n * @returns {Promise<InspectedURLResult>} A promise resolving to the inspected URL result.\n */\nexport const inspectURL = async url => sanitizer.inspectURL(url);\n\n/**\n * Checks if the given string is a valid URI and is registered.\n * @param {string} uri - The URI string to verify.\n * @returns {boolean} True if valid and registered, false otherwise.\n */\nexport const isValidURI = uri => sanitizer.isValidURI(uri);\n\n/**\n * @deprecated Use {@link isValidURI} instead.\n * @param {string} uri - The URI string to verify.\n * @returns {boolean} True if valid and registered, false otherwise.\n */\nexport const isURISync = uri => sanitizer.isValidURI(uri);\n\n/* export instance */\nexport default sanitizer;\n"],
5
- "mappings": "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",
6
- "names": ["DUMMY_BASE", "getType", "o", "isString", "logDebug", "message", "error", "PROPERTIES", "hookQueue", "domPurify", "target", "prop", "receiver", "purifier", "p", "args", "value", "REG_AMP", "REG_AMP_ENC", "REG_HASH", "REG_MIME_DOM", "REG_NON_ASCII", "REG_NUM_REF", "REG_PCT_ENC", "REG_QUERY", "REG_SCHEME", "REG_SCHEME_EXT", "REG_SCRIPT", "REG_SCRIPT_OR_BLOB", "REG_TAG_QUOT", "REG_URL_ENC", "REG_VERIFY_RELATIVE", "text_chars_default", "TEXT_CHAR_CODES", "text_chars_default", "WINDOWS1252_TO_UNICODE", "generateNonTextCharCodes", "charCodes", "i", "NON_TEXT_CHAR_CODES", "ENC_AMP", "ENC_NUM", "ENC_LT", "ENC_GT", "ENC_QUOT", "ENC_APOS", "ch", "ESCAPE_MAP", "HEX_TABLE", "_", "i", "IS_NODE", "NON_TEXT_PATTERN", "NON_TEXT_CHAR_CODES", "REG_NON_TEXT", "REG_NON_TEXT_G", "SHARED_BUFFER", "encoder", "decoder", "normalizeURL", "url", "isScheme", "isString", "normalized", "REG_NON_ASCII", "parseURL", "base", "normalize", "urlStr", "baseStr", "getSchemeParts", "protocol", "escapeURLEncodedHTMLChars", "ch", "isString", "target", "REG_URL_ENC", "ESCAPE_MAP", "truncateURL", "url", "str", "trimTrailingEmptyQueryAndHash", "REG_HASH", "REG_QUERY", "replaceNumCharRef", "match", "value", "num", "NON_TEXT_CHAR_CODES", "TEXT_CHAR_CODES", "codePoint", "WINDOWS1252_TO_UNICODE", "parseURLEncodedNumCharRef", "nest", "getType", "res", "REG_PCT_ENC", "REG_NON_TEXT_G", "depth", "previousRes", "REG_AMP", "REG_NUM_REF", "extractDataURLComponents", "pathname", "search", "hash", "comma", "mediaType", "dataPart", "data", "mediaTypes", "lastType", "isBase64", "parseBase64", "binStr", "cleanData", "bytes", "IS_NODE", "len", "SHARED_BUFFER", "text", "decoder", "REG_NON_TEXT", "encodeBufferToBase64", "buffer", "uint8arr", "chunks", "i", "SanitizeContext", "opt", "domPurifyInstance", "#compileRules", "allowRelative", "debug", "schemes", "allow", "deny", "only", "scheme", "#registerScheme", "normalized", "normalizeURL", "normalizedScheme", "REG_SCRIPT_OR_BLOB", "REG_SCHEME", "s", "REG_SCRIPT", "url", "logDebug", "truncateURL", "SanitizeFilter", "#defaultOpts", "options", "#process", "ctx", "urlObj", "parseURL", "REG_VERIFY_RELATIVE", "dummyURL", "DUMMY_BASE", "protocol", "hostname", "pathname", "search", "hash", "#sanitizeStandardURL", "schemeParts", "part", "#sanitizeDataURL", "mediaType", "mediaTypes", "data", "isBase64", "extractDataURLComponents", "parsedData", "parseBase64", "e", "decodedData", "parseURLEncodedNumCharRef", "parsedURL", "getSchemeParts", "REG_MIME_DOM", "#purify", "dom", "decodedDom", "purifiedDom", "node", "evt", "#handleSanitizeAttribute", "trimTrailingEmptyQueryAndHash", "originalURL", "sanitized", "urlToSanitize", "len", "truncateIndex", "matchTagQuot", "REG_TAG_QUOT", "matchAmp", "REG_AMP_ENC", "matchAmpIndex", "lastChar", "isString", "maxLength", "msg", "escapeURLEncodedHTMLChars", "domPurify", "buffer", "mimeType", "base64Data", "encodeBufferToBase64", "dataUrl", "uri_schemes_default", "URISchemes", "#schemes", "uri_schemes_default", "uri", "isString", "parsed", "scheme", "normalized", "isScheme", "normalizeURL", "schemes", "normalizedSchemes", "base", "normalize", "parseURL", "parsedUrl", "allowCustom", "targetSchemes", "REG_SCRIPT", "parts", "s", "REG_SCHEME_EXT", "URL_PROPS", "DEFAULT_OPTS", "readStreamInChunksAsArrayBuffer", "response", "maxSize", "reader", "chunks", "accumulatedSize", "done", "value", "combined", "offset", "chunk", "fetchBlobAsArrayBuffer", "url", "maxBlobSize", "msg", "truncateURL", "contentLength", "parsedLength", "mimeType", "buffer", "blob", "URLSanitizer", "URISchemes", "#allowedSchemes", "#defaultOpts", "#filter", "SanitizeFilter", "#isWellFormedScheme", "normalizedScheme", "isString", "REG_SCRIPT_OR_BLOB", "REG_SCRIPT", "REG_SCHEME", "#normalizeOptions", "opt", "options", "scheme", "#inspect", "inspectedURL", "sanitizedURL", "invalidReason", "e", "urlObj", "parseURL", "normalizeURL", "mediaTypes", "data", "isBase64", "extractDataURLComponents", "key", "getType", "isValid", "allow", "deny", "only", "sanitizedData", "fetchedBuffer", "fetchedMimeType", "fetchResult", "logDebug", "s", "parsedURL", "base64Data", "encodeBufferToBase64", "dataURL", "inspectedURLResult", "uri", "sanitizer", "URLSanitizer", "sanitizeURL", "url", "opt", "sanitizeURLSync", "inspectURL", "isValidURI", "uri", "isURISync", "index_default"]
4
+ "sourcesContent": ["/**\n * constant.js\n */\n\n/**\n * The total number of 8-bit byte values (0x00\u20130xFF).\n * @type {number}\n */\nexport const BYTE_RANGE = 256;\n\n/**\n * Chunk size (8KB) used when processing byte arrays to avoid stack overflow.\n * @type {number}\n */\nexport const CHUNK_SIZE = 8 * 1024;\n\n/**\n * Decimal radix used for numeric string conversion.\n * @type {number}\n */\nexport const DECI = 10;\n\n/**\n * Hexadecimal radix used for numeric string conversion.\n * @type {number}\n */\nexport const HEX = 16;\n\n/**\n * Maximum allowed Blob size (16MB).\n * @type {number}\n */\nexport const MAX_BLOB_SIZE = 16 * 1024 * 1024;\n\n/**\n * Maximum recursion depth allowed for nested parsing.\n * @type {number}\n */\nexport const MAX_NEST = 16;\n\n/**\n * Maximum URL length (64KB).\n * @type {number}\n */\nexport const MAX_URL_LENGTH = 64 * 1024;\n\n/**\n * Length used for truncating string.\n * @type {number}\n */\nexport const TRUNCATE_LENGTH = 64;\n\n/**\n * Start index used to extract the type name from Object.prototype.toString().\n * (e.g. removes \"[object \" prefix)\n * @type {number}\n */\nexport const TYPE_FROM = 8;\n\n/**\n * End index used to extract the type name from Object.prototype.toString().\n * (e.g. removes trailing \"]\")\n * @type {number}\n */\nexport const TYPE_TO = -1;\n\n/**\n * The dummy base URL.\n * @type {string}\n */\nexport const DUMMY_BASE = 'http://dummy.local';\n\n/**\n * The default sanitization options.\n * @type {import('./sanitize.js').InternalSanitizeOptions}\n */\nexport const DEFAULT_OPTS = {\n allow: Object.freeze([]),\n deny: Object.freeze([]),\n only: Object.freeze([]),\n allowRelative: false,\n debug: false,\n revokeObjectURL: false,\n maxBlobSize: MAX_BLOB_SIZE,\n maxLength: MAX_URL_LENGTH,\n schemes: new Set()\n};\n", "/**\n * common.js\n */\n\n/* shared */\nimport { TYPE_FROM, TYPE_TO } from './constant.js';\n\n/**\n * Gets the type of the given object.\n * Returns the object class name (e.g., \"String\", \"Array\", \"Null\", \"Undefined\").\n * @param {unknown} o - The object to check.\n * @returns {string} The specific type of the object.\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * Checks if the given value is a string.\n * @param {unknown} o - The value to check.\n * @returns {boolean} True if the value is a string, false otherwise.\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n\n/**\n * Debug logger.\n * @param {string} message - The message to output.\n * @param {Error} [error] - The caught error object, if any.\n * @returns {void}\n */\nexport const logDebug = (message, error) => {\n console.warn(`[URLSanitizer Debug] ${message}`, error);\n};\n", "/**\n * dompurify.js (for wo-dompurify build)\n */\n\n/* constants */\nconst PROPERTIES = Object.freeze([\n 'addHook',\n 'removeHook',\n 'removeAllHooks',\n 'setConfig'\n]);\n\nconst hookQueue = [];\nexport const domPurify = new Proxy({}, {\n get(target, prop, receiver) {\n const purifier = globalThis.DOMPurify || globalThis.window?.DOMPurify;\n if (purifier) {\n if (hookQueue.length) {\n for (const { prop: p, args } of hookQueue) {\n if (typeof purifier[p] === 'function') {\n purifier[p](...args);\n }\n }\n hookQueue.length = 0;\n }\n const value = purifier[prop];\n return typeof value === 'function' ? value.bind(purifier) : value;\n }\n return (...args) => {\n if (PROPERTIES.includes(prop)) {\n hookQueue.push({ prop, args });\n return receiver;\n }\n throw new Error('DOMPurify is not available. Ensure DOMPurify is exposed globally (e.g., window.DOMPurify).');\n };\n }\n});\n", "/**\n * regexp.js\n */\n\n/**\n * Matches HTML-encoded ampersands.\n * @type {RegExp}\n */\nexport const REG_AMP = /&amp;/gi;\n\n/**\n * Matches ampersand that may begin an HTML entity reference.\n * @type {RegExp}\n */\nexport const REG_AMP_ENC = /&(?=[#a-z0-9])(?![a-z0-9]+=)/i;\n\n/**\n * Matches and captures the charset parameter in a media type string.\n * @type {RegExp}\n */\nexport const REG_CHARSET = /^charset\\s*=\\s*([\"']?)(?<name>[\\w:-]+)\\1$/;\n\n/**\n * Matches a trailing empty fragment identifier (#).\n * @type {RegExp}\n */\nexport const REG_HASH = /#$/;\n\n/**\n * Matches MIME types that contain DOM-parsable content (HTML, XML, SVG).\n * @type {RegExp}\n */\nexport const REG_MIME_DOM =\n /^(?:application\\/(?:[\\w.-]+\\+)?xml|image\\/svg\\+xml|text\\/(?:html|xml))(?:\\s*;\\s*|$)/i;\n\n/**\n * Matches general text MIME types.\n * @type {RegExp}\n */\nexport const REG_MIME_TEXT = /^text\\/[\\w#&.;+-]+/i;\n\n/**\n * Matches non-ASCII character.\n * @type {RegExp}\n */\nexport const REG_NON_ASCII = /\\P{ASCII}/u;\n\n/**\n * Matches numeric character references (hex or decimal).\n * @type {RegExp}\n */\nexport const REG_NUM_REF = /&#(x0*[\\dA-F]{1,2}|0*\\d{1,3});?/gi;\n\n/**\n * Matches one or more consecutive percent-encoded sequences (%20, %E3%81%82).\n * @type {RegExp}\n */\nexport const REG_PCT_ENC = /(?:%[\\dA-F]{2})+/gi;\n\n/**\n * Matches a trailing empty query string (?), ensuring it is not part of a hash.\n * @type {RegExp}\n */\nexport const REG_QUERY = /^((?:[^#%]|%(?!23))*)\\?$/;\n\n/**\n * Validates a string against standard IANA URI scheme syntax.\n * @type {RegExp}\n */\nexport const REG_SCHEME = /^[a-z][\\da-z+.-]*$/;\n\n/**\n * Matches web custom schemes (`web+`) or application-specific schemes (`ext+`).\n * - `web+` schemes comply with the HTML Standard.\n * - `ext+` schemes comply with RFC 3986 but disallow `+` in the suffix.\n * @type {RegExp}\n */\nexport const REG_SCHEME_EXT = /^(?:web\\+[a-z]+|ext\\+[a-z][\\da-z.-]*)$/;\n\n/**\n * Matches executable script schemes (javascript or vbscript).\n * @type {RegExp}\n */\nexport const REG_SCRIPT = /^(?:java|vb)script$/i;\n\n/**\n * Matches script-executing or data-fetching schemes.\n * @type {RegExp}\n */\nexport const REG_SCRIPT_OR_BLOB = /^(?:(?:java|vb)script|blob)$/i;\n\n/**\n * Matches HTML-sensitive characters and their encoded variants.\n * @type {RegExp}\n */\nexport const REG_TAG_QUOT =\n /[\"'<>]|%(?:22|27|3C|3E)|&(?:apos|lt|gt|quot|#0*(?:34|39|60|62)|#x0*(?:22|27|3C|3E));/i;\n\n/**\n * Matches a percent-encoded character (%XX).\n * @type {RegExp}\n */\nexport const REG_URL_ENC = /^%[\\dA-F]{2}$/i;\n\n/**\n * Matches invalid relative URL patterns.\n * @type {RegExp}\n */\nexport const REG_VERIFY_RELATIVE = /^(?:\\/{2,}|\\\\|[a-z][a-z\\d+\\-.]*:[^/])/i;\n", "[9,10,13,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]\n", "/**\n * text-chars.js\n */\n\n/* shared */\nimport textChars from '../lib/file/text-chars.json' with { type: 'json' };\nimport { BYTE_RANGE, HEX } from './constant.js';\n\n/**\n * A set of valid text character codes.\n * @type {Set<number>}\n */\nexport const TEXT_CHAR_CODES = new Set(textChars);\n\n/**\n * A map of Windows-1252 codes and their corresponding Unicode code points.\n * @type {Map<number, number>}\n */\nexport const WINDOWS1252_TO_UNICODE = new Map([\n [128, 0x20ac],\n [130, 0x201a],\n [131, 0x0192],\n [132, 0x201e],\n [133, 0x2026],\n [134, 0x2020],\n [135, 0x2021],\n [136, 0x02c6],\n [137, 0x2030],\n [138, 0x0160],\n [139, 0x2039],\n [140, 0x0152],\n [142, 0x017d],\n [145, 0x2018],\n [146, 0x2019],\n [147, 0x201c],\n [148, 0x201d],\n [149, 0x2022],\n [150, 0x2013],\n [151, 0x2014],\n [152, 0x02dc],\n [153, 0x2122],\n [154, 0x0161],\n [155, 0x203a],\n [156, 0x0153],\n [158, 0x017e],\n [159, 0x0178]\n]);\n\n/**\n * Generates hexadecimal escape strings for non-text codes.\n * @private\n * @returns {Map<number, string>} The map of non-text codes and hexadecimal escape strings.\n */\nconst generateNonTextCharCodes = () => {\n const charCodes = new Map();\n for (let i = 0; i < BYTE_RANGE; i++) {\n if (!TEXT_CHAR_CODES.has(i) && !WINDOWS1252_TO_UNICODE.has(i)) {\n charCodes.set(i, `\\\\x${i.toString(HEX).padStart(2, '0').toUpperCase()}`);\n }\n }\n return charCodes;\n};\n\n/**\n * A map of non-text codes and their hexadecimal escape strings.\n * @type {Map<number, string>}\n */\nexport const NON_TEXT_CHAR_CODES = generateNonTextCharCodes();\n", "/**\n * utility.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\n\n/* constants */\nimport {\n BYTE_RANGE,\n CHUNK_SIZE,\n DECI,\n HEX,\n MAX_NEST,\n MAX_URL_LENGTH,\n TRUNCATE_LENGTH\n} from './constant.js';\nimport {\n REG_AMP,\n REG_HASH,\n REG_NON_ASCII,\n REG_NUM_REF,\n REG_PCT_ENC,\n REG_QUERY,\n REG_URL_ENC\n} from './regexp.js';\nimport {\n NON_TEXT_CHAR_CODES,\n TEXT_CHAR_CODES,\n WINDOWS1252_TO_UNICODE\n} from './text-chars.js';\nconst [ENC_AMP, ENC_NUM, ENC_LT, ENC_GT, ENC_QUOT, ENC_APOS] = [\n '&',\n '#',\n '<',\n '>',\n '\"',\n \"'\"\n].map(ch => `%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\nconst ESCAPE_MAP = {\n [ENC_AMP]: `${ENC_AMP}amp;`,\n [ENC_LT]: `${ENC_AMP}lt;`,\n [ENC_GT]: `${ENC_AMP}gt;`,\n [ENC_QUOT]: `${ENC_AMP}quot;`,\n [ENC_APOS]: `${ENC_AMP}${ENC_NUM}39;`\n};\nconst HEX_TABLE = Array.from(\n { length: BYTE_RANGE },\n (_, i) => `%${i.toString(HEX).padStart(2, '0').toUpperCase()}`\n);\nconst IS_NODE = globalThis.process?.versions?.node !== undefined;\nconst NON_TEXT_PATTERN = `[${[...NON_TEXT_CHAR_CODES.values()].join('')}]`;\nconst REG_NON_TEXT = new RegExp(NON_TEXT_PATTERN);\nconst REG_NON_TEXT_G = new RegExp(NON_TEXT_PATTERN, 'g');\nconst SHARED_BUFFER = new Uint8Array(MAX_URL_LENGTH);\n\n/* typedef */\n/**\n * The extracted Data URL components.\n * @typedef {object} DataURLComponents\n * @property {string} data - The actual data part of the Data URL.\n * @property {boolean} isBase64 - Indicates whether the data is base64-encoded.\n * @property {string} mediaType - The MIME type of the data.\n * @property {string[]} mediaTypes - The array of parsed media types.\n */\n\n/* encoder / decoder */\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder('utf-8', { fatal: true });\n\n/**\n * Normalizes the URL string using NFKC.\n * @param {string} url - The URL string to normalize.\n * @param {boolean} [isScheme] - True if the given `url` is a scheme.\n * @returns {string|null} The normalized URL string, or null.\n */\nexport const normalizeURL = (url, isScheme = false) => {\n if (!isString(url)) {\n return null;\n }\n const normalized = REG_NON_ASCII.test(url) ? url.normalize('NFKC') : url;\n if (isScheme) {\n return normalized.trim().toLowerCase().replace(/:$/, '');\n }\n return normalized;\n};\n\n/**\n * Parses a URL string with a fallback.\n * @param {string} url - The URL string to parse.\n * @param {string} [base] - The base URL string.\n * @param {boolean} [normalize] - Indicates whether to normalize the URI.\n * @returns {URL|null} The parsed URL object, or null.\n */\nexport const parseURL = (url, base, normalize = false) => {\n if (!isString(url) || url === '') {\n return null;\n }\n let urlStr = url;\n let baseStr = base && isString(base) ? base : '';\n if (normalize) {\n urlStr = normalizeURL(urlStr);\n if (baseStr) {\n baseStr = normalizeURL(baseStr);\n }\n }\n if (typeof URL.parse === 'function') {\n return baseStr ? URL.parse(urlStr, baseStr) : URL.parse(urlStr);\n }\n try {\n return baseStr ? new URL(urlStr, baseStr) : new URL(urlStr);\n } catch {\n return null;\n }\n};\n\n/**\n * Extracts an array of schemes.\n * @param {string} protocol - The URL protocol (e.g., \"data:\", \"git+https:\").\n * @returns {string[]} An array of scheme parts.\n */\nexport const getSchemeParts = protocol => {\n if (!isString(protocol)) {\n return [];\n }\n return protocol.replace(/:$/, '').split('+');\n};\n\n/**\n * Gets the URL-encoded representation of a given string.\n * @param {string} str - The target string.\n * @returns {string} The URL-encoded string.\n */\nexport const getURLEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const bytes = encoder.encode(str);\n const encoded = new Array(bytes.length);\n for (let i = 0; i < bytes.length; i++) {\n encoded[i] = HEX_TABLE[bytes[i]];\n }\n return encoded.join('');\n};\n\n/**\n * Escapes URL-encoded HTML special characters.\n * @param {string} ch - A URL-encoded (percent-encoded) character.\n * @returns {string} The escaped HTML special character, or the given character.\n */\nexport const escapeURLEncodedHTMLChars = ch => {\n if (!isString(ch)) {\n return ch;\n }\n const target = REG_URL_ENC.test(ch) ? ch.toUpperCase() : ch;\n return ESCAPE_MAP[target] ?? ch;\n};\n\n/**\n * Truncates the URL string.\n * @param {string|unknown} url - A URL string.\n * @returns {string} The truncated string.\n */\nexport const truncateURL = url => {\n const str = isString(url) ? url : String(url);\n const truncated =\n str.length > TRUNCATE_LENGTH ? `${str.slice(0, TRUNCATE_LENGTH)}...` : str;\n return truncated;\n};\n\n/**\n * Removes a trailing empty hash and an empty query string from a URL.\n * @param {string} url - The target URL string to be cleaned.\n * @returns {string} The cleaned URL string or the original input.\n */\nexport const trimTrailingEmptyQueryAndHash = url => {\n if (!isString(url)) {\n return url;\n }\n return url.replace(REG_HASH, '').replace(REG_QUERY, '$1');\n};\n\n/**\n * Replaces URL-encoded numeric character references.\n * @param {string} match - The matched substring.\n * @param {string} value - The captured numeric value.\n * @returns {string} The resolved character or the original match.\n */\nexport const replaceNumCharRef = (match, value) => {\n const num = /^x/i.test(value)\n ? Number.parseInt(value.slice(1), HEX)\n : Number.parseInt(value, DECI);\n if (!Number.isInteger(num) || num < 0 || num >= BYTE_RANGE) {\n return match;\n }\n if (NON_TEXT_CHAR_CODES.has(num)) {\n return '';\n }\n if (TEXT_CHAR_CODES.has(num)) {\n return String.fromCharCode(num);\n }\n const codePoint = WINDOWS1252_TO_UNICODE.get(num);\n return String.fromCodePoint(codePoint);\n};\n\n/**\n * Parses URL-encoded numeric character references.\n * @param {string} str - The target string to parse.\n * @param {number} [nest] - The current nesting depth for recursive parsing.\n * @returns {string} The decoded and parsed string.\n */\nexport const parseURLEncodedNumCharRef = (str, nest = 0) => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n if (!Number.isInteger(nest)) {\n throw new TypeError(`Expected Number but got ${getType(nest)}.`);\n }\n let res;\n try {\n res = decodeURIComponent(str);\n } catch {\n // Fallback: decode only valid multi-byte %XX sequences.\n res = str.replace(REG_PCT_ENC, match => {\n try {\n return decodeURIComponent(match);\n } catch {\n return match;\n }\n });\n }\n res = res.replace(REG_NON_TEXT_G, '');\n let depth = 0;\n for (; depth + nest < MAX_NEST; depth++) {\n const previousRes = res;\n // Decode '&amp;' before decoding numeric references.\n res = res.replace(REG_AMP, '&').replace(REG_NUM_REF, replaceNumCharRef);\n if (res === previousRes) {\n break;\n }\n }\n if (depth + nest >= MAX_NEST && /&#/.test(res)) {\n throw new Error('Character references nested too deeply.');\n }\n return res;\n};\n\n/**\n * Extracts the components of a parsed Data URL.\n * @param {string} pathname - The pathname of the URL.\n * @param {string} [search] - The search (query) string of the URL.\n * @param {string} [hash] - The hash (fragment) of the URL.\n * @returns {DataURLComponents} The DataURLComponents object.\n */\nexport const extractDataURLComponents = (pathname, search = '', hash = '') => {\n if (!isString(pathname)) {\n return { mediaType: '', mediaTypes: [], data: '', isBase64: false };\n }\n const comma = pathname.indexOf(',');\n if (comma === -1) {\n return {\n mediaType: pathname,\n mediaTypes: pathname.split(';'),\n data: '',\n isBase64: false\n };\n }\n const mediaType = pathname.substring(0, comma);\n const dataPart = pathname.substring(comma + 1);\n const data =\n search === '' && hash === '' ? dataPart : dataPart + search + hash;\n const mediaTypes = mediaType.split(';');\n const lastType = mediaTypes.at(-1);\n const isBase64 =\n lastType !== undefined &&\n lastType.length === 6 &&\n lastType.toLowerCase() === 'base64';\n\n return { mediaType, mediaTypes, data, isBase64 };\n};\n\n/**\n * Parses base64-encoded data.\n * @param {string} data - The base64-encoded string.\n * @returns {string} The parsed text, or the original base64 if binary.\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n }\n let binStr;\n let cleanData = data;\n try {\n binStr = atob(data);\n } catch {\n cleanData = data.replace(/\\s/g, '');\n try {\n binStr = atob(cleanData);\n } catch {\n throw new Error(`Invalid base64 data: ${truncateURL(data)}`);\n }\n }\n let bytes;\n if (IS_NODE && globalThis.Buffer) {\n // Use 'latin1' to correctly map the binary string directly to bytes.\n // @see https://nodejs.org/docs/latest/api/buffer.html#buffers-and-character-encodings\n bytes = globalThis.Buffer.from(binStr, 'latin1');\n } else {\n const len = binStr.length;\n if (len > MAX_URL_LENGTH) {\n bytes = new Uint8Array(len);\n } else {\n bytes = SHARED_BUFFER.subarray(0, len);\n }\n for (let i = 0; i < len; i++) {\n bytes[i] = binStr.charCodeAt(i);\n }\n }\n try {\n const text = decoder.decode(bytes);\n if (REG_NON_TEXT.test(text)) {\n return cleanData;\n }\n return text;\n } catch {\n return cleanData;\n }\n};\n\n/**\n * Encodes an ArrayBuffer to a Base64 string.\n * @private\n * @param {ArrayBuffer} buffer - The buffer to encode.\n * @returns {string} The Base64 string.\n */\nexport const encodeBufferToBase64 = buffer => {\n if (IS_NODE && globalThis.Buffer) {\n return globalThis.Buffer.from(buffer).toString('base64');\n }\n const uint8arr = new Uint8Array(buffer);\n if (typeof uint8arr.toBase64 === 'function') {\n return uint8arr.toBase64();\n }\n const chunks = [];\n for (let i = 0; i < uint8arr.length; i += CHUNK_SIZE) {\n chunks.push(String.fromCharCode(...uint8arr.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(chunks.join(''));\n};\n", "/**\n * filter.js\n */\n\n/* shared */\nimport { logDebug, isString } from './common.js';\nimport { domPurify } from './dompurify.js';\nimport {\n encodeBufferToBase64,\n escapeURLEncodedHTMLChars,\n extractDataURLComponents,\n getSchemeParts,\n normalizeURL,\n parseBase64,\n parseURL,\n parseURLEncodedNumCharRef,\n trimTrailingEmptyQueryAndHash,\n truncateURL\n} from './utility.js';\n\n/* typedef */\n/**\n * @typedef {import('dompurify').DOMPurify} DOMPurify\n * @typedef {import('../index.js').InspectedDataURL} InspectedDataURL\n * @typedef {import('../index.js').InspectedURLResult} InspectedURLResult\n * @typedef {import('../index.js').SanitizeOptions} SanitizeOptions\n * @typedef {import('./sanitize.js').InternalSanitizeOptions} InternalSanitizeOptions\n */\n\n/* constants */\nimport { DEFAULT_OPTS, DUMMY_BASE, MAX_NEST } from './constant.js';\nimport {\n REG_AMP_ENC,\n REG_MIME_DOM,\n REG_SCHEME,\n REG_SCRIPT,\n REG_SCRIPT_OR_BLOB,\n REG_TAG_QUOT,\n REG_VERIFY_RELATIVE\n} from './regexp.js';\n\n/**\n * Context manager for the sanitization process.\n */\nexport class SanitizeContext {\n /**\n * @param {DOMPurify} domPurifyInstance - The DOMPurify instance.\n * @param {InternalSanitizeOptions} opt - The internal sanitization options.\n */\n constructor(domPurifyInstance, opt = DEFAULT_OPTS) {\n this.domPurify = domPurifyInstance;\n this.nest = 0;\n this.recurse = new Set();\n this.restrictScheme = false;\n this.schemeMap = new Map([\n ['blob', false],\n ['data', false],\n ['file', false],\n ['javascript', false],\n ['vbscript', false]\n ]);\n this.#compileRules(opt);\n }\n\n /**\n * Compiles allow, deny, and only rules into the context.\n * @private\n * @param {InternalSanitizeOptions} opt - The internal sanitization options.\n */\n #compileRules(opt) {\n const { allowRelative, debug, allow, deny, only } = opt;\n this.allowRelative = !!allowRelative;\n this.debug = !!debug;\n if (Array.isArray(only) && only.length) {\n this.restrictScheme = true;\n for (const scheme of only) {\n this.#registerScheme(scheme);\n }\n } else {\n if (Array.isArray(allow) && allow.length) {\n for (const scheme of allow) {\n this.#registerScheme(scheme);\n }\n }\n if (Array.isArray(deny) && deny.length) {\n for (const scheme of deny) {\n const normalized = normalizeURL(scheme, true);\n if (normalized) {\n this.schemeMap.set(normalized, false);\n }\n }\n }\n }\n }\n\n /**\n * Register schemes for the 'allow' or 'only' options.\n * @private\n * @param {string} scheme - The scheme to register.\n * @returns {boolean} True if the scheme is successfully registered.\n */\n #registerScheme(scheme) {\n const normalizedScheme = normalizeURL(scheme, true);\n if (\n !normalizedScheme ||\n REG_SCRIPT_OR_BLOB.test(normalizedScheme) ||\n !REG_SCHEME.test(normalizedScheme)\n ) {\n return false;\n }\n if (normalizedScheme.includes('+')) {\n const isScript = normalizedScheme\n .split('+')\n .some(s => REG_SCRIPT.test(s));\n if (isScript) {\n return false;\n }\n }\n this.schemeMap.set(normalizedScheme, true);\n return true;\n }\n\n /**\n * Tracks the URL to prevent circular references.\n * @param {string} url - The URL being processed.\n * @returns {boolean} True if safe to proceed, false otherwise.\n */\n enter(url) {\n if (this.recurse.has(url)) {\n if (this.debug) {\n logDebug(`Circular Data URL detected and skipped: ${truncateURL(url)}`);\n }\n return false;\n }\n this.nest++;\n this.recurse.add(url);\n return true;\n }\n\n /**\n * Cleans up the tracking state after processing the URL.\n * @param {string} url - The URL that finished processing.\n */\n leave(url) {\n this.nest--;\n this.recurse.delete(url);\n }\n}\n\n/**\n * An executor for sanitization filters.\n */\nexport class SanitizeFilter {\n /* private fields */\n #defaultOpts;\n\n /**\n * @param {InternalSanitizeOptions} opt - The default sanitization options.\n */\n constructor(opt = DEFAULT_OPTS) {\n this.#defaultOpts = opt;\n }\n\n /**\n * Process recursive method for sanitization.\n * @private\n * @param {string} url - The URL string to sanitize.\n * @param {SanitizeContext} ctx - The sanitization context.\n * @returns {string|null} The sanitized URL, or null.\n */\n #process(url, ctx) {\n if (ctx.nest > MAX_NEST) {\n throw new Error('Data URLs nested too deeply.');\n }\n const urlObj = parseURL(url, null, true);\n if (!urlObj) {\n if (ctx.allowRelative && !REG_VERIFY_RELATIVE.test(url)) {\n const dummyURL = parseURL(url, DUMMY_BASE);\n if (dummyURL) {\n const { protocol, hostname, pathname, search, hash } = dummyURL;\n if (protocol === 'http:' && hostname === 'dummy.local') {\n return this.#sanitizeStandardURL(`${pathname}${search}${hash}`);\n }\n }\n }\n return null;\n }\n const scheme = normalizeURL(urlObj.protocol, true);\n if (ctx.restrictScheme && !ctx.schemeMap.has(scheme)) {\n return null;\n }\n if (scheme.includes('+')) {\n const schemeParts = scheme.split('+');\n if (\n ctx.schemeMap.get(scheme) === false ||\n schemeParts.some(part => ctx.schemeMap.get(part) === false)\n ) {\n return null;\n }\n } else if (ctx.schemeMap.get(scheme) === false) {\n return null;\n }\n if (scheme === 'data') {\n return this.#sanitizeDataURL(urlObj, ctx);\n }\n return this.#sanitizeStandardURL(urlObj.href);\n }\n\n /**\n * Decodes, verifies inner protocols, and purifies Data URLs.\n * @private\n * @param {URL} urlObj - The URL object.\n * @param {SanitizeContext} ctx - The sanitization context.\n * @returns {string|null} Sanitized Data URL or null.\n */\n #sanitizeDataURL(urlObj, ctx) {\n const { mediaType, mediaTypes, data, isBase64 } = extractDataURLComponents(\n urlObj.pathname,\n urlObj.search,\n urlObj.hash\n );\n let parsedData = data;\n if (isBase64) {\n try {\n parsedData = parseBase64(data);\n } catch (e) {\n if (ctx.debug) {\n logDebug('Failed to parse base64 data.', e);\n }\n return null;\n }\n }\n try {\n const decodedData = parseURLEncodedNumCharRef(parsedData).trim();\n const parsedURL = parseURL(decodedData, DUMMY_BASE);\n if (!parsedURL) {\n return null;\n }\n const dataSchemeParts = getSchemeParts(parsedURL.protocol);\n if (dataSchemeParts.some(s => REG_SCRIPT_OR_BLOB.test(s))) {\n return null;\n }\n } catch (e) {\n if (ctx.debug) {\n logDebug('Failed to parse inner data URL protocol.', e);\n }\n return null;\n }\n if (!mediaType || REG_MIME_DOM.test(mediaType)) {\n parsedData = this.#purify(parsedData, ctx);\n }\n if (parsedData) {\n if (isBase64 && parsedData !== data) {\n mediaTypes.pop();\n }\n return `data:${mediaTypes.join(';')},${parsedData}`;\n }\n return null;\n }\n\n /**\n * Purifies a URL-encoded DOM string to prevent XSS.\n * @private\n * @param {string} dom - The URL-encoded DOM string.\n * @param {SanitizeContext} ctx - The sanitization context.\n * @returns {string|null} The purified DOM string or null.\n */\n #purify(dom, ctx) {\n let decodedDom = '';\n try {\n decodedDom = decodeURIComponent(dom);\n } catch {\n decodedDom = dom;\n }\n const hook = (node, evt) => this.#handleSanitizeAttribute(node, evt, ctx);\n let purifiedDom = '';\n try {\n ctx.domPurify.addHook('uponSanitizeAttribute', hook);\n purifiedDom = ctx.domPurify.sanitize(decodedDom);\n } finally {\n ctx.domPurify.removeHook('uponSanitizeAttribute', hook);\n }\n if (!purifiedDom) {\n return null;\n }\n try {\n return encodeURI(trimTrailingEmptyQueryAndHash(purifiedDom));\n } catch {\n return null;\n }\n }\n\n /**\n * Internal handler for the DOMPurify hook.\n * @private\n * @param {Node} node - The DOM node.\n * @param {object} evt - The event object.\n * @param {SanitizeContext} ctx - The sanitization context.\n */\n #handleSanitizeAttribute(node, evt, ctx) {\n if (!evt.attrValue || !/^\\s*data:/i.test(evt.attrValue)) {\n return;\n }\n const urlObj = parseURL(evt.attrValue, null, true);\n if (!urlObj || urlObj.protocol !== 'data:') {\n return;\n }\n const originalURL = evt.attrValue;\n if (!ctx.enter(originalURL)) {\n evt.attrValue = '';\n return;\n }\n try {\n const sanitized = this.#process(originalURL, ctx);\n evt.attrValue = sanitized || '';\n } finally {\n ctx.leave(originalURL);\n }\n }\n\n /**\n * Sanitizes URLs by stripping out problematic characters.\n * @private\n * @param {string} urlToSanitize - The absolute/relative URL.\n * @returns {string} The sanitized URL.\n */\n #sanitizeStandardURL(urlToSanitize) {\n const len = urlToSanitize.length;\n let truncateIndex = len;\n const matchTagQuot = REG_TAG_QUOT.exec(urlToSanitize);\n if (matchTagQuot) {\n truncateIndex = matchTagQuot.index;\n }\n if (urlToSanitize.indexOf('&') > -1) {\n const matchAmp = REG_AMP_ENC.exec(urlToSanitize);\n if (matchAmp) {\n const matchAmpIndex = matchAmp.index;\n if (matchAmpIndex < truncateIndex) {\n truncateIndex = matchAmpIndex;\n }\n }\n }\n if (truncateIndex === len) {\n return urlToSanitize;\n }\n const lastChar = urlToSanitize.charCodeAt(truncateIndex - 1);\n if (lastChar === 63 /* ? */ || lastChar === 38 /* & */) {\n truncateIndex--;\n }\n return urlToSanitize.substring(0, truncateIndex);\n }\n\n /**\n * Sanitizes the URL.\n * @param {string} url - The URL string to sanitize.\n * @param {InternalSanitizeOptions} opt - The internal sanitization options.\n * @returns {string|null} The sanitized URL, or null.\n */\n sanitize(url, opt = this.#defaultOpts) {\n if (!url || !isString(url)) {\n return null;\n }\n const { deny, maxLength, only, allowRelative } = opt;\n if (Number.isInteger(maxLength) && url.length > maxLength) {\n const msg = `URL length ${url.length} exceeds max length ${maxLength}.`;\n throw new RangeError(msg);\n }\n const hasRestrictiveRules =\n (Array.isArray(deny) && deny.length > 0) ||\n (Array.isArray(only) && only.length > 0) ||\n allowRelative;\n // Early return for standard HTTP/HTTPS URLs without restrictive rules.\n if (\n !hasRestrictiveRules &&\n /^https?:\\/\\//.test(url) &&\n !REG_TAG_QUOT.test(url) &&\n !url.includes('data:')\n ) {\n const urlObj = parseURL(url, null, true);\n if (urlObj && opt.schemes.has(urlObj.protocol.replace(/:$/, ''))) {\n return urlObj.href.replace(/%26/g, escapeURLEncodedHTMLChars);\n }\n return null;\n }\n const ctx = new SanitizeContext(domPurify, opt);\n return this.#process(url, ctx);\n }\n\n /**\n * Asynchronously sanitizes an ArrayBuffer and converts it to a Data URL.\n * @param {ArrayBuffer} buffer - The target buffer.\n * @param {string} mimeType - The MIME type of the buffer.\n * @param {InternalSanitizeOptions} opt - The internal sanitization options.\n * @returns {Promise<string|null>} The sanitized Data URL, or null.\n */\n async sanitizeBuffer(buffer, mimeType, opt = this.#defaultOpts) {\n if (!(buffer instanceof ArrayBuffer)) {\n return null;\n }\n const base64Data = encodeBufferToBase64(buffer);\n const mime = mimeType ? `${mimeType};base64` : 'base64';\n const dataUrl = `data:${mime},${base64Data}`;\n if (Number.isInteger(opt.maxLength) && dataUrl.length > opt.maxLength) {\n throw new RangeError(\n `URL length ${dataUrl.length} exceeds max length ${opt.maxLength}.`\n );\n }\n const ctx = new SanitizeContext(domPurify, opt);\n if (!ctx.schemeMap.get('data')) {\n return null;\n }\n const urlObj = parseURL(dataUrl);\n if (!urlObj) {\n return null;\n }\n return this.#sanitizeDataURL(urlObj, ctx);\n }\n\n /**\n * Asynchronously sanitizes the Data URL.\n * @param {string} url - The URL string to sanitize.\n * @param {InternalSanitizeOptions} opt - The internal sanitization options.\n * @returns {Promise<string|null>} The sanitized Data URL, or null.\n */\n async sanitizeDataURL(url, opt = this.#defaultOpts) {\n if (!url || !isString(url)) {\n return null;\n }\n const { maxLength } = opt;\n if (Number.isInteger(maxLength) && url.length > maxLength) {\n throw new RangeError(\n `URL length ${url.length} exceeds max length ${maxLength}.`\n );\n }\n const urlObj = parseURL(url);\n if (!urlObj) {\n return null;\n }\n const scheme = normalizeURL(urlObj.protocol, true);\n if (scheme !== 'data') {\n return null;\n }\n const ctx = new SanitizeContext(domPurify, opt);\n if (!ctx.schemeMap.get(scheme)) {\n return null;\n }\n return this.#sanitizeDataURL(urlObj, ctx);\n }\n}\n", "[\"aaa\",\"aaas\",\"about\",\"acap\",\"acct\",\"acd\",\"acr\",\"adiumxtra\",\"adt\",\"aet\",\"afp\",\"afs\",\"agtp\",\"aim\",\"amss\",\"android\",\"appdata\",\"apt\",\"ar\",\"ari\",\"ark\",\"ars\",\"at\",\"attachment\",\"aw\",\"barion\",\"beshare\",\"bitcoin\",\"bitcoincash\",\"bl\",\"blob\",\"bluetooth\",\"bolo\",\"brid\",\"browserext\",\"cabal\",\"caip\",\"calculator\",\"callto\",\"cap\",\"cast\",\"casts\",\"chrome\",\"chrome-extension\",\"cid\",\"cm\",\"coap\",\"coaps\",\"com-eventbrite-attendee\",\"content\",\"content-type\",\"crid\",\"cstr\",\"cttps\",\"cvs\",\"dab\",\"dat\",\"data\",\"dav\",\"dhttp\",\"diaspora\",\"dict\",\"did\",\"dilithium3\",\"dis\",\"dlna-playcontainer\",\"dlna-playsingle\",\"dnp\",\"dns\",\"dntp\",\"doi\",\"donau\",\"dpp\",\"drm\",\"dtmi\",\"dtn\",\"dvb\",\"dvx\",\"dweb\",\"ed2k\",\"eid\",\"elsi\",\"embedded\",\"ens\",\"esim\",\"ethereum\",\"example\",\"ez\",\"facetime\",\"feed\",\"feedready\",\"fido\",\"file\",\"finger\",\"first-run-pen-experience\",\"fish\",\"fm\",\"ftp\",\"fuchsia-pkg\",\"gcx\",\"gdsi\",\"geo\",\"gg\",\"git\",\"gitoid\",\"gizmoproject\",\"go\",\"gopher\",\"graph\",\"gtalk\",\"h323\",\"ham\",\"hcap\",\"hcp\",\"hs20\",\"http\",\"https\",\"hxxp\",\"hxxps\",\"hydrazone\",\"hyper\",\"i0\",\"iax\",\"ibi\",\"ibi-\",\"icap\",\"icon\",\"ilstring\",\"im\",\"imap\",\"info\",\"interaction\",\"iotdisco\",\"ipfs\",\"ipn\",\"ipns\",\"ipp\",\"ipps\",\"irc\",\"irc6\",\"ircs\",\"iris\",\"iris.beep\",\"iris.lwz\",\"iris.xpc\",\"iris.xpcs\",\"isostore\",\"itms\",\"jabber\",\"jar\",\"jms\",\"keyparc\",\"lastfm\",\"lbry\",\"ldap\",\"ldaps\",\"leaptofrogans\",\"lid\",\"linkid\",\"lorawan\",\"lpa\",\"lvlt\",\"machineProvisioningProgressReporter\",\"magnet\",\"mailto\",\"maps\",\"market\",\"matrix\",\"mdoc\",\"mdoc-openid4vp\",\"message\",\"microsoft.windows.camera\",\"microsoft.windows.camera.multipicker\",\"microsoft.windows.camera.picker\",\"mid\",\"mms\",\"mongodb\",\"moz\",\"moz-extension\",\"mqtt\",\"mqtts\",\"ms-access\",\"ms-appinstaller\",\"ms-browser-extension\",\"ms-calculator\",\"ms-drive-to\",\"ms-enrollment\",\"ms-excel\",\"ms-eyecontrolspeech\",\"ms-gamebarservices\",\"ms-gamingoverlay\",\"ms-getoffice\",\"ms-help\",\"ms-infopath\",\"ms-inputapp\",\"ms-launchremotedesktop\",\"ms-lockscreencomponent-config\",\"ms-media-stream-id\",\"ms-meetnow\",\"ms-mixedrealitycapture\",\"ms-mobileplans\",\"ms-newsandinterests\",\"ms-officeapp\",\"ms-people\",\"ms-personacard\",\"ms-powerpoint\",\"ms-project\",\"ms-publisher\",\"ms-recall\",\"ms-remotedesktop\",\"ms-remotedesktop-launch\",\"ms-restoretabcompanion\",\"ms-screenclip\",\"ms-screensketch\",\"ms-search\",\"ms-search-repair\",\"ms-secondary-screen-controller\",\"ms-secondary-screen-setup\",\"ms-settings\",\"ms-settings-airplanemode\",\"ms-settings-bluetooth\",\"ms-settings-camera\",\"ms-settings-cellular\",\"ms-settings-cloudstorage\",\"ms-settings-connectabledevices\",\"ms-settings-displays-topology\",\"ms-settings-emailandaccounts\",\"ms-settings-language\",\"ms-settings-location\",\"ms-settings-lock\",\"ms-settings-nfctransactions\",\"ms-settings-notifications\",\"ms-settings-power\",\"ms-settings-privacy\",\"ms-settings-proximity\",\"ms-settings-screenrotation\",\"ms-settings-wifi\",\"ms-settings-workplace\",\"ms-spd\",\"ms-stickers\",\"ms-sttoverlay\",\"ms-transit-to\",\"ms-useractivityset\",\"ms-uup\",\"ms-virtualtouchpad\",\"ms-visio\",\"ms-walk-to\",\"ms-whiteboard\",\"ms-whiteboard-cmd\",\"ms-widgetboard\",\"ms-widgets\",\"ms-word\",\"msnim\",\"msrp\",\"msrps\",\"mss\",\"mt\",\"mtqp\",\"mtrust\",\"mumble\",\"mupdate\",\"musik\",\"mvn\",\"mvrp\",\"mvrps\",\"news\",\"nfs\",\"ni\",\"nih\",\"nntp\",\"nostr\",\"notes\",\"npamp\",\"num\",\"ocf\",\"oid\",\"onenote\",\"onenote-cmd\",\"opaquelocktoken\",\"openid\",\"openpgp4fpr\",\"otpauth\",\"palm\",\"paparazzi\",\"payto\",\"pkcs11\",\"pkg\",\"platform\",\"pop\",\"pres\",\"proxy\",\"psyc\",\"pttp\",\"pwid\",\"qb\",\"query\",\"quic-transport\",\"redis\",\"rediss\",\"reload\",\"res\",\"resource\",\"rmi\",\"rsync\",\"rtmfp\",\"rtmp\",\"rtsp\",\"rtsps\",\"rtspu\",\"sarif\",\"secondlife\",\"secret-token\",\"service\",\"session\",\"sftp\",\"sgn\",\"shc\",\"shelter\",\"sieve\",\"simpleledger\",\"simplex\",\"sip\",\"sips\",\"skype\",\"smb\",\"smp\",\"sms\",\"smtp\",\"snmp\",\"soap.beep\",\"soap.beeps\",\"soldat\",\"spacify\",\"spiffe\",\"spotify\",\"ssb\",\"ssh\",\"sss\",\"starknet\",\"steam\",\"stun\",\"stuns\",\"submit\",\"svn\",\"swh\",\"swid\",\"swidpath\",\"tag\",\"taler\",\"teamspeak\",\"teapot\",\"teapots\",\"tel\",\"teliaeid\",\"telnet\",\"tftp\",\"things\",\"thismessage\",\"tip\",\"tn3270\",\"tool\",\"tttps\",\"turn\",\"turns\",\"tv\",\"udp\",\"unreal\",\"upn\",\"urn\",\"ust\",\"ut2004\",\"uuaid\",\"uuid-in-package\",\"v-event\",\"vemmi\",\"ventrilo\",\"ves\",\"view-source\",\"vnc\",\"vscode\",\"vscode-insiders\",\"vsls\",\"w3\",\"wasm\",\"wasm-js\",\"wcr\",\"web3\",\"webcal\",\"wifi\",\"ws\",\"wss\",\"wtai\",\"wyciwyg\",\"xcompute\",\"xcon\",\"xcon-userid\",\"xfire\",\"xftp\",\"xmlrpc.beep\",\"xmlrpc.beeps\",\"xmpp\",\"xrcp\",\"xri\",\"ymsgr\",\"z39.50r\",\"z39.50s\",\"ztdnaid\"]\n", "/**\n * scheme.js\n */\n\n/* shared */\nimport uriSchemes from '../lib/iana/uri-schemes.json' with { type: 'json' };\nimport { isString } from './common.js';\nimport { normalizeURL, parseURL } from './utility.js';\n\n/* constants */\nimport { REG_SCHEME_EXT, REG_SCRIPT } from './regexp.js';\n\n/**\n * URI schemes\n */\nexport class URISchemes {\n /* private fields */\n #schemes = new Set(uriSchemes);\n\n /**\n * Gets the list of registered URI schemes.\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes are omitted.\n * - The 'moz-extension' scheme is added by default.\n * @returns {string[]} An array of registered schemes.\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * Extracts the scheme from URI.\n * @param {string} uri - The URI string.\n * @returns {string|null} The extracted scheme, or null.\n */\n getScheme(uri) {\n if (!isString(uri)) {\n return null;\n }\n const parsed = this.parse(uri);\n if (parsed) {\n return this.normalize(parsed.protocol, true);\n }\n return null;\n }\n\n /**\n * Checks if the specified scheme is currently registered.\n * @param {string} scheme - The target scheme.\n * @returns {boolean} True if the scheme is registered.\n */\n has(scheme) {\n const normalized = this.normalize(scheme, true);\n if (normalized) {\n return this.#schemes.has(normalized);\n }\n return false;\n }\n\n /**\n * Normalizes the URI string using NFKC.\n * @param {string} uri - The URI string to normalize.\n * @param {boolean} [isScheme] - True if the URI is a scheme.\n * @returns {string|null} The normalized URI string, or null.\n */\n normalize(uri, isScheme = false) {\n return normalizeURL(uri, isScheme);\n }\n\n /**\n * Normalizes an array of scheme strings.\n * Filters out non-string items and trims/lowercases valid schemes.\n * @param {string[]} schemes - An array of scheme strings to normalize.\n * @returns {string[]} An array of normalized scheme strings, or an empty array if invalid.\n */\n normalizeSchemes(schemes) {\n if (Array.isArray(schemes)) {\n const normalizedSchemes = [];\n for (const scheme of schemes) {\n const normalized = normalizeURL(scheme, true);\n if (normalized) {\n normalizedSchemes.push(normalized);\n }\n }\n return normalizedSchemes;\n }\n return [];\n }\n\n /**\n * Parses the URI/URL string.\n * @param {string} uri - The URI/URL string.\n * @param {string} [base] - The base URL string.\n * @param {boolean} [normalize] - Indicates whether to normalize the URI.\n * @returns {URL|null} The parsed URL object, or null.\n */\n parse(uri, base, normalize = false) {\n return parseURL(uri, base, normalize);\n }\n\n /**\n * Verifies if the given URI is valid and its scheme is allowed.\n * @param {string} uri - The URI string to verify.\n * @param {Set<string>} [schemes] - The set of allowed schemes.\n * @returns {boolean} True if the URI is valid and permitted.\n */\n verifyURI(uri, schemes) {\n if (!isString(uri)) {\n return false;\n }\n const parsedUrl = this.parse(uri);\n if (!parsedUrl) {\n return false;\n }\n return this.verifyScheme(parsedUrl.protocol, schemes, true);\n }\n\n /**\n * Verifies if the scheme is valid and allowed.\n * @param {string} scheme - A scheme or URL.protocol to verify.\n * @param {Set<string>} [schemes] - The set of allowed schemes.\n * @param {boolean} [allowCustom] - True if web+*, ext+* schemes are allowed.\n * @returns {boolean} True if the parsed URL is valid and permitted.\n */\n verifyScheme(scheme, schemes, allowCustom = false) {\n const normalized = this.normalize(scheme, true);\n if (!normalized) {\n return false;\n }\n const targetSchemes = schemes || this.#schemes;\n if (!normalized.includes('+')) {\n if (REG_SCRIPT.test(normalized)) {\n return false;\n }\n return targetSchemes.has(normalized);\n }\n const parts = normalized.split('+');\n const isScript = parts.some(s => REG_SCRIPT.test(s));\n if (isScript) {\n return false;\n }\n if (targetSchemes.has(normalized)) {\n return true;\n }\n return (\n (allowCustom && REG_SCHEME_EXT.test(normalized)) ||\n parts.every(s => targetSchemes.has(s))\n );\n }\n}\n", "/**\n * sanitize.js\n */\n\n/* shared */\nimport { getType, logDebug, isString } from './common.js';\nimport { SanitizeFilter } from './filter.js';\nimport { URISchemes } from './scheme.js';\nimport {\n encodeBufferToBase64,\n extractDataURLComponents,\n normalizeURL,\n parseURL,\n truncateURL\n} from './utility.js';\n\n/* constants */\nimport { DECI, DEFAULT_OPTS, MAX_BLOB_SIZE } from './constant.js';\nimport { REG_SCHEME, REG_SCRIPT, REG_SCRIPT_OR_BLOB } from './regexp.js';\n/* @type {string[]} */\nconst URL_PROPS = Object.freeze([\n 'href',\n 'origin',\n 'protocol',\n 'username',\n 'password',\n 'host',\n 'hostname',\n 'port',\n 'pathname',\n 'search',\n 'hash'\n]);\n\n/* typedef */\n/**\n * @typedef {import('../index.js').InspectedDataURL} InspectedDataURL\n * @typedef {import('../index.js').InspectedURLResult} InspectedURLResult\n * @typedef {import('../index.js').SanitizeOptions} SanitizeOptions\n */\n\n/**\n * Internal sanitization options.\n * @typedef {SanitizeOptions & { schemes?: Set<string> }} InternalSanitizeOptions\n */\n\n/* blob handlers */\n/**\n * Reads a stream in chunks and generates an ArrayBuffer.\n * @private\n * @param {Response} response - The Response instance.\n * @param {number} maxSize - The maximum allowed size in bytes.\n * @returns {Promise<ArrayBuffer>} A promise resolving to the generated ArrayBuffer.\n */\nconst readStreamInChunksAsArrayBuffer = async (response, maxSize) => {\n const reader = response.body.getReader();\n const chunks = [];\n try {\n let accumulatedSize = 0;\n while (accumulatedSize <= maxSize) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n accumulatedSize += value.byteLength;\n if (accumulatedSize > maxSize) {\n await reader.cancel('Size limit exceeded');\n throw new DOMException(\n `Payload (${accumulatedSize} bytes) exceeds max (${maxSize} bytes).`,\n 'NotReadableError'\n );\n }\n chunks.push(value);\n }\n const combined = new Uint8Array(accumulatedSize);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return combined.buffer;\n } finally {\n reader.releaseLock();\n }\n};\n\n/**\n * Fetches a Blob URL and extracts its ArrayBuffer and MIME type.\n * @private\n * @param {string} url - The Blob URL to fetch.\n * @param {number} [maxBlobSize] - The maximum allowed Blob size in bytes.\n * @returns {Promise<{ buffer: ArrayBuffer, mimeType: string }>} A promise resolving to the buffer and MIME type.\n */\nconst fetchBlobAsArrayBuffer = async (url, maxBlobSize) => {\n let maxSize = MAX_BLOB_SIZE;\n if (Number.isInteger(maxBlobSize) && maxBlobSize > 0) {\n maxSize = maxBlobSize;\n }\n const response = await fetch(url);\n if (!response.ok) {\n const truncatedURL = truncateURL(url);\n let msg = `Failed to fetch ${truncatedURL}`;\n if (Number.isInteger(response.status)) {\n if (response.statusText) {\n msg += `: ${response.status} ${response.statusText}`;\n } else {\n msg += `: ${response.status}`;\n }\n }\n throw new Error(msg);\n }\n const contentLength = response.headers.get('content-length');\n if (contentLength) {\n const parsedLength = Number.parseInt(contentLength, DECI);\n if (Number.isInteger(parsedLength) && parsedLength > maxSize) {\n throw new DOMException(\n `Payload (${parsedLength} bytes) exceeds max (${maxSize} bytes).`,\n 'NotReadableError'\n );\n }\n }\n const mimeType = response.headers.get('content-type') || '';\n let buffer;\n if (response.body) {\n buffer = await readStreamInChunksAsArrayBuffer(response, maxSize);\n } else {\n const blob = await response.blob();\n if (blob.size > maxSize) {\n throw new DOMException(\n `Payload (${blob.size} bytes) exceeds max (${maxSize} bytes).`,\n 'NotReadableError'\n );\n }\n buffer = await blob.arrayBuffer();\n }\n return { buffer, mimeType };\n};\n\n/**\n * URL sanitizer\n */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #allowedSchemes;\n #defaultOpts;\n #filter;\n\n constructor() {\n super();\n this.#allowedSchemes = new Set(super.get());\n this.#defaultOpts = {\n ...DEFAULT_OPTS,\n schemes: this.#allowedSchemes\n };\n this.#filter = new SanitizeFilter(this.#defaultOpts);\n }\n\n /**\n * Validates if a normalized URI scheme is syntactically correct.\n * @private\n * @param {string} normalizedScheme - The normalized URI scheme to validate.\n * @returns {boolean} True if the scheme satisfies the syntax and requirements.\n */\n #isWellFormedScheme(normalizedScheme) {\n if (\n !isString(normalizedScheme) ||\n REG_SCRIPT_OR_BLOB.test(normalizedScheme)\n ) {\n return false;\n }\n if (normalizedScheme.includes('+')) {\n const isScript = normalizedScheme\n .split('+')\n .some(s => REG_SCRIPT.test(s));\n if (isScript) {\n return false;\n }\n }\n return REG_SCHEME.test(normalizedScheme);\n }\n\n /**\n * Normalizes options and evaluates preliminary scheme routing.\n * @private\n * @param {string} url - The URL string.\n * @param {SanitizeOptions} [opt] - The sanitization options.\n * @returns {{ isValid: boolean|undefined, options: InternalSanitizeOptions, scheme: string|null }} Normalized options, scheme, and isValid.\n */\n #normalizeOptions(url, opt = {}) {\n if (!isString(url) || url === '') {\n return { isValid: false };\n }\n const options = {\n ...this.#defaultOpts,\n ...opt,\n allow: this.normalizeSchemes(opt.allow),\n deny: this.normalizeSchemes(opt.deny),\n only: this.normalizeSchemes(opt.only),\n schemes: this.#allowedSchemes\n };\n const scheme = this.getScheme(url);\n if (scheme === null && !options.allowRelative) {\n return { isValid: false };\n }\n return { options, scheme };\n }\n\n /**\n * Inspects, parses, and sanitizes the given URL.\n * @private\n * @param {string} url - The URL string to parse.\n * @returns {InspectedURLResult} The result of an inspected URL.\n */\n #inspect(url) {\n const inspectedURL = {\n input: url,\n href: null,\n valid: false\n };\n if (!isString(url)) {\n inspectedURL.reason = `Invalid URL input: ${truncateURL(url)}`;\n return inspectedURL;\n }\n if (url === '') {\n inspectedURL.reason = 'Invalid URL input: (empty string)';\n return inspectedURL;\n }\n let sanitizedURL;\n let invalidReason = null;\n try {\n sanitizedURL = this.#filter.sanitize(url, {\n ...this.#defaultOpts,\n allow: ['data'],\n allowRelative: true,\n schemes: this.#allowedSchemes\n });\n if (!sanitizedURL) {\n invalidReason =\n 'Sanitization failed (blocked by allowed schemes or rules).';\n }\n } catch (e) {\n invalidReason = e.message;\n }\n if (sanitizedURL) {\n // Reparse the sanitized string to safely extract updated properties.\n const urlObj = parseURL(sanitizedURL);\n inspectedURL.valid = true;\n if (urlObj) {\n const scheme = normalizeURL(urlObj.protocol, true);\n if (scheme === 'data') {\n const { mediaTypes, data, isBase64 } = extractDataURLComponents(\n urlObj.pathname,\n urlObj.search,\n urlObj.hash\n );\n if (isBase64) {\n mediaTypes.pop();\n }\n inspectedURL.data = {\n mime: mediaTypes.join(';'),\n base64: isBase64,\n data\n };\n } else {\n inspectedURL.data = null;\n }\n for (const key of URL_PROPS) {\n const value = urlObj[key];\n if (isString(value)) {\n inspectedURL[key] = value;\n }\n }\n } else {\n // URL which is invalid as an absolute URL, but valid as a relative URL.\n inspectedURL.valid = false;\n inspectedURL.relative = true;\n inspectedURL.href = sanitizedURL;\n inspectedURL.reason =\n 'Invalid as an absolute URL, but valid as a relative URL.';\n }\n } else {\n inspectedURL.reason = invalidReason;\n }\n return inspectedURL;\n }\n\n /**\n * Gets the list of registered URI schemes.\n * @returns {string[]} An array of registered schemes.\n */\n get() {\n return [...this.#allowedSchemes];\n }\n\n /**\n * Checks if the specified scheme is currently registered.\n * @param {string} scheme - The target scheme.\n * @returns {boolean} True if the scheme is registered.\n */\n has(scheme) {\n const normalizedScheme = normalizeURL(scheme, true);\n if (normalizedScheme) {\n return this.#allowedSchemes.has(normalizedScheme);\n }\n return false;\n }\n\n /**\n * Adds a new scheme to the allowed list.\n * @param {string} scheme - The scheme to add.\n * @returns {string[]} The updated array of registered schemes.\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n }\n const normalizedScheme = normalizeURL(scheme, true);\n if (!this.#isWellFormedScheme(normalizedScheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#allowedSchemes.add(normalizedScheme);\n return [...this.#allowedSchemes];\n }\n\n /**\n * Removes a scheme from the allowed list.\n * @param {string} scheme - The scheme to remove.\n * @returns {boolean} True if the scheme was successfully removed.\n */\n remove(scheme) {\n if (!isString(scheme)) {\n return false;\n }\n const normalizedScheme = normalizeURL(scheme, true);\n return this.#allowedSchemes.delete(normalizedScheme);\n }\n\n /**\n * Resets the registered schemes back to the default initial list.\n * @returns {void}\n */\n reset() {\n this.#allowedSchemes.clear();\n for (const scheme of super.get()) {\n this.#allowedSchemes.add(scheme);\n }\n }\n\n /**\n * Asynchronously sanitizes the given URL.\n * NOTE: `blob`, `data`, and `file` schemes must be explicitly allowed.\n * Given a `blob` URL, it securely converts and returns a sanitized `data` URL.\n * @param {string} url - URL\n * @param {SanitizeOptions} [opt] - The sanitization options.\n * @returns {Promise<string|null>} A promise resolving to the sanitized URL, or null.\n */\n async sanitizeURL(url, opt) {\n const { isValid, options, scheme } = this.#normalizeOptions(url, opt);\n if (isValid === false) {\n return null;\n }\n if (scheme === 'blob') {\n const { allow, deny, only } = options;\n let sanitizedData = null;\n try {\n if (\n (allow.includes('blob') && !deny.includes('blob')) ||\n only.includes('blob')\n ) {\n let fetchedBuffer = null;\n let fetchedMimeType = '';\n try {\n const fetchResult = await fetchBlobAsArrayBuffer(\n url,\n options.maxBlobSize\n );\n fetchedBuffer = fetchResult.buffer;\n fetchedMimeType = fetchResult.mimeType;\n } catch (e) {\n if (options.debug) {\n logDebug(\n `Failed to fetch and convert blob URL: ${truncateURL(url)}`,\n e\n );\n }\n }\n if (fetchedBuffer) {\n if (only.length) {\n if (!only.includes('data')) {\n options.only = [...only, 'data'];\n }\n } else {\n if (!allow.includes('data')) {\n options.allow = [...allow, 'data'];\n }\n options.deny = deny.filter(s => s !== 'data');\n }\n sanitizedData = await this.#filter.sanitizeBuffer(\n fetchedBuffer,\n fetchedMimeType,\n options\n );\n }\n }\n } finally {\n if (options.revokeObjectURL) {\n URL.revokeObjectURL(url);\n }\n }\n return sanitizedData;\n } else if (scheme === 'data') {\n return this.#filter.sanitizeDataURL(url, options);\n }\n return this.#filter.sanitize(url, options);\n }\n\n /**\n * Synchronously sanitizes the given URL.\n * NOTE: `data` and `file` schemes must be explicitly allowed.\n * The `blob` scheme is not supported and will return `null`.\n * @param {string} url - URL.\n * @param {SanitizeOptions} [opt] - The sanitization options.\n * @returns {string|null} The sanitized URL, or null if denied.\n */\n sanitizeURLSync(url, opt) {\n const { isValid, options, scheme } = this.#normalizeOptions(url, opt);\n if (isValid === false) {\n return null;\n }\n if (scheme === 'blob') {\n if (options.revokeObjectURL) {\n URL.revokeObjectURL(url);\n }\n return null;\n }\n return this.#filter.sanitize(url, options);\n }\n\n /**\n * Sanitizes the given URL and returns its parsed components.\n * NOTE: Blob URLs are not revoked after inspection.\n * @param {string} url - The URL string to inspect.\n * @returns {Promise<InspectedURLResult>} A promise resolving to the inspected URL result.\n */\n async inspectURL(url) {\n if (isString(url)) {\n const parsedURL = parseURL(url, null, true);\n if (parsedURL?.protocol === 'blob:') {\n try {\n const { buffer, mimeType } = await fetchBlobAsArrayBuffer(\n parsedURL.href\n );\n const base64Data = encodeBufferToBase64(buffer);\n const dataURL = `data:${mimeType ? `${mimeType};base64` : 'base64'},${base64Data}`;\n const inspectedURLResult = this.#inspect(dataURL);\n inspectedURLResult.input = url;\n return inspectedURLResult;\n } catch (e) {\n return { input: url, valid: false, reason: e.message };\n }\n }\n }\n return this.#inspect(url);\n }\n\n /**\n * Verifies if the given URI is valid and its scheme is allowed.\n * @param {string} uri - The URI string to verify.\n * @returns {boolean} True if the URI is syntactically valid and permitted.\n */\n isValidURI(uri) {\n return super.verifyURI(uri, this.#allowedSchemes);\n }\n}\n", "/*!\n * URL Sanitizer\n *\n * @license MIT\n * @copyright asamuzaK (Kazz)\n * @see {@link https://github.com/asamuzaK/urlSanitizer/blob/main/LICENSE}\n */\n\nimport { URLSanitizer } from './mjs/sanitize.js';\n\n/* typedef */\n/**\n * The parsed result of a Data URL.\n * @typedef {object} InspectedDataURL\n * @property {boolean} base64 - Indicates whether the data is base64-encoded.\n * @property {string} data - The actual data part of the Data URL.\n * @property {string} mime - The MIME type of the data.\n */\n\n/**\n * The result of an inspected URL, extending the standard URL API.\n * The properties except for input and valid are omitted for invalid URLs.\n * @typedef {object} InspectedURLResult\n * @property {string} input - The original URL input.\n * @property {boolean} valid - Indicates whether the sanitized URL (href) is a valid absolute URL.\n * @property {string|null} href - The sanitized URL, or null.\n * @property {boolean} [relative] - Indicates whether the sanitized URL (href) is a valid relative URL.\n * @property {string} [reason] - The reason why the URL is invalid.\n * @property {InspectedDataURL|null} [data] - The parsed result of a Data URL, or null.\n * @property {string} [origin] - The scheme, domain, and port.\n * @property {string} [protocol] - The protocol scheme.\n * @property {string} [username] - The specified username.\n * @property {string} [password] - The specified password.\n * @property {string} [host] - The domain and port.\n * @property {string} [hostname] - The domain.\n * @property {string} [port] - The port number.\n * @property {string} [pathname] - The path.\n * @property {string} [search] - The query string.\n * @property {string} [hash] - The fragment identifier.\n */\n\n/**\n * The sanitization options.\n * @typedef {object} SanitizeOptions\n * @property {string[]} [allow] - The array of schemes to allow.\n * @property {string[]} [deny] - The array of schemes to deny. Takes precedence over `allow`.\n * @property {string[]} [only] - The array of specific schemes to allow. Takes precedence over `allow` and `deny`.\n * @property {boolean} [allowRelative] - Allow relative URLs.\n * @property {boolean} [debug] - Enable debug mode.\n * @property {boolean} [revokeObjectURL] - Revokes the Blob URL after sanitization.\n * @property {number} [maxBlobSize] - The maximum allowed Blob size in bytes.\n * @property {number} [maxLength] - The maximum allowed URL length.\n */\n\nexport { URLSanitizer };\n\n/* URLSanitizer instance */\nconst sanitizer = new URLSanitizer();\n\n/* aliases */\n/**\n * Asynchronously sanitizes the given URL.\n * NOTE: `blob`, `data`, and `file` schemes must be explicitly allowed.\n * Given a `blob` URL, it securely converts and returns a sanitized `data` URL.\n * @param {string} url - URL.\n * @param {SanitizeOptions} [opt] - The sanitization options.\n * @returns {Promise<string|null>} A promise resolving to the sanitized URL, or null.\n */\nexport const sanitizeURL = async (url, opt) => sanitizer.sanitizeURL(url, opt);\n\n/**\n * Synchronously sanitizes the given URL.\n * NOTE: `data` and `file` schemes must be explicitly allowed.\n * The `blob` scheme is not supported and will return `null`.\n * @param {string} url - URL.\n * @param {SanitizeOptions} [opt] - The sanitization options.\n * @returns {string|null} The sanitized URL, or null if denied.\n */\nexport const sanitizeURLSync = (url, opt) =>\n sanitizer.sanitizeURLSync(url, opt);\n\n/**\n * Sanitizes the given URL and returns its parsed components.\n * NOTE: Blob URLs are not revoked after inspection.\n * @param {string} url - The URL string to inspect.\n * @returns {Promise<InspectedURLResult>} A promise resolving to the inspected URL result.\n */\nexport const inspectURL = async url => sanitizer.inspectURL(url);\n\n/**\n * Checks if the given string is a valid URI and is registered.\n * @param {string} uri - The URI string to verify.\n * @returns {boolean} True if valid and registered, false otherwise.\n */\nexport const isValidURI = uri => sanitizer.isValidURI(uri);\n\n/**\n * @deprecated Use {@link isValidURI} instead.\n * @param {string} uri - The URI string to verify.\n * @returns {boolean} True if valid and registered, false otherwise.\n */\nexport const isURISync = uri => sanitizer.isValidURI(uri);\n\n/* export instance */\nexport default sanitizer;\n"],
5
+ "mappings": "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",
6
+ "names": ["DUMMY_BASE", "DEFAULT_OPTS", "getType", "o", "isString", "logDebug", "message", "error", "PROPERTIES", "hookQueue", "domPurify", "target", "prop", "receiver", "purifier", "p", "args", "value", "REG_AMP", "REG_AMP_ENC", "REG_HASH", "REG_MIME_DOM", "REG_NON_ASCII", "REG_NUM_REF", "REG_PCT_ENC", "REG_QUERY", "REG_SCHEME", "REG_SCHEME_EXT", "REG_SCRIPT", "REG_SCRIPT_OR_BLOB", "REG_TAG_QUOT", "REG_URL_ENC", "REG_VERIFY_RELATIVE", "text_chars_default", "TEXT_CHAR_CODES", "text_chars_default", "WINDOWS1252_TO_UNICODE", "generateNonTextCharCodes", "charCodes", "i", "NON_TEXT_CHAR_CODES", "ENC_AMP", "ENC_NUM", "ENC_LT", "ENC_GT", "ENC_QUOT", "ENC_APOS", "ch", "ESCAPE_MAP", "HEX_TABLE", "_", "i", "IS_NODE", "NON_TEXT_PATTERN", "NON_TEXT_CHAR_CODES", "REG_NON_TEXT", "REG_NON_TEXT_G", "SHARED_BUFFER", "encoder", "decoder", "normalizeURL", "url", "isScheme", "isString", "normalized", "REG_NON_ASCII", "parseURL", "base", "normalize", "urlStr", "baseStr", "getSchemeParts", "protocol", "escapeURLEncodedHTMLChars", "ch", "isString", "target", "REG_URL_ENC", "ESCAPE_MAP", "truncateURL", "url", "str", "trimTrailingEmptyQueryAndHash", "REG_HASH", "REG_QUERY", "replaceNumCharRef", "match", "value", "num", "NON_TEXT_CHAR_CODES", "TEXT_CHAR_CODES", "codePoint", "WINDOWS1252_TO_UNICODE", "parseURLEncodedNumCharRef", "nest", "getType", "res", "REG_PCT_ENC", "REG_NON_TEXT_G", "depth", "previousRes", "REG_AMP", "REG_NUM_REF", "extractDataURLComponents", "pathname", "search", "hash", "comma", "mediaType", "dataPart", "data", "mediaTypes", "lastType", "isBase64", "parseBase64", "binStr", "cleanData", "bytes", "IS_NODE", "len", "SHARED_BUFFER", "i", "text", "decoder", "REG_NON_TEXT", "encodeBufferToBase64", "buffer", "uint8arr", "chunks", "SanitizeContext", "domPurifyInstance", "opt", "DEFAULT_OPTS", "#compileRules", "allowRelative", "debug", "allow", "deny", "only", "scheme", "#registerScheme", "normalized", "normalizeURL", "normalizedScheme", "REG_SCRIPT_OR_BLOB", "REG_SCHEME", "s", "REG_SCRIPT", "url", "logDebug", "truncateURL", "SanitizeFilter", "#defaultOpts", "#process", "ctx", "urlObj", "parseURL", "REG_VERIFY_RELATIVE", "dummyURL", "DUMMY_BASE", "protocol", "hostname", "pathname", "search", "hash", "#sanitizeStandardURL", "schemeParts", "part", "#sanitizeDataURL", "mediaType", "mediaTypes", "data", "isBase64", "extractDataURLComponents", "parsedData", "parseBase64", "e", "decodedData", "parseURLEncodedNumCharRef", "parsedURL", "getSchemeParts", "REG_MIME_DOM", "#purify", "dom", "decodedDom", "hook", "node", "evt", "#handleSanitizeAttribute", "purifiedDom", "trimTrailingEmptyQueryAndHash", "originalURL", "sanitized", "urlToSanitize", "len", "truncateIndex", "matchTagQuot", "REG_TAG_QUOT", "matchAmp", "REG_AMP_ENC", "matchAmpIndex", "lastChar", "isString", "maxLength", "msg", "escapeURLEncodedHTMLChars", "domPurify", "buffer", "mimeType", "base64Data", "encodeBufferToBase64", "dataUrl", "uri_schemes_default", "URISchemes", "#schemes", "uri_schemes_default", "uri", "isString", "parsed", "scheme", "normalized", "isScheme", "normalizeURL", "schemes", "normalizedSchemes", "base", "normalize", "parseURL", "parsedUrl", "allowCustom", "targetSchemes", "REG_SCRIPT", "parts", "s", "REG_SCHEME_EXT", "URL_PROPS", "readStreamInChunksAsArrayBuffer", "response", "maxSize", "reader", "chunks", "accumulatedSize", "done", "value", "combined", "offset", "chunk", "fetchBlobAsArrayBuffer", "url", "maxBlobSize", "msg", "truncateURL", "contentLength", "parsedLength", "mimeType", "buffer", "blob", "URLSanitizer", "URISchemes", "#allowedSchemes", "#defaultOpts", "#filter", "DEFAULT_OPTS", "SanitizeFilter", "#isWellFormedScheme", "normalizedScheme", "isString", "REG_SCRIPT_OR_BLOB", "REG_SCRIPT", "REG_SCHEME", "#normalizeOptions", "opt", "options", "scheme", "#inspect", "inspectedURL", "sanitizedURL", "invalidReason", "e", "urlObj", "parseURL", "normalizeURL", "mediaTypes", "data", "isBase64", "extractDataURLComponents", "key", "getType", "isValid", "allow", "deny", "only", "sanitizedData", "fetchedBuffer", "fetchedMimeType", "fetchResult", "logDebug", "s", "parsedURL", "base64Data", "encodeBufferToBase64", "dataURL", "inspectedURLResult", "uri", "sanitizer", "URLSanitizer", "sanitizeURL", "url", "opt", "sanitizeURLSync", "inspectURL", "isValidURI", "uri", "isURISync", "index_default"]
7
7
  }