{"version":3,"sources":["jsdelivr-header.js","/npm/rehype-harden@1.1.6/dist/index.js"],"names":[],"mappings":"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","file":"/npm/rehype-harden@1.1.6/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/rehype-harden@1.1.6/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { CONTINUE, SKIP, visit } from \"unist-util-visit\";\nexport function harden({ defaultOrigin = \"\", allowedLinkPrefixes = [], allowedImagePrefixes = [], allowDataImages = false, allowedProtocols = [], blockedImageClass = \"inline-block bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-400 px-3 py-1 rounded text-sm\", blockedLinkClass = \"text-gray-500\", }) {\n    // Only require defaultOrigin if we have specific prefixes (not wildcard only)\n    const hasSpecificLinkPrefixes = allowedLinkPrefixes.length && !allowedLinkPrefixes.every((p) => p === \"*\");\n    const hasSpecificImagePrefixes = allowedImagePrefixes.length &&\n        !allowedImagePrefixes.every((p) => p === \"*\");\n    if (!defaultOrigin && (hasSpecificLinkPrefixes || hasSpecificImagePrefixes)) {\n        throw new Error(\"defaultOrigin is required when allowedLinkPrefixes or allowedImagePrefixes are provided\");\n    }\n    return (tree) => {\n        const visitor = createVisitor(defaultOrigin, allowedLinkPrefixes, allowedImagePrefixes, allowDataImages, allowedProtocols, blockedImageClass, blockedLinkClass);\n        visit(tree, visitor);\n    };\n}\nfunction parseUrl(url, defaultOrigin) {\n    if (typeof url !== \"string\")\n        return null;\n    try {\n        // Try to parse as absolute URL first\n        return new URL(url);\n    }\n    catch {\n        // If that fails and we have a defaultOrigin, try with it\n        if (defaultOrigin) {\n            try {\n                return new URL(url, defaultOrigin);\n            }\n            catch {\n                return null;\n            }\n        }\n        return null;\n    }\n}\nfunction isPathRelativeUrl(url) {\n    if (typeof url !== \"string\")\n        return false;\n    return url.startsWith(\"/\");\n}\nconst safeProtocols = new Set([\n    \"https:\",\n    \"http:\",\n    \"irc:\",\n    \"ircs:\",\n    \"mailto:\",\n    \"xmpp:\",\n    \"blob:\",\n]);\n// Protocols that should NEVER be allowed for security reasons\nconst blockedProtocols = new Set([\n    \"javascript:\",\n    \"data:\",\n    \"file:\",\n    \"vbscript:\",\n]);\nfunction transformUrl(url, allowedPrefixes, defaultOrigin, allowDataImages = false, isImage = false, allowedProtocols = []) {\n    if (!url)\n        return null;\n    // Allow hash-only (fragment-only) URLs - they navigate within the current page\n    if (typeof url === \"string\" && url.startsWith(\"#\") && !isImage) {\n        // Hash-only URLs don't need defaultOrigin validation\n        // Just verify it's a valid fragment identifier\n        try {\n            // Use a dummy base to validate the hash format\n            const testUrl = new URL(url, \"http://example.com\");\n            if (testUrl.hash === url) {\n                return url;\n            }\n        }\n        catch {\n            // Invalid hash format, fall through to normal validation\n        }\n    }\n    // Handle data: URLs for images if allowDataImages is enabled\n    if (typeof url === \"string\" && url.startsWith(\"data:\")) {\n        // Only allow data: URLs for images when explicitly enabled\n        if (isImage && allowDataImages && url.startsWith(\"data:image/\")) {\n            return url;\n        }\n        return null;\n    }\n    // Handle blob: URLs - these are browser-generated URLs for local objects\n    if (typeof url === \"string\" && url.startsWith(\"blob:\")) {\n        // blob: URLs are valid and safe - they reference in-memory objects\n        // They can only reference content already loaded in the browser\n        try {\n            // Validate it's a properly formatted blob URL\n            // blob: URLs should have the format: blob:<origin>/<uuid> or blob:null/<uuid>\n            const blobUrl = new URL(url);\n            if (blobUrl.protocol === \"blob:\" && url.length > 5) {\n                // Ensure there's actual content after \"blob:\"\n                const afterProtocol = url.substring(5);\n                if (afterProtocol && afterProtocol.length > 0 && afterProtocol !== \"invalid\") {\n                    return url;\n                }\n            }\n        }\n        catch {\n            return null;\n        }\n        // If we get here, the blob URL is malformed\n        return null;\n    }\n    const parsedUrl = parseUrl(url, defaultOrigin);\n    if (!parsedUrl)\n        return null;\n    // Block dangerous protocols - these should NEVER be allowed\n    // Exception: data: is allowed for images if allowDataImages is true (handled above)\n    if (blockedProtocols.has(parsedUrl.protocol)) {\n        return null;\n    }\n    // Check if protocol is allowed\n    const isProtocolAllowed = safeProtocols.has(parsedUrl.protocol) ||\n        allowedProtocols.includes(parsedUrl.protocol) ||\n        allowedProtocols.includes(\"*\");\n    if (!isProtocolAllowed)\n        return null;\n    // mailto: and other custom protocols can just return as-is\n    if (parsedUrl.protocol === \"mailto:\" || !parsedUrl.protocol.match(/^https?:$/)) {\n        return parsedUrl.href;\n    }\n    // If the input is path relative, we output a path relative URL as well,\n    // however, we always run the same checks on an absolute URL and we\n    // always reconstruct the output from the parsed URL to ensure that\n    // the output is always a valid URL.\n    const inputWasRelative = isPathRelativeUrl(url);\n    if (parsedUrl &&\n        allowedPrefixes.some((prefix) => {\n            const parsedPrefix = parseUrl(prefix, defaultOrigin);\n            if (!parsedPrefix) {\n                return false;\n            }\n            if (parsedPrefix.origin !== parsedUrl.origin) {\n                return false;\n            }\n            return parsedUrl.href.startsWith(parsedPrefix.href);\n        })) {\n        if (inputWasRelative) {\n            return parsedUrl.pathname + parsedUrl.search + parsedUrl.hash;\n        }\n        return parsedUrl.href;\n    }\n    // Check for wildcard - allow all URLs\n    if (allowedPrefixes.includes(\"*\")) {\n        // Wildcard only allows http and https URLs\n        if (parsedUrl.protocol !== \"https:\" && parsedUrl.protocol !== \"http:\") {\n            return null;\n        }\n        if (inputWasRelative) {\n            return parsedUrl.pathname + parsedUrl.search + parsedUrl.hash;\n        }\n        return parsedUrl.href;\n    }\n    return null;\n}\nconst SEEN = Symbol(\"node-seen\");\nconst createVisitor = (defaultOrigin, allowedLinkPrefixes, allowedImagePrefixes, allowDataImages, allowedProtocols, blockedImageClass, blockedLinkClass) => {\n    const visitor = (node, index, parent) => {\n        if (node.type !== \"element\" ||\n            // @ts-expect-error\n            node[SEEN]) {\n            return CONTINUE;\n        }\n        if (node.tagName === \"a\") {\n            const transformedUrl = transformUrl(node.properties.href, allowedLinkPrefixes, defaultOrigin, false, false, allowedProtocols);\n            if (transformedUrl === null) {\n                // @ts-expect-error\n                node[SEEN] = true;\n                // We need to eagerly visit children so that we catch any nested nastiness as well,\n                // prior to modifying the node's parent.\n                visit(node, visitor);\n                if (parent && typeof index === \"number\") {\n                    parent.children[index] = {\n                        type: \"element\",\n                        tagName: \"span\",\n                        properties: {\n                            title: \"Blocked URL: \" + String(node.properties.href),\n                            class: blockedLinkClass,\n                        },\n                        children: [\n                            ...node.children,\n                            {\n                                type: \"text\",\n                                value: \" [blocked]\",\n                            },\n                        ],\n                    };\n                }\n                return SKIP;\n            }\n            else {\n                node.properties.href = transformedUrl;\n                node.properties.target = \"_blank\";\n                node.properties.rel = \"noopener noreferrer\";\n                return CONTINUE;\n            }\n        }\n        if (node.tagName === \"img\") {\n            const transformedUrl = transformUrl(node.properties.src, allowedImagePrefixes, defaultOrigin, allowDataImages, true, allowedProtocols);\n            if (transformedUrl === null) {\n                // @ts-expect-error\n                node[SEEN] = true;\n                visit(node, visitor);\n                if (parent && typeof index === \"number\") {\n                    parent.children[index] = {\n                        type: \"element\",\n                        tagName: \"span\",\n                        properties: {\n                            class: blockedImageClass,\n                        },\n                        children: [\n                            {\n                                type: \"text\",\n                                value: \"[Image blocked: \" +\n                                    String(node.properties.alt || \"No description\") +\n                                    \"]\",\n                            },\n                        ],\n                    };\n                }\n                return SKIP;\n            }\n            else {\n                node.properties.src = transformedUrl;\n                return CONTINUE;\n            }\n        }\n        return CONTINUE;\n    };\n    return visitor;\n};\n"]}