var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { try { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; } catch (e) { throw mod = 0, e; } }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // src/notifications/SecureNotificationManager.js var require_SecureNotificationManager = __commonJS({ "src/notifications/SecureNotificationManager.js"(exports, module) { var SecureChatNotificationManager = class { constructor(config = {}) { this.permission = typeof Notification !== "undefined" && Notification && typeof Notification.permission === "string" ? Notification.permission : "denied"; this.isTabActive = this.checkTabActive(); this.unreadCount = 0; this.originalTitle = document.title; this.notificationQueue = []; this.maxQueueSize = config.maxQueueSize || 5; this.rateLimitMs = config.rateLimitMs || 2e3; this.lastNotificationTime = 0; this.trustedOrigins = config.trustedOrigins || []; this.isSecureContext = window.isSecureContext; this.hidden = this.getHiddenProperty(); this.visibilityChange = this.getVisibilityChangeEvent(); this.initVisibilityTracking(); this.initSecurityChecks(); } /** * Initialize security checks and validation * @private */ initSecurityChecks() { } /** * Get hidden property name for cross-browser compatibility * @returns {string} Hidden property name * @private */ getHiddenProperty() { if (typeof document.hidden !== "undefined") { return "hidden"; } else if (typeof document.msHidden !== "undefined") { return "msHidden"; } else if (typeof document.webkitHidden !== "undefined") { return "webkitHidden"; } return "hidden"; } /** * Get visibility change event name for cross-browser compatibility * @returns {string} Visibility change event name * @private */ getVisibilityChangeEvent() { if (typeof document.hidden !== "undefined") { return "visibilitychange"; } else if (typeof document.msHidden !== "undefined") { return "msvisibilitychange"; } else if (typeof document.webkitHidden !== "undefined") { return "webkitvisibilitychange"; } return "visibilitychange"; } /** * Check if tab is currently active using multiple methods * @returns {boolean} True if tab is active * @private */ checkTabActive() { if (this.hidden && typeof document[this.hidden] !== "undefined") { return !document[this.hidden]; } if (typeof document.hasFocus === "function") { return document.hasFocus(); } return true; } /** * Initialize page visibility tracking (Page Visibility API) * @private */ initVisibilityTracking() { if (typeof document.addEventListener !== "undefined" && typeof document[this.hidden] !== "undefined") { document.addEventListener(this.visibilityChange, () => { this.isTabActive = this.checkTabActive(); if (this.isTabActive) { this.resetUnreadCount(); this.clearNotificationQueue(); } }); } window.addEventListener("focus", () => { this.isTabActive = this.checkTabActive(); if (this.isTabActive) { this.resetUnreadCount(); } }); window.addEventListener("blur", () => { this.isTabActive = this.checkTabActive(); }); window.addEventListener("beforeunload", () => { this.clearNotificationQueue(); }); } /** * Request notification permission (BEST PRACTICE: Only call in response to user action) * Never call on page load! * @returns {Promise} Permission granted status */ async requestPermission() { if (!this.isSecureContext || !("Notification" in window)) { return false; } if (this.permission === "granted") { return true; } if (this.permission === "denied") { return false; } try { this.permission = await Notification.requestPermission(); return this.permission === "granted"; } catch (error) { return false; } } /** * Update page title with unread count * @private */ updateTitle() { if (this.unreadCount > 0) { document.title = `(${this.unreadCount}) ${this.originalTitle}`; } else { document.title = this.originalTitle; } } /** * XSS Protection: Sanitize input text * @param {string} text - Text to sanitize * @returns {string} Sanitized text * @private */ sanitizeText(text2) { if (typeof text2 !== "string") { return ""; } const div = document.createElement("div"); div.textContent = text2; return div.innerHTML.replace(//g, ">").replace(/"/g, """).replace(/'/g, "'").substring(0, 500); } /** * Validate icon URL (XSS protection) * @param {string} url - URL to validate * @returns {string|null} Validated URL or null * @private */ validateIconUrl(url) { if (!url) return null; try { const parsedUrl = new URL(url, window.location.origin); if (parsedUrl.protocol === "https:" || parsedUrl.protocol === "data:") { if (this.trustedOrigins.length > 0) { const isTrusted = this.trustedOrigins.some( (origin) => parsedUrl.origin === origin ); return isTrusted ? parsedUrl.href : null; } return parsedUrl.href; } return null; } catch (error) { return null; } } /** * Rate limiting for spam protection * @returns {boolean} Rate limit check passed * @private */ checkRateLimit() { const now = Date.now(); if (now - this.lastNotificationTime < this.rateLimitMs) { return false; } this.lastNotificationTime = now; return true; } /** * Send secure notification * @param {string} senderName - Name of message sender * @param {string} message - Message content * @param {Object} options - Notification options * @returns {Notification|null} Created notification or null */ notify(senderName, message, options = {}) { if (typeof Notification === "undefined") { return null; } this.isTabActive = this.checkTabActive(); if (this.isTabActive) { return null; } if (this.permission !== "granted") { return null; } if (!this.checkRateLimit()) { return null; } const safeSenderName = this.sanitizeText(senderName || "Unknown"); const safeMessage = this.sanitizeText(message || ""); const safeIcon = this.validateIconUrl(options.icon) || "/logo/icon-192x192.png"; if (this.notificationQueue.length >= this.maxQueueSize) { this.clearNotificationQueue(); } try { const notification = new Notification( `${safeSenderName}`, { body: safeMessage.substring(0, 200), // Length limit icon: safeIcon, badge: safeIcon, tag: `chat-${options.senderId || "unknown"}`, // Grouping requireInteraction: false, // Don't block user silent: options.silent || false, // Vibrate only for mobile and if supported vibrate: navigator.vibrate ? [200, 100, 200] : void 0, // Safe metadata data: { senderId: this.sanitizeText(options.senderId), timestamp: Date.now() // Don't include sensitive data! } } ); this.unreadCount++; this.updateTitle(); this.notificationQueue.push(notification); notification.onclick = (event) => { event.preventDefault(); window.focus(); notification.close(); if (typeof options.onClick === "function") { try { options.onClick(options.senderId); } catch (error) { console.error("[Notifications] Error in onClick handler:", error); } } }; notification.onerror = (event) => { console.error("[Notifications] Error showing notification:", event); }; const autoCloseTimeout = Math.min(options.autoClose || 5e3, 1e4); setTimeout(() => { notification.close(); this.removeFromQueue(notification); }, autoCloseTimeout); return notification; } catch (error) { console.error("[Notifications] Failed to create notification:", error); return null; } } /** * Remove notification from queue * @param {Notification} notification - Notification to remove * @private */ removeFromQueue(notification) { const index = this.notificationQueue.indexOf(notification); if (index > -1) { this.notificationQueue.splice(index, 1); } } /** * Clear all notifications */ clearNotificationQueue() { this.notificationQueue.forEach((notification) => { try { notification.close(); } catch (error) { } }); this.notificationQueue = []; } /** * Reset unread counter */ resetUnreadCount() { this.unreadCount = 0; this.updateTitle(); } /** * Get current status * @returns {Object} Current notification status */ getStatus() { return { permission: this.permission, isTabActive: this.isTabActive, unreadCount: this.unreadCount, isSecureContext: this.isSecureContext, queueSize: this.notificationQueue.length }; } }; var SecureP2PChat = class { constructor() { this.notificationManager = new SecureChatNotificationManager({ maxQueueSize: 5, rateLimitMs: 2e3, trustedOrigins: [ window.location.origin // Add other trusted origins for CDN icons ] }); this.dataChannel = null; this.peerConnection = null; this.remotePeerName = "Peer"; this.messageHistory = []; this.maxHistorySize = 100; } /** * Initialize when user connects */ async init() { } /** * Method for manual permission request (called on click) * @returns {Promise} Permission granted status */ async enableNotifications() { const granted = await this.notificationManager.requestPermission(); return granted; } /** * Setup DataChannel with security checks * @param {RTCDataChannel} dataChannel - WebRTC data channel */ setupDataChannel(dataChannel) { if (!dataChannel) { console.error("[Chat] Invalid DataChannel"); return; } this.dataChannel = dataChannel; this.dataChannel.onmessage = (event) => { this.handleIncomingMessage(event.data); }; this.dataChannel.onerror = (error) => { }; } /** * XSS Protection: Validate incoming messages * @param {string|Object} data - Message data * @returns {Object|null} Validated message or null * @private */ validateMessage(data) { try { const message = typeof data === "string" ? JSON.parse(data) : data; if (!message || typeof message !== "object") { throw new Error("Invalid message structure"); } if (!message.text || typeof message.text !== "string") { throw new Error("Invalid message text"); } if (message.text.length > 1e4) { throw new Error("Message too long"); } return { text: message.text, senderName: message.senderName || "Unknown", senderId: message.senderId || "unknown", timestamp: message.timestamp || Date.now(), senderAvatar: message.senderAvatar || null }; } catch (error) { console.error("[Chat] Message validation failed:", error); return null; } } /** * Secure handling of incoming messages * @param {string|Object} data - Message data * @private */ handleIncomingMessage(data) { const message = this.validateMessage(data); if (!message) { return; } this.messageHistory.push(message); if (this.messageHistory.length > this.maxHistorySize) { this.messageHistory.shift(); } this.displayMessage(message); this.notificationManager.notify( message.senderName, message.text, { icon: message.senderAvatar, senderId: message.senderId, onClick: (senderId) => { this.scrollToLatestMessage(); } } ); if (!this.notificationManager.isTabActive) { this.playNotificationSound(); } } /** * XSS Protection: Safe message display * @param {Object} message - Message to display * @private */ displayMessage(message) { const container = document.getElementById("messages"); if (!container) { return; } const messageEl = document.createElement("div"); messageEl.className = "message"; const nameEl = document.createElement("strong"); nameEl.textContent = message.senderName + ": "; const textEl = document.createElement("span"); textEl.textContent = message.text; textEl.style.wordWrap = "break-word"; textEl.style.overflowWrap = "break-word"; textEl.style.whiteSpace = "normal"; const timeEl = document.createElement("small"); timeEl.textContent = new Date(message.timestamp).toLocaleTimeString(); messageEl.appendChild(nameEl); messageEl.appendChild(textEl); messageEl.appendChild(document.createElement("br")); messageEl.appendChild(timeEl); container.appendChild(messageEl); this.scrollToLatestMessage(); } /** * Safe sound playback * @private */ playNotificationSound() { try { const audio = new Audio("/assets/audio/notification.mp3"); audio.volume = 0.3; audio.play().catch((error) => { }); } catch (error) { } } /** * Scroll to latest message * @private */ scrollToLatestMessage() { const container = document.getElementById("messages"); if (container) { container.scrollTop = container.scrollHeight; } } /** * Get status * @returns {Object} Current chat status */ getStatus() { return { notifications: this.notificationManager.getStatus(), messageCount: this.messageHistory.length, connected: this.dataChannel?.readyState === "open" }; } }; if (typeof module !== "undefined" && module.exports) { module.exports = { SecureChatNotificationManager, SecureP2PChat }; } if (typeof window !== "undefined") { window.SecureChatNotificationManager = SecureChatNotificationManager; window.SecureP2PChat = SecureP2PChat; } } }); // src/notifications/NotificationIntegration.js var require_NotificationIntegration = __commonJS({ "src/notifications/NotificationIntegration.js"(exports, module) { var import_SecureNotificationManager = __toESM(require_SecureNotificationManager()); var NotificationIntegration2 = class { constructor(webrtcManager) { this.webrtcManager = webrtcManager; this.notificationManager = new import_SecureNotificationManager.SecureChatNotificationManager({ maxQueueSize: 10, rateLimitMs: 1e3, // Reduced from 2000ms to 1000ms trustedOrigins: [ window.location.origin // Add other trusted origins for CDN icons ] }); this.isInitialized = false; this.originalOnMessage = null; this.originalOnStatusChange = null; this.processedMessages = /* @__PURE__ */ new Set(); } /** * Initialize notification integration * @returns {Promise} Initialization success */ async init() { try { if (this.isInitialized) { return true; } this.originalOnMessage = this.webrtcManager.onMessage; this.originalOnStatusChange = this.webrtcManager.onStatusChange; this.webrtcManager.onMessage = (message, type) => { this.handleIncomingMessage(message, type); if (this.originalOnMessage) { this.originalOnMessage(message, type); } }; this.webrtcManager.onStatusChange = (status) => { this.handleStatusChange(status); if (this.originalOnStatusChange) { this.originalOnStatusChange(status); } }; if (this.webrtcManager.deliverMessageToUI) { this.originalDeliverMessageToUI = this.webrtcManager.deliverMessageToUI.bind(this.webrtcManager); this.webrtcManager.deliverMessageToUI = (message, type) => { this.handleIncomingMessage(message, type); this.originalDeliverMessageToUI(message, type); }; } this.isInitialized = true; return true; } catch (error) { return false; } } /** * Handle incoming messages and trigger notifications * @param {*} message - Message content * @param {string} type - Message type * @private */ handleIncomingMessage(message, type) { try { const messageKey = `${type}:${typeof message === "string" ? message : JSON.stringify(message)}`; if (this.processedMessages.has(messageKey)) { return; } this.processedMessages.add(messageKey); if (this.processedMessages.size > 100) { const messagesArray = Array.from(this.processedMessages); this.processedMessages.clear(); messagesArray.slice(-50).forEach((msg) => this.processedMessages.add(msg)); } if (type === "system" || type === "file-transfer" || type === "heartbeat") { return; } const messageInfo = this.extractMessageInfo(message, type); if (!messageInfo) { return; } const notificationResult = this.notificationManager.notify( messageInfo.senderName, messageInfo.text, { icon: messageInfo.senderAvatar, senderId: messageInfo.senderId, onClick: (senderId) => { this.focusChatWindow(); } } ); } catch (error) { } } /** * Handle status changes * @param {string} status - Connection status * @private */ handleStatusChange(status) { try { if (status === "disconnected" || status === "failed") { this.notificationManager.clearNotificationQueue(); this.notificationManager.resetUnreadCount(); } } catch (error) { } } /** * Extract message information for notifications * @param {*} message - Message content * @param {string} type - Message type * @returns {Object|null} Extracted message info or null * @private */ extractMessageInfo(message, type) { try { let messageData = message; if (typeof message === "string") { try { messageData = JSON.parse(message); } catch (e) { return { senderName: "Peer", text: message, senderId: "peer", senderAvatar: null }; } } if (typeof messageData === "object" && messageData !== null) { return { senderName: messageData.senderName || messageData.name || "Peer", text: messageData.text || messageData.message || messageData.content || "", senderId: messageData.senderId || messageData.id || "peer", senderAvatar: messageData.senderAvatar || messageData.avatar || null }; } return null; } catch (error) { return null; } } /** * Focus chat window when notification is clicked * @private */ focusChatWindow() { try { window.focus(); const messagesContainer = document.getElementById("messages"); if (messagesContainer) { messagesContainer.scrollTop = messagesContainer.scrollHeight; } } catch (error) { } } /** * Request notification permission * @returns {Promise} Permission granted status */ async requestPermission() { try { return await this.notificationManager.requestPermission(); } catch (error) { return false; } } /** * Get notification status * @returns {Object} Notification status */ getStatus() { return this.notificationManager.getStatus(); } /** * Clear all notifications */ clearNotifications() { this.notificationManager.clearNotificationQueue(); this.notificationManager.resetUnreadCount(); } /** * Cleanup integration */ cleanup() { try { if (this.isInitialized) { if (this.originalOnMessage) { this.webrtcManager.onMessage = this.originalOnMessage; } if (this.originalOnStatusChange) { this.webrtcManager.onStatusChange = this.originalOnStatusChange; } if (this.originalDeliverMessageToUI) { this.webrtcManager.deliverMessageToUI = this.originalDeliverMessageToUI; } this.clearNotifications(); this.isInitialized = false; } } catch (error) { } } }; if (typeof module !== "undefined" && module.exports) { module.exports = { NotificationIntegration: NotificationIntegration2 }; } if (typeof window !== "undefined") { window.NotificationIntegration = NotificationIntegration2; } } }); // node_modules/dompurify/dist/purify.es.mjs function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = true) ; } catch (r2) { o = true, n = r2; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } var entries = Object.entries; var setPrototypeOf = Object.setPrototypeOf; var isFrozen = Object.isFrozen; var getPrototypeOf = Object.getPrototypeOf; var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var freeze = Object.freeze; var seal = Object.seal; var create = Object.create; var _ref = typeof Reflect !== "undefined" && Reflect; var apply = _ref.apply; var construct = _ref.construct; if (!freeze) { freeze = function freeze2(x) { return x; }; } if (!seal) { seal = function seal2(x) { return x; }; } if (!apply) { apply = function apply2(func, thisArg) { for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } return func.apply(thisArg, args); }; } if (!construct) { construct = function construct2(Func) { for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } return new Func(...args); }; } var arrayForEach = unapply(Array.prototype.forEach); var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf); var arrayPop = unapply(Array.prototype.pop); var arrayPush = unapply(Array.prototype.push); var arraySplice = unapply(Array.prototype.splice); var arrayIsArray = Array.isArray; var stringToLowerCase = unapply(String.prototype.toLowerCase); var stringToString = unapply(String.prototype.toString); var stringMatch = unapply(String.prototype.match); var stringReplace = unapply(String.prototype.replace); var stringIndexOf = unapply(String.prototype.indexOf); var stringTrim = unapply(String.prototype.trim); var numberToString = unapply(Number.prototype.toString); var booleanToString = unapply(Boolean.prototype.toString); var bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString); var symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString); var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty); var objectToString = unapply(Object.prototype.toString); var regExpTest = unapply(RegExp.prototype.test); var typeErrorCreate = unconstruct(TypeError); function unapply(func) { return function(thisArg) { if (thisArg instanceof RegExp) { thisArg.lastIndex = 0; } for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { args[_key3 - 1] = arguments[_key3]; } return apply(func, thisArg, args); }; } function unconstruct(Func) { return function() { for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } return construct(Func, args); }; } function addToSet(set, array) { let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase; if (setPrototypeOf) { setPrototypeOf(set, null); } if (!arrayIsArray(array)) { return set; } let l = array.length; while (l--) { let element = array[l]; if (typeof element === "string") { const lcElement = transformCaseFunc(element); if (lcElement !== element) { if (!isFrozen(array)) { array[l] = lcElement; } element = lcElement; } } set[element] = true; } return set; } function cleanArray(array) { for (let index = 0; index < array.length; index++) { const isPropertyExist = objectHasOwnProperty(array, index); if (!isPropertyExist) { array[index] = null; } } return array; } function clone(object) { const newObject = create(null); for (const _ref2 of entries(object)) { var _ref3 = _slicedToArray(_ref2, 2); const property = _ref3[0]; const value = _ref3[1]; const isPropertyExist = objectHasOwnProperty(object, property); if (isPropertyExist) { if (arrayIsArray(value)) { newObject[property] = cleanArray(value); } else if (value && typeof value === "object" && value.constructor === Object) { newObject[property] = clone(value); } else { newObject[property] = value; } } } return newObject; } function stringifyValue(value) { switch (typeof value) { case "string": { return value; } case "number": { return numberToString(value); } case "boolean": { return booleanToString(value); } case "bigint": { return bigintToString ? bigintToString(value) : "0"; } case "symbol": { return symbolToString ? symbolToString(value) : "Symbol()"; } case "undefined": { return objectToString(value); } case "function": case "object": { if (value === null) { return objectToString(value); } const valueAsRecord = value; const valueToString = lookupGetter(valueAsRecord, "toString"); if (typeof valueToString === "function") { const stringified = valueToString(valueAsRecord); return typeof stringified === "string" ? stringified : objectToString(stringified); } return objectToString(value); } default: { return objectToString(value); } } } function lookupGetter(object, prop) { while (object !== null) { const desc = getOwnPropertyDescriptor(object, prop); if (desc) { if (desc.get) { return unapply(desc.get); } if (typeof desc.value === "function") { return unapply(desc.value); } } object = getPrototypeOf(object); } function fallbackValue() { return null; } return fallbackValue; } function isRegex(value) { try { regExpTest(value, ""); return true; } catch (_unused) { return false; } } var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]); var svg$1 = freeze(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "enterkeyhint", "exportparts", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "inputmode", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "part", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]); var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]); var svgDisallowed = freeze(["animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]); var mathMl$1 = freeze(["math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "mprescripts"]); var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]); var text = freeze(["#text"]); var html = freeze(["accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "command", "commandfor", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "exportparts", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inert", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "nonce", "noshade", "novalidate", "nowrap", "open", "optimum", "part", "pattern", "placeholder", "playsinline", "popover", "popovertarget", "popovertargetaction", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "slot", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "wrap", "xmlns"]); var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]); var mathMl = freeze(["accent", "accentunder", "align", "bevelled", "close", "columnalign", "columnlines", "columnspacing", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lquote", "lspace", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns"]); var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]); var MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g); var ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g); var TMPLIT_EXPR = seal(/\${[\w\W]*/g); var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); var ARIA_ATTR = seal(/^aria-[\-\w]+$/); var IS_ALLOWED_URI = seal( /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape ); var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); var ATTR_WHITESPACE = seal( /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex ); var DOCTYPE_NAME = seal(/^html$/i); var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); var ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g); var COMMENT_MARKUP_PROBE = seal(/<[/\w]/g); var FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i); var SELF_CLOSING_TAG = seal(/\/>/i); var NODE_TYPE = { element: 1, attribute: 2, text: 3, cdataSection: 4, entityReference: 5, // Deprecated entityNode: 6, // Deprecated processingInstruction: 7, comment: 8, document: 9, documentType: 10, documentFragment: 11, notation: 12 // Deprecated }; var getGlobal = function getGlobal2() { return typeof window === "undefined" ? null : window; }; var _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) { if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") { return null; } let suffix = null; const ATTR_NAME = "data-tt-policy-suffix"; if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) { suffix = purifyHostElement.getAttribute(ATTR_NAME); } const policyName = "dompurify" + (suffix ? "#" + suffix : ""); try { return trustedTypes.createPolicy(policyName, { createHTML(html2) { return html2; }, createScriptURL(scriptUrl) { return scriptUrl; } }); } catch (_) { console.warn("TrustedTypes policy " + policyName + " could not be created."); return null; } }; var _createHooksMap = function _createHooksMap2() { return { afterSanitizeAttributes: [], afterSanitizeElements: [], afterSanitizeShadowDOM: [], beforeSanitizeAttributes: [], beforeSanitizeElements: [], beforeSanitizeShadowDOM: [], uponSanitizeAttribute: [], uponSanitizeElement: [], uponSanitizeShadowNode: [] }; }; var _resolveSetOption = function _resolveSetOption2(cfg, key, fallback, options) { return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback; }; function createDOMPurify() { let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal(); const DOMPurify = (root) => createDOMPurify(root); DOMPurify.version = "3.4.10"; DOMPurify.removed = []; if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) { DOMPurify.isSupported = false; return DOMPurify; } let document2 = window2.document; const originalDocument = document2; const currentScript = originalDocument.currentScript; window2.DocumentFragment; const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap; _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap; window2.HTMLFormElement; const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes; const ElementPrototype = Element.prototype; const cloneNode = lookupGetter(ElementPrototype, "cloneNode"); const remove = lookupGetter(ElementPrototype, "remove"); const getNextSibling = lookupGetter(ElementPrototype, "nextSibling"); const getChildNodes = lookupGetter(ElementPrototype, "childNodes"); const getParentNode = lookupGetter(ElementPrototype, "parentNode"); const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot"); const getAttributes = lookupGetter(ElementPrototype, "attributes"); const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null; const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null; if (typeof HTMLTemplateElement === "function") { const template = document2.createElement("template"); if (template.content && template.content.ownerDocument) { document2 = template.content.ownerDocument; } } let trustedTypesPolicy; let emptyHTML = ""; let defaultTrustedTypesPolicy; let defaultTrustedTypesPolicyResolved = false; let IN_TRUSTED_TYPES_POLICY = 0; const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy2() { if (IN_TRUSTED_TYPES_POLICY > 0) { throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.'); } }; const _createTrustedHTML = function _createTrustedHTML2(html2) { _assertNotInTrustedTypesPolicy(); IN_TRUSTED_TYPES_POLICY++; try { return trustedTypesPolicy.createHTML(html2); } finally { IN_TRUSTED_TYPES_POLICY--; } }; const _createTrustedScriptURL = function _createTrustedScriptURL2(scriptUrl) { _assertNotInTrustedTypesPolicy(); IN_TRUSTED_TYPES_POLICY++; try { return trustedTypesPolicy.createScriptURL(scriptUrl); } finally { IN_TRUSTED_TYPES_POLICY--; } }; const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy2() { if (!defaultTrustedTypesPolicyResolved) { defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); defaultTrustedTypesPolicyResolved = true; } return defaultTrustedTypesPolicy; }; const _document = document2, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName; const importNode = originalDocument.importNode; let hooks = _createHooksMap(); DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0; const MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, TMPLIT_EXPR$1 = TMPLIT_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE, CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT; let IS_ALLOWED_URI$1 = IS_ALLOWED_URI; let ALLOWED_TAGS = null; const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]); let ALLOWED_ATTR = null; const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]); let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, { tagNameCheck: { writable: true, configurable: false, enumerable: true, value: null }, attributeNameCheck: { writable: true, configurable: false, enumerable: true, value: null }, allowCustomizedBuiltInElements: { writable: true, configurable: false, enumerable: true, value: false } })); let FORBID_TAGS = null; let FORBID_ATTR = null; const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, { tagCheck: { writable: true, configurable: false, enumerable: true, value: null }, attributeCheck: { writable: true, configurable: false, enumerable: true, value: null } })); let ALLOW_ARIA_ATTR = true; let ALLOW_DATA_ATTR = true; let ALLOW_UNKNOWN_PROTOCOLS = false; let ALLOW_SELF_CLOSE_IN_ATTR = true; let SAFE_FOR_TEMPLATES = false; let SAFE_FOR_XML = true; let WHOLE_DOCUMENT = false; let SET_CONFIG = false; let FORCE_BODY = false; let RETURN_DOM = false; let RETURN_DOM_FRAGMENT = false; let RETURN_TRUSTED_TYPE = false; let SANITIZE_DOM = true; let SANITIZE_NAMED_PROPS = false; const SANITIZE_NAMED_PROPS_PREFIX = "user-content-"; let KEEP_CONTENT = true; let IN_PLACE = false; let USE_PROFILES = {}; let FORBID_CONTENTS = null; const DEFAULT_FORBID_CONTENTS = addToSet({}, [ "annotation-xml", "audio", "colgroup", "desc", "foreignobject", "head", "iframe", "math", "mi", "mn", "mo", "ms", "mtext", "noembed", "noframes", "noscript", "plaintext", "script", // mirrors the selected