diff --git a/backend/Gemfile b/backend/Gemfile index 309c0bb..1c76afc 100644 --- a/backend/Gemfile +++ b/backend/Gemfile @@ -35,6 +35,7 @@ gem "thruster", require: false # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin Ajax possible gem "rack-cors" gem 'jwt' +gem 'sprockets-rails' group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem diff --git a/backend/Gemfile.lock b/backend/Gemfile.lock index d23b681..6ffef1d 100644 --- a/backend/Gemfile.lock +++ b/backend/Gemfile.lock @@ -276,6 +276,13 @@ GEM fugit (~> 1.11.0) railties (>= 7.1) thor (~> 1.3.1) + sprockets (4.2.1) + concurrent-ruby (~> 1.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) + sprockets (>= 3.0.0) sqlite3 (2.6.0-aarch64-linux-gnu) sqlite3 (2.6.0-aarch64-linux-musl) sqlite3 (2.6.0-arm-linux-gnu) @@ -338,6 +345,7 @@ DEPENDENCIES solid_cable solid_cache solid_queue + sprockets-rails sqlite3 (>= 2.1) thruster tzinfo-data diff --git a/backend/app/assets/config/manifest.js b/backend/app/assets/config/manifest.js new file mode 100644 index 0000000..b16e53d --- /dev/null +++ b/backend/app/assets/config/manifest.js @@ -0,0 +1,3 @@ +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css diff --git a/backend/app/assets/images/.gitkeep b/backend/app/assets/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/assets/javascripts/.gitkeep b/backend/app/assets/javascripts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/assets/stylesheets/.gitkeep b/backend/app/assets/stylesheets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/backend/public/assets/.sprockets-manifest-bc72bf50aa9693fc0bfc25057f1a5282.json b/backend/public/assets/.sprockets-manifest-bc72bf50aa9693fc0bfc25057f1a5282.json new file mode 100644 index 0000000..83d14f4 --- /dev/null +++ b/backend/public/assets/.sprockets-manifest-bc72bf50aa9693fc0bfc25057f1a5282.json @@ -0,0 +1 @@ +{"files":{"manifest-6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167.js":{"logical_path":"manifest.js","mtime":"2025-02-26T00:16:38+09:00","size":3,"digest":"6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167","integrity":"sha256-ajz1GSNU9xYVrFEDSz6Xwg7amWQ/yvW75tQa1ZvRIWc="},"actiontext-9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d.js":{"logical_path":"actiontext.js","mtime":"2025-02-26T00:16:38+09:00","size":30872,"digest":"9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d","integrity":"sha256-nMv2gkUdQ5YR/loEjlUVfFYDiEDrtKgpJDfrVf0xyD0="},"actiontext.esm-6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c.js":{"logical_path":"actiontext.esm.js","mtime":"2025-02-26T00:16:38+09:00","size":29011,"digest":"6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c","integrity":"sha256-Z5DU2vVFjNbrjeLVbnVKNAyuupCcspUqNftHiVVJPYw="},"trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js":{"logical_path":"trix.js","mtime":"2025-02-26T00:16:38+09:00","size":512990,"digest":"488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc","integrity":"sha256-SIrIi1Dt7oqrc92CbplnB17tkAChP9E8vMF3RfhmUMw="},"trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css":{"logical_path":"trix.css","mtime":"2025-02-26T00:16:38+09:00","size":20027,"digest":"4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211","integrity":"sha256-TH9WdnaZrmwI8hAEydwjobdrBzSw/KYdRTSQDuD+8hE="},"activestorage-cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2.js":{"logical_path":"activestorage.js","mtime":"2025-02-26T00:16:38+09:00","size":29420,"digest":"cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2","integrity":"sha256-zyKkl9GVbo8NPsUPRdaJYaoNE47gYoAsNq44TvsmCqI="},"activestorage.esm-8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485.js":{"logical_path":"activestorage.esm.js","mtime":"2025-02-26T00:16:38+09:00","size":27262,"digest":"8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485","integrity":"sha256-i7AoIo5iLFBQGz6yacvkBEpG2ge1ZakOWubyIdwG5IU="},"actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js":{"logical_path":"actioncable.js","mtime":"2025-02-26T00:16:38+09:00","size":16474,"digest":"1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e","integrity":"sha256-GiOf+WZEvI/WJvh6dBdbTufq/SAfUDQDSkM8ItjE3D4="},"actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js":{"logical_path":"actioncable.esm.js","mtime":"2025-02-26T00:16:38+09:00","size":14813,"digest":"555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0","integrity":"sha256-VVZ55E8Rm+en5UEh/KC+sKWDLykzwaHtzQUVu6+tIuA="}},"assets":{"manifest.js":"manifest-6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167.js","actiontext.js":"actiontext-9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d.js","actiontext.esm.js":"actiontext.esm-6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c.js","trix.js":"trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js","trix.css":"trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css","activestorage.js":"activestorage-cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2.js","activestorage.esm.js":"activestorage.esm-8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485.js","actioncable.js":"actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js","actioncable.esm.js":"actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js"}} \ No newline at end of file diff --git a/backend/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js b/backend/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js new file mode 100644 index 0000000..5fc9943 --- /dev/null +++ b/backend/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js @@ -0,0 +1,510 @@ +(function(global, factory) { + typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, + factory(global.ActionCable = {})); +})(this, (function(exports) { + "use strict"; + var adapters = { + logger: typeof console !== "undefined" ? console : undefined, + WebSocket: typeof WebSocket !== "undefined" ? WebSocket : undefined + }; + var logger = { + log(...messages) { + if (this.enabled) { + messages.push(Date.now()); + adapters.logger.log("[ActionCable]", ...messages); + } + } + }; + const now = () => (new Date).getTime(); + const secondsSince = time => (now() - time) / 1e3; + class ConnectionMonitor { + constructor(connection) { + this.visibilityDidChange = this.visibilityDidChange.bind(this); + this.connection = connection; + this.reconnectAttempts = 0; + } + start() { + if (!this.isRunning()) { + this.startedAt = now(); + delete this.stoppedAt; + this.startPolling(); + addEventListener("visibilitychange", this.visibilityDidChange); + logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`); + } + } + stop() { + if (this.isRunning()) { + this.stoppedAt = now(); + this.stopPolling(); + removeEventListener("visibilitychange", this.visibilityDidChange); + logger.log("ConnectionMonitor stopped"); + } + } + isRunning() { + return this.startedAt && !this.stoppedAt; + } + recordMessage() { + this.pingedAt = now(); + } + recordConnect() { + this.reconnectAttempts = 0; + delete this.disconnectedAt; + logger.log("ConnectionMonitor recorded connect"); + } + recordDisconnect() { + this.disconnectedAt = now(); + logger.log("ConnectionMonitor recorded disconnect"); + } + startPolling() { + this.stopPolling(); + this.poll(); + } + stopPolling() { + clearTimeout(this.pollTimeout); + } + poll() { + this.pollTimeout = setTimeout((() => { + this.reconnectIfStale(); + this.poll(); + }), this.getPollInterval()); + } + getPollInterval() { + const {staleThreshold: staleThreshold, reconnectionBackoffRate: reconnectionBackoffRate} = this.constructor; + const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10)); + const jitterMax = this.reconnectAttempts === 0 ? 1 : reconnectionBackoffRate; + const jitter = jitterMax * Math.random(); + return staleThreshold * 1e3 * backoff * (1 + jitter); + } + reconnectIfStale() { + if (this.connectionIsStale()) { + logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`); + this.reconnectAttempts++; + if (this.disconnectedRecently()) { + logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`); + } else { + logger.log("ConnectionMonitor reopening"); + this.connection.reopen(); + } + } + } + get refreshedAt() { + return this.pingedAt ? this.pingedAt : this.startedAt; + } + connectionIsStale() { + return secondsSince(this.refreshedAt) > this.constructor.staleThreshold; + } + disconnectedRecently() { + return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold; + } + visibilityDidChange() { + if (document.visibilityState === "visible") { + setTimeout((() => { + if (this.connectionIsStale() || !this.connection.isOpen()) { + logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`); + this.connection.reopen(); + } + }), 200); + } + } + } + ConnectionMonitor.staleThreshold = 6; + ConnectionMonitor.reconnectionBackoffRate = .15; + var INTERNAL = { + message_types: { + welcome: "welcome", + disconnect: "disconnect", + ping: "ping", + confirmation: "confirm_subscription", + rejection: "reject_subscription" + }, + disconnect_reasons: { + unauthorized: "unauthorized", + invalid_request: "invalid_request", + server_restart: "server_restart", + remote: "remote" + }, + default_mount_path: "/cable", + protocols: [ "actioncable-v1-json", "actioncable-unsupported" ] + }; + const {message_types: message_types, protocols: protocols} = INTERNAL; + const supportedProtocols = protocols.slice(0, protocols.length - 1); + const indexOf = [].indexOf; + class Connection { + constructor(consumer) { + this.open = this.open.bind(this); + this.consumer = consumer; + this.subscriptions = this.consumer.subscriptions; + this.monitor = new ConnectionMonitor(this); + this.disconnected = true; + } + send(data) { + if (this.isOpen()) { + this.webSocket.send(JSON.stringify(data)); + return true; + } else { + return false; + } + } + open() { + if (this.isActive()) { + logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`); + return false; + } else { + const socketProtocols = [ ...protocols, ...this.consumer.subprotocols || [] ]; + logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`); + if (this.webSocket) { + this.uninstallEventHandlers(); + } + this.webSocket = new adapters.WebSocket(this.consumer.url, socketProtocols); + this.installEventHandlers(); + this.monitor.start(); + return true; + } + } + close({allowReconnect: allowReconnect} = { + allowReconnect: true + }) { + if (!allowReconnect) { + this.monitor.stop(); + } + if (this.isOpen()) { + return this.webSocket.close(); + } + } + reopen() { + logger.log(`Reopening WebSocket, current state is ${this.getState()}`); + if (this.isActive()) { + try { + return this.close(); + } catch (error) { + logger.log("Failed to reopen WebSocket", error); + } finally { + logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`); + setTimeout(this.open, this.constructor.reopenDelay); + } + } else { + return this.open(); + } + } + getProtocol() { + if (this.webSocket) { + return this.webSocket.protocol; + } + } + isOpen() { + return this.isState("open"); + } + isActive() { + return this.isState("open", "connecting"); + } + triedToReconnect() { + return this.monitor.reconnectAttempts > 0; + } + isProtocolSupported() { + return indexOf.call(supportedProtocols, this.getProtocol()) >= 0; + } + isState(...states) { + return indexOf.call(states, this.getState()) >= 0; + } + getState() { + if (this.webSocket) { + for (let state in adapters.WebSocket) { + if (adapters.WebSocket[state] === this.webSocket.readyState) { + return state.toLowerCase(); + } + } + } + return null; + } + installEventHandlers() { + for (let eventName in this.events) { + const handler = this.events[eventName].bind(this); + this.webSocket[`on${eventName}`] = handler; + } + } + uninstallEventHandlers() { + for (let eventName in this.events) { + this.webSocket[`on${eventName}`] = function() {}; + } + } + } + Connection.reopenDelay = 500; + Connection.prototype.events = { + message(event) { + if (!this.isProtocolSupported()) { + return; + } + const {identifier: identifier, message: message, reason: reason, reconnect: reconnect, type: type} = JSON.parse(event.data); + this.monitor.recordMessage(); + switch (type) { + case message_types.welcome: + if (this.triedToReconnect()) { + this.reconnectAttempted = true; + } + this.monitor.recordConnect(); + return this.subscriptions.reload(); + + case message_types.disconnect: + logger.log(`Disconnecting. Reason: ${reason}`); + return this.close({ + allowReconnect: reconnect + }); + + case message_types.ping: + return null; + + case message_types.confirmation: + this.subscriptions.confirmSubscription(identifier); + if (this.reconnectAttempted) { + this.reconnectAttempted = false; + return this.subscriptions.notify(identifier, "connected", { + reconnected: true + }); + } else { + return this.subscriptions.notify(identifier, "connected", { + reconnected: false + }); + } + + case message_types.rejection: + return this.subscriptions.reject(identifier); + + default: + return this.subscriptions.notify(identifier, "received", message); + } + }, + open() { + logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`); + this.disconnected = false; + if (!this.isProtocolSupported()) { + logger.log("Protocol is unsupported. Stopping monitor and disconnecting."); + return this.close({ + allowReconnect: false + }); + } + }, + close(event) { + logger.log("WebSocket onclose event"); + if (this.disconnected) { + return; + } + this.disconnected = true; + this.monitor.recordDisconnect(); + return this.subscriptions.notifyAll("disconnected", { + willAttemptReconnect: this.monitor.isRunning() + }); + }, + error() { + logger.log("WebSocket onerror event"); + } + }; + const extend = function(object, properties) { + if (properties != null) { + for (let key in properties) { + const value = properties[key]; + object[key] = value; + } + } + return object; + }; + class Subscription { + constructor(consumer, params = {}, mixin) { + this.consumer = consumer; + this.identifier = JSON.stringify(params); + extend(this, mixin); + } + perform(action, data = {}) { + data.action = action; + return this.send(data); + } + send(data) { + return this.consumer.send({ + command: "message", + identifier: this.identifier, + data: JSON.stringify(data) + }); + } + unsubscribe() { + return this.consumer.subscriptions.remove(this); + } + } + class SubscriptionGuarantor { + constructor(subscriptions) { + this.subscriptions = subscriptions; + this.pendingSubscriptions = []; + } + guarantee(subscription) { + if (this.pendingSubscriptions.indexOf(subscription) == -1) { + logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`); + this.pendingSubscriptions.push(subscription); + } else { + logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`); + } + this.startGuaranteeing(); + } + forget(subscription) { + logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`); + this.pendingSubscriptions = this.pendingSubscriptions.filter((s => s !== subscription)); + } + startGuaranteeing() { + this.stopGuaranteeing(); + this.retrySubscribing(); + } + stopGuaranteeing() { + clearTimeout(this.retryTimeout); + } + retrySubscribing() { + this.retryTimeout = setTimeout((() => { + if (this.subscriptions && typeof this.subscriptions.subscribe === "function") { + this.pendingSubscriptions.map((subscription => { + logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`); + this.subscriptions.subscribe(subscription); + })); + } + }), 500); + } + } + class Subscriptions { + constructor(consumer) { + this.consumer = consumer; + this.guarantor = new SubscriptionGuarantor(this); + this.subscriptions = []; + } + create(channelName, mixin) { + const channel = channelName; + const params = typeof channel === "object" ? channel : { + channel: channel + }; + const subscription = new Subscription(this.consumer, params, mixin); + return this.add(subscription); + } + add(subscription) { + this.subscriptions.push(subscription); + this.consumer.ensureActiveConnection(); + this.notify(subscription, "initialized"); + this.subscribe(subscription); + return subscription; + } + remove(subscription) { + this.forget(subscription); + if (!this.findAll(subscription.identifier).length) { + this.sendCommand(subscription, "unsubscribe"); + } + return subscription; + } + reject(identifier) { + return this.findAll(identifier).map((subscription => { + this.forget(subscription); + this.notify(subscription, "rejected"); + return subscription; + })); + } + forget(subscription) { + this.guarantor.forget(subscription); + this.subscriptions = this.subscriptions.filter((s => s !== subscription)); + return subscription; + } + findAll(identifier) { + return this.subscriptions.filter((s => s.identifier === identifier)); + } + reload() { + return this.subscriptions.map((subscription => this.subscribe(subscription))); + } + notifyAll(callbackName, ...args) { + return this.subscriptions.map((subscription => this.notify(subscription, callbackName, ...args))); + } + notify(subscription, callbackName, ...args) { + let subscriptions; + if (typeof subscription === "string") { + subscriptions = this.findAll(subscription); + } else { + subscriptions = [ subscription ]; + } + return subscriptions.map((subscription => typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined)); + } + subscribe(subscription) { + if (this.sendCommand(subscription, "subscribe")) { + this.guarantor.guarantee(subscription); + } + } + confirmSubscription(identifier) { + logger.log(`Subscription confirmed ${identifier}`); + this.findAll(identifier).map((subscription => this.guarantor.forget(subscription))); + } + sendCommand(subscription, command) { + const {identifier: identifier} = subscription; + return this.consumer.send({ + command: command, + identifier: identifier + }); + } + } + class Consumer { + constructor(url) { + this._url = url; + this.subscriptions = new Subscriptions(this); + this.connection = new Connection(this); + this.subprotocols = []; + } + get url() { + return createWebSocketURL(this._url); + } + send(data) { + return this.connection.send(data); + } + connect() { + return this.connection.open(); + } + disconnect() { + return this.connection.close({ + allowReconnect: false + }); + } + ensureActiveConnection() { + if (!this.connection.isActive()) { + return this.connection.open(); + } + } + addSubProtocol(subprotocol) { + this.subprotocols = [ ...this.subprotocols, subprotocol ]; + } + } + function createWebSocketURL(url) { + if (typeof url === "function") { + url = url(); + } + if (url && !/^wss?:/i.test(url)) { + const a = document.createElement("a"); + a.href = url; + a.href = a.href; + a.protocol = a.protocol.replace("http", "ws"); + return a.href; + } else { + return url; + } + } + function createConsumer(url = getConfig("url") || INTERNAL.default_mount_path) { + return new Consumer(url); + } + function getConfig(name) { + const element = document.head.querySelector(`meta[name='action-cable-${name}']`); + if (element) { + return element.getAttribute("content"); + } + } + exports.Connection = Connection; + exports.ConnectionMonitor = ConnectionMonitor; + exports.Consumer = Consumer; + exports.INTERNAL = INTERNAL; + exports.Subscription = Subscription; + exports.SubscriptionGuarantor = SubscriptionGuarantor; + exports.Subscriptions = Subscriptions; + exports.adapters = adapters; + exports.createConsumer = createConsumer; + exports.createWebSocketURL = createWebSocketURL; + exports.getConfig = getConfig; + exports.logger = logger; + Object.defineProperty(exports, "__esModule", { + value: true + }); +})); diff --git a/backend/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js.gz b/backend/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js.gz new file mode 100644 index 0000000..8ffa46b Binary files /dev/null and b/backend/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js.gz differ diff --git a/backend/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js b/backend/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js new file mode 100644 index 0000000..1832009 --- /dev/null +++ b/backend/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js @@ -0,0 +1,512 @@ +var adapters = { + logger: typeof console !== "undefined" ? console : undefined, + WebSocket: typeof WebSocket !== "undefined" ? WebSocket : undefined +}; + +var logger = { + log(...messages) { + if (this.enabled) { + messages.push(Date.now()); + adapters.logger.log("[ActionCable]", ...messages); + } + } +}; + +const now = () => (new Date).getTime(); + +const secondsSince = time => (now() - time) / 1e3; + +class ConnectionMonitor { + constructor(connection) { + this.visibilityDidChange = this.visibilityDidChange.bind(this); + this.connection = connection; + this.reconnectAttempts = 0; + } + start() { + if (!this.isRunning()) { + this.startedAt = now(); + delete this.stoppedAt; + this.startPolling(); + addEventListener("visibilitychange", this.visibilityDidChange); + logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`); + } + } + stop() { + if (this.isRunning()) { + this.stoppedAt = now(); + this.stopPolling(); + removeEventListener("visibilitychange", this.visibilityDidChange); + logger.log("ConnectionMonitor stopped"); + } + } + isRunning() { + return this.startedAt && !this.stoppedAt; + } + recordMessage() { + this.pingedAt = now(); + } + recordConnect() { + this.reconnectAttempts = 0; + delete this.disconnectedAt; + logger.log("ConnectionMonitor recorded connect"); + } + recordDisconnect() { + this.disconnectedAt = now(); + logger.log("ConnectionMonitor recorded disconnect"); + } + startPolling() { + this.stopPolling(); + this.poll(); + } + stopPolling() { + clearTimeout(this.pollTimeout); + } + poll() { + this.pollTimeout = setTimeout((() => { + this.reconnectIfStale(); + this.poll(); + }), this.getPollInterval()); + } + getPollInterval() { + const {staleThreshold: staleThreshold, reconnectionBackoffRate: reconnectionBackoffRate} = this.constructor; + const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10)); + const jitterMax = this.reconnectAttempts === 0 ? 1 : reconnectionBackoffRate; + const jitter = jitterMax * Math.random(); + return staleThreshold * 1e3 * backoff * (1 + jitter); + } + reconnectIfStale() { + if (this.connectionIsStale()) { + logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`); + this.reconnectAttempts++; + if (this.disconnectedRecently()) { + logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`); + } else { + logger.log("ConnectionMonitor reopening"); + this.connection.reopen(); + } + } + } + get refreshedAt() { + return this.pingedAt ? this.pingedAt : this.startedAt; + } + connectionIsStale() { + return secondsSince(this.refreshedAt) > this.constructor.staleThreshold; + } + disconnectedRecently() { + return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold; + } + visibilityDidChange() { + if (document.visibilityState === "visible") { + setTimeout((() => { + if (this.connectionIsStale() || !this.connection.isOpen()) { + logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`); + this.connection.reopen(); + } + }), 200); + } + } +} + +ConnectionMonitor.staleThreshold = 6; + +ConnectionMonitor.reconnectionBackoffRate = .15; + +var INTERNAL = { + message_types: { + welcome: "welcome", + disconnect: "disconnect", + ping: "ping", + confirmation: "confirm_subscription", + rejection: "reject_subscription" + }, + disconnect_reasons: { + unauthorized: "unauthorized", + invalid_request: "invalid_request", + server_restart: "server_restart", + remote: "remote" + }, + default_mount_path: "/cable", + protocols: [ "actioncable-v1-json", "actioncable-unsupported" ] +}; + +const {message_types: message_types, protocols: protocols} = INTERNAL; + +const supportedProtocols = protocols.slice(0, protocols.length - 1); + +const indexOf = [].indexOf; + +class Connection { + constructor(consumer) { + this.open = this.open.bind(this); + this.consumer = consumer; + this.subscriptions = this.consumer.subscriptions; + this.monitor = new ConnectionMonitor(this); + this.disconnected = true; + } + send(data) { + if (this.isOpen()) { + this.webSocket.send(JSON.stringify(data)); + return true; + } else { + return false; + } + } + open() { + if (this.isActive()) { + logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`); + return false; + } else { + const socketProtocols = [ ...protocols, ...this.consumer.subprotocols || [] ]; + logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`); + if (this.webSocket) { + this.uninstallEventHandlers(); + } + this.webSocket = new adapters.WebSocket(this.consumer.url, socketProtocols); + this.installEventHandlers(); + this.monitor.start(); + return true; + } + } + close({allowReconnect: allowReconnect} = { + allowReconnect: true + }) { + if (!allowReconnect) { + this.monitor.stop(); + } + if (this.isOpen()) { + return this.webSocket.close(); + } + } + reopen() { + logger.log(`Reopening WebSocket, current state is ${this.getState()}`); + if (this.isActive()) { + try { + return this.close(); + } catch (error) { + logger.log("Failed to reopen WebSocket", error); + } finally { + logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`); + setTimeout(this.open, this.constructor.reopenDelay); + } + } else { + return this.open(); + } + } + getProtocol() { + if (this.webSocket) { + return this.webSocket.protocol; + } + } + isOpen() { + return this.isState("open"); + } + isActive() { + return this.isState("open", "connecting"); + } + triedToReconnect() { + return this.monitor.reconnectAttempts > 0; + } + isProtocolSupported() { + return indexOf.call(supportedProtocols, this.getProtocol()) >= 0; + } + isState(...states) { + return indexOf.call(states, this.getState()) >= 0; + } + getState() { + if (this.webSocket) { + for (let state in adapters.WebSocket) { + if (adapters.WebSocket[state] === this.webSocket.readyState) { + return state.toLowerCase(); + } + } + } + return null; + } + installEventHandlers() { + for (let eventName in this.events) { + const handler = this.events[eventName].bind(this); + this.webSocket[`on${eventName}`] = handler; + } + } + uninstallEventHandlers() { + for (let eventName in this.events) { + this.webSocket[`on${eventName}`] = function() {}; + } + } +} + +Connection.reopenDelay = 500; + +Connection.prototype.events = { + message(event) { + if (!this.isProtocolSupported()) { + return; + } + const {identifier: identifier, message: message, reason: reason, reconnect: reconnect, type: type} = JSON.parse(event.data); + this.monitor.recordMessage(); + switch (type) { + case message_types.welcome: + if (this.triedToReconnect()) { + this.reconnectAttempted = true; + } + this.monitor.recordConnect(); + return this.subscriptions.reload(); + + case message_types.disconnect: + logger.log(`Disconnecting. Reason: ${reason}`); + return this.close({ + allowReconnect: reconnect + }); + + case message_types.ping: + return null; + + case message_types.confirmation: + this.subscriptions.confirmSubscription(identifier); + if (this.reconnectAttempted) { + this.reconnectAttempted = false; + return this.subscriptions.notify(identifier, "connected", { + reconnected: true + }); + } else { + return this.subscriptions.notify(identifier, "connected", { + reconnected: false + }); + } + + case message_types.rejection: + return this.subscriptions.reject(identifier); + + default: + return this.subscriptions.notify(identifier, "received", message); + } + }, + open() { + logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`); + this.disconnected = false; + if (!this.isProtocolSupported()) { + logger.log("Protocol is unsupported. Stopping monitor and disconnecting."); + return this.close({ + allowReconnect: false + }); + } + }, + close(event) { + logger.log("WebSocket onclose event"); + if (this.disconnected) { + return; + } + this.disconnected = true; + this.monitor.recordDisconnect(); + return this.subscriptions.notifyAll("disconnected", { + willAttemptReconnect: this.monitor.isRunning() + }); + }, + error() { + logger.log("WebSocket onerror event"); + } +}; + +const extend = function(object, properties) { + if (properties != null) { + for (let key in properties) { + const value = properties[key]; + object[key] = value; + } + } + return object; +}; + +class Subscription { + constructor(consumer, params = {}, mixin) { + this.consumer = consumer; + this.identifier = JSON.stringify(params); + extend(this, mixin); + } + perform(action, data = {}) { + data.action = action; + return this.send(data); + } + send(data) { + return this.consumer.send({ + command: "message", + identifier: this.identifier, + data: JSON.stringify(data) + }); + } + unsubscribe() { + return this.consumer.subscriptions.remove(this); + } +} + +class SubscriptionGuarantor { + constructor(subscriptions) { + this.subscriptions = subscriptions; + this.pendingSubscriptions = []; + } + guarantee(subscription) { + if (this.pendingSubscriptions.indexOf(subscription) == -1) { + logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`); + this.pendingSubscriptions.push(subscription); + } else { + logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`); + } + this.startGuaranteeing(); + } + forget(subscription) { + logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`); + this.pendingSubscriptions = this.pendingSubscriptions.filter((s => s !== subscription)); + } + startGuaranteeing() { + this.stopGuaranteeing(); + this.retrySubscribing(); + } + stopGuaranteeing() { + clearTimeout(this.retryTimeout); + } + retrySubscribing() { + this.retryTimeout = setTimeout((() => { + if (this.subscriptions && typeof this.subscriptions.subscribe === "function") { + this.pendingSubscriptions.map((subscription => { + logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`); + this.subscriptions.subscribe(subscription); + })); + } + }), 500); + } +} + +class Subscriptions { + constructor(consumer) { + this.consumer = consumer; + this.guarantor = new SubscriptionGuarantor(this); + this.subscriptions = []; + } + create(channelName, mixin) { + const channel = channelName; + const params = typeof channel === "object" ? channel : { + channel: channel + }; + const subscription = new Subscription(this.consumer, params, mixin); + return this.add(subscription); + } + add(subscription) { + this.subscriptions.push(subscription); + this.consumer.ensureActiveConnection(); + this.notify(subscription, "initialized"); + this.subscribe(subscription); + return subscription; + } + remove(subscription) { + this.forget(subscription); + if (!this.findAll(subscription.identifier).length) { + this.sendCommand(subscription, "unsubscribe"); + } + return subscription; + } + reject(identifier) { + return this.findAll(identifier).map((subscription => { + this.forget(subscription); + this.notify(subscription, "rejected"); + return subscription; + })); + } + forget(subscription) { + this.guarantor.forget(subscription); + this.subscriptions = this.subscriptions.filter((s => s !== subscription)); + return subscription; + } + findAll(identifier) { + return this.subscriptions.filter((s => s.identifier === identifier)); + } + reload() { + return this.subscriptions.map((subscription => this.subscribe(subscription))); + } + notifyAll(callbackName, ...args) { + return this.subscriptions.map((subscription => this.notify(subscription, callbackName, ...args))); + } + notify(subscription, callbackName, ...args) { + let subscriptions; + if (typeof subscription === "string") { + subscriptions = this.findAll(subscription); + } else { + subscriptions = [ subscription ]; + } + return subscriptions.map((subscription => typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined)); + } + subscribe(subscription) { + if (this.sendCommand(subscription, "subscribe")) { + this.guarantor.guarantee(subscription); + } + } + confirmSubscription(identifier) { + logger.log(`Subscription confirmed ${identifier}`); + this.findAll(identifier).map((subscription => this.guarantor.forget(subscription))); + } + sendCommand(subscription, command) { + const {identifier: identifier} = subscription; + return this.consumer.send({ + command: command, + identifier: identifier + }); + } +} + +class Consumer { + constructor(url) { + this._url = url; + this.subscriptions = new Subscriptions(this); + this.connection = new Connection(this); + this.subprotocols = []; + } + get url() { + return createWebSocketURL(this._url); + } + send(data) { + return this.connection.send(data); + } + connect() { + return this.connection.open(); + } + disconnect() { + return this.connection.close({ + allowReconnect: false + }); + } + ensureActiveConnection() { + if (!this.connection.isActive()) { + return this.connection.open(); + } + } + addSubProtocol(subprotocol) { + this.subprotocols = [ ...this.subprotocols, subprotocol ]; + } +} + +function createWebSocketURL(url) { + if (typeof url === "function") { + url = url(); + } + if (url && !/^wss?:/i.test(url)) { + const a = document.createElement("a"); + a.href = url; + a.href = a.href; + a.protocol = a.protocol.replace("http", "ws"); + return a.href; + } else { + return url; + } +} + +function createConsumer(url = getConfig("url") || INTERNAL.default_mount_path) { + return new Consumer(url); +} + +function getConfig(name) { + const element = document.head.querySelector(`meta[name='action-cable-${name}']`); + if (element) { + return element.getAttribute("content"); + } +} + +export { Connection, ConnectionMonitor, Consumer, INTERNAL, Subscription, SubscriptionGuarantor, Subscriptions, adapters, createConsumer, createWebSocketURL, getConfig, logger }; diff --git a/backend/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js.gz b/backend/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js.gz new file mode 100644 index 0000000..62de4cb Binary files /dev/null and b/backend/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js.gz differ diff --git a/backend/public/assets/actiontext-9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d.js b/backend/public/assets/actiontext-9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d.js new file mode 100644 index 0000000..e61f03c --- /dev/null +++ b/backend/public/assets/actiontext-9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d.js @@ -0,0 +1,884 @@ +(function(factory) { + typeof define === "function" && define.amd ? define(factory) : factory(); +})((function() { + "use strict"; + var sparkMd5 = { + exports: {} + }; + (function(module, exports) { + (function(factory) { + { + module.exports = factory(); + } + })((function(undefined$1) { + var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ]; + function md5cycle(x, k) { + var a = x[0], b = x[1], c = x[2], d = x[3]; + a += (b & c | ~b & d) + k[0] - 680876936 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[1] - 389564586 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[2] + 606105819 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[3] - 1044525330 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[4] - 176418897 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[5] + 1200080426 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[6] - 1473231341 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[7] - 45705983 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[8] + 1770035416 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[9] - 1958414417 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[10] - 42063 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[11] - 1990404162 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[12] + 1804603682 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[13] - 40341101 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[14] - 1502002290 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[15] + 1236535329 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & d | c & ~d) + k[1] - 165796510 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[6] - 1069501632 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[11] + 643717713 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[0] - 373897302 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[5] - 701558691 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[10] + 38016083 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[15] - 660478335 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[4] - 405537848 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[9] + 568446438 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[14] - 1019803690 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[3] - 187363961 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[8] + 1163531501 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[13] - 1444681467 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[2] - 51403784 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[7] + 1735328473 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[12] - 1926607734 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b ^ c ^ d) + k[5] - 378558 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[8] - 2022574463 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[11] + 1839030562 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[14] - 35309556 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[1] - 1530992060 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[4] + 1272893353 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[7] - 155497632 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[10] - 1094730640 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[13] + 681279174 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[0] - 358537222 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[3] - 722521979 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[6] + 76029189 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[9] - 640364487 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[12] - 421815835 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[15] + 530742520 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[2] - 995338651 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; + b = (b << 21 | b >>> 11) + c | 0; + x[0] = a + x[0] | 0; + x[1] = b + x[1] | 0; + x[2] = c + x[2] | 0; + x[3] = d + x[3] | 0; + } + function md5blk(s) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + } + function md5blk_array(a) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + } + function md51(s) { + var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function md51_array(a) { + var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0); + length = a.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function rhex(n) { + var s = "", j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15]; + } + return s; + } + function hex(x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(""); + } + if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ; + if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) { + (function() { + function clamp(val, length) { + val = val | 0 || 0; + if (val < 0) { + return Math.max(val + length, 0); + } + return Math.min(val, length); + } + ArrayBuffer.prototype.slice = function(from, to) { + var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray; + if (to !== undefined$1) { + end = clamp(to, length); + } + if (begin > end) { + return new ArrayBuffer(0); + } + num = end - begin; + target = new ArrayBuffer(num); + targetArray = new Uint8Array(target); + sourceArray = new Uint8Array(this, begin, num); + targetArray.set(sourceArray); + return target; + }; + })(); + } + function toUtf8(str) { + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + return str; + } + function utf8Str2ArrayBuffer(str, returnUInt8Array) { + var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i; + for (i = 0; i < length; i += 1) { + arr[i] = str.charCodeAt(i); + } + return returnUInt8Array ? arr : buff; + } + function arrayBuffer2Utf8Str(buff) { + return String.fromCharCode.apply(null, new Uint8Array(buff)); + } + function concatenateArrayBuffers(first, second, returnUInt8Array) { + var result = new Uint8Array(first.byteLength + second.byteLength); + result.set(new Uint8Array(first)); + result.set(new Uint8Array(second), first.byteLength); + return returnUInt8Array ? result : result.buffer; + } + function hexToBinaryString(hex) { + var bytes = [], length = hex.length, x; + for (x = 0; x < length - 1; x += 2) { + bytes.push(parseInt(hex.substr(x, 2), 16)); + } + return String.fromCharCode.apply(String, bytes); + } + function SparkMD5() { + this.reset(); + } + SparkMD5.prototype.append = function(str) { + this.appendBinary(toUtf8(str)); + return this; + }; + SparkMD5.prototype.appendBinary = function(contents) { + this._buff += contents; + this._length += contents.length; + var length = this._buff.length, i; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i))); + } + this._buff = this._buff.substring(i - 64); + return this; + }; + SparkMD5.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.prototype.reset = function() { + this._buff = ""; + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.prototype.getState = function() { + return { + buff: this._buff, + length: this._length, + hash: this._hash.slice() + }; + }; + SparkMD5.prototype.setState = function(state) { + this._buff = state.buff; + this._length = state.length; + this._hash = state.hash; + return this; + }; + SparkMD5.prototype.destroy = function() { + delete this._hash; + delete this._buff; + delete this._length; + }; + SparkMD5.prototype._finish = function(tail, length) { + var i = length, tmp, lo, hi; + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(this._hash, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(this._hash, tail); + }; + SparkMD5.hash = function(str, raw) { + return SparkMD5.hashBinary(toUtf8(str), raw); + }; + SparkMD5.hashBinary = function(content, raw) { + var hash = md51(content), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + SparkMD5.ArrayBuffer = function() { + this.reset(); + }; + SparkMD5.ArrayBuffer.prototype.append = function(arr) { + var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i; + this._length += arr.byteLength; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i))); + } + this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0); + return this; + }; + SparkMD5.ArrayBuffer.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.ArrayBuffer.prototype.reset = function() { + this._buff = new Uint8Array(0); + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.ArrayBuffer.prototype.getState = function() { + var state = SparkMD5.prototype.getState.call(this); + state.buff = arrayBuffer2Utf8Str(state.buff); + return state; + }; + SparkMD5.ArrayBuffer.prototype.setState = function(state) { + state.buff = utf8Str2ArrayBuffer(state.buff, true); + return SparkMD5.prototype.setState.call(this, state); + }; + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + SparkMD5.ArrayBuffer.hash = function(arr, raw) { + var hash = md51_array(new Uint8Array(arr)), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + return SparkMD5; + })); + })(sparkMd5); + var SparkMD5 = sparkMd5.exports; + const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; + class FileChecksum { + static create(file, callback) { + const instance = new FileChecksum(file); + instance.create(callback); + } + constructor(file) { + this.file = file; + this.chunkSize = 2097152; + this.chunkCount = Math.ceil(this.file.size / this.chunkSize); + this.chunkIndex = 0; + } + create(callback) { + this.callback = callback; + this.md5Buffer = new SparkMD5.ArrayBuffer; + this.fileReader = new FileReader; + this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event))); + this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event))); + this.readNextChunk(); + } + fileReaderDidLoad(event) { + this.md5Buffer.append(event.target.result); + if (!this.readNextChunk()) { + const binaryDigest = this.md5Buffer.end(true); + const base64digest = btoa(binaryDigest); + this.callback(null, base64digest); + } + } + fileReaderDidError(event) { + this.callback(`Error reading ${this.file.name}`); + } + readNextChunk() { + if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) { + const start = this.chunkIndex * this.chunkSize; + const end = Math.min(start + this.chunkSize, this.file.size); + const bytes = fileSlice.call(this.file, start, end); + this.fileReader.readAsArrayBuffer(bytes); + this.chunkIndex++; + return true; + } else { + return false; + } + } + } + function getMetaValue(name) { + const element = findElement(document.head, `meta[name="${name}"]`); + if (element) { + return element.getAttribute("content"); + } + } + function findElements(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + const elements = root.querySelectorAll(selector); + return toArray(elements); + } + function findElement(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + return root.querySelector(selector); + } + function dispatchEvent(element, type, eventInit = {}) { + const {disabled: disabled} = element; + const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit; + const event = document.createEvent("Event"); + event.initEvent(type, bubbles || true, cancelable || true); + event.detail = detail || {}; + try { + element.disabled = false; + element.dispatchEvent(event); + } finally { + element.disabled = disabled; + } + return event; + } + function toArray(value) { + if (Array.isArray(value)) { + return value; + } else if (Array.from) { + return Array.from(value); + } else { + return [].slice.call(value); + } + } + class BlobRecord { + constructor(file, checksum, url, customHeaders = {}) { + this.file = file; + this.attributes = { + filename: file.name, + content_type: file.type || "application/octet-stream", + byte_size: file.size, + checksum: checksum + }; + this.xhr = new XMLHttpRequest; + this.xhr.open("POST", url, true); + this.xhr.responseType = "json"; + this.xhr.setRequestHeader("Content-Type", "application/json"); + this.xhr.setRequestHeader("Accept", "application/json"); + this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + Object.keys(customHeaders).forEach((headerKey => { + this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]); + })); + const csrfToken = getMetaValue("csrf-token"); + if (csrfToken != undefined) { + this.xhr.setRequestHeader("X-CSRF-Token", csrfToken); + } + this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); + this.xhr.addEventListener("error", (event => this.requestDidError(event))); + } + get status() { + return this.xhr.status; + } + get response() { + const {responseType: responseType, response: response} = this.xhr; + if (responseType == "json") { + return response; + } else { + return JSON.parse(response); + } + } + create(callback) { + this.callback = callback; + this.xhr.send(JSON.stringify({ + blob: this.attributes + })); + } + requestDidLoad(event) { + if (this.status >= 200 && this.status < 300) { + const {response: response} = this; + const {direct_upload: direct_upload} = response; + delete response.direct_upload; + this.attributes = response; + this.directUploadData = direct_upload; + this.callback(null, this.toJSON()); + } else { + this.requestDidError(event); + } + } + requestDidError(event) { + this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`); + } + toJSON() { + const result = {}; + for (const key in this.attributes) { + result[key] = this.attributes[key]; + } + return result; + } + } + class BlobUpload { + constructor(blob) { + this.blob = blob; + this.file = blob.file; + const {url: url, headers: headers} = blob.directUploadData; + this.xhr = new XMLHttpRequest; + this.xhr.open("PUT", url, true); + this.xhr.responseType = "text"; + for (const key in headers) { + this.xhr.setRequestHeader(key, headers[key]); + } + this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); + this.xhr.addEventListener("error", (event => this.requestDidError(event))); + } + create(callback) { + this.callback = callback; + this.xhr.send(this.file.slice()); + } + requestDidLoad(event) { + const {status: status, response: response} = this.xhr; + if (status >= 200 && status < 300) { + this.callback(null, response); + } else { + this.requestDidError(event); + } + } + requestDidError(event) { + this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`); + } + } + let id = 0; + class DirectUpload { + constructor(file, url, delegate, customHeaders = {}) { + this.id = ++id; + this.file = file; + this.url = url; + this.delegate = delegate; + this.customHeaders = customHeaders; + } + create(callback) { + FileChecksum.create(this.file, ((error, checksum) => { + if (error) { + callback(error); + return; + } + const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders); + notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr); + blob.create((error => { + if (error) { + callback(error); + } else { + const upload = new BlobUpload(blob); + notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr); + upload.create((error => { + if (error) { + callback(error); + } else { + callback(null, blob.toJSON()); + } + })); + } + })); + })); + } + } + function notify(object, methodName, ...messages) { + if (object && typeof object[methodName] == "function") { + return object[methodName](...messages); + } + } + class DirectUploadController { + constructor(input, file) { + this.input = input; + this.file = file; + this.directUpload = new DirectUpload(this.file, this.url, this); + this.dispatch("initialize"); + } + start(callback) { + const hiddenInput = document.createElement("input"); + hiddenInput.type = "hidden"; + hiddenInput.name = this.input.name; + this.input.insertAdjacentElement("beforebegin", hiddenInput); + this.dispatch("start"); + this.directUpload.create(((error, attributes) => { + if (error) { + hiddenInput.parentNode.removeChild(hiddenInput); + this.dispatchError(error); + } else { + hiddenInput.value = attributes.signed_id; + } + this.dispatch("end"); + callback(error); + })); + } + uploadRequestDidProgress(event) { + const progress = event.loaded / event.total * 100; + if (progress) { + this.dispatch("progress", { + progress: progress + }); + } + } + get url() { + return this.input.getAttribute("data-direct-upload-url"); + } + dispatch(name, detail = {}) { + detail.file = this.file; + detail.id = this.directUpload.id; + return dispatchEvent(this.input, `direct-upload:${name}`, { + detail: detail + }); + } + dispatchError(error) { + const event = this.dispatch("error", { + error: error + }); + if (!event.defaultPrevented) { + alert(error); + } + } + directUploadWillCreateBlobWithXHR(xhr) { + this.dispatch("before-blob-request", { + xhr: xhr + }); + } + directUploadWillStoreFileWithXHR(xhr) { + this.dispatch("before-storage-request", { + xhr: xhr + }); + xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event))); + } + } + const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])"; + class DirectUploadsController { + constructor(form) { + this.form = form; + this.inputs = findElements(form, inputSelector).filter((input => input.files.length)); + } + start(callback) { + const controllers = this.createDirectUploadControllers(); + const startNextController = () => { + const controller = controllers.shift(); + if (controller) { + controller.start((error => { + if (error) { + callback(error); + this.dispatch("end"); + } else { + startNextController(); + } + })); + } else { + callback(); + this.dispatch("end"); + } + }; + this.dispatch("start"); + startNextController(); + } + createDirectUploadControllers() { + const controllers = []; + this.inputs.forEach((input => { + toArray(input.files).forEach((file => { + const controller = new DirectUploadController(input, file); + controllers.push(controller); + })); + })); + return controllers; + } + dispatch(name, detail = {}) { + return dispatchEvent(this.form, `direct-uploads:${name}`, { + detail: detail + }); + } + } + const processingAttribute = "data-direct-uploads-processing"; + const submitButtonsByForm = new WeakMap; + let started = false; + function start() { + if (!started) { + started = true; + document.addEventListener("click", didClick, true); + document.addEventListener("submit", didSubmitForm, true); + document.addEventListener("ajax:before", didSubmitRemoteElement); + } + } + function didClick(event) { + const button = event.target.closest("button, input"); + if (button && button.type === "submit" && button.form) { + submitButtonsByForm.set(button.form, button); + } + } + function didSubmitForm(event) { + handleFormSubmissionEvent(event); + } + function didSubmitRemoteElement(event) { + if (event.target.tagName == "FORM") { + handleFormSubmissionEvent(event); + } + } + function handleFormSubmissionEvent(event) { + const form = event.target; + if (form.hasAttribute(processingAttribute)) { + event.preventDefault(); + return; + } + const controller = new DirectUploadsController(form); + const {inputs: inputs} = controller; + if (inputs.length) { + event.preventDefault(); + form.setAttribute(processingAttribute, ""); + inputs.forEach(disable); + controller.start((error => { + form.removeAttribute(processingAttribute); + if (error) { + inputs.forEach(enable); + } else { + submitForm(form); + } + })); + } + } + function submitForm(form) { + let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]"); + if (button) { + const {disabled: disabled} = button; + button.disabled = false; + button.focus(); + button.click(); + button.disabled = disabled; + } else { + button = document.createElement("input"); + button.type = "submit"; + button.style.display = "none"; + form.appendChild(button); + button.click(); + form.removeChild(button); + } + submitButtonsByForm.delete(form); + } + function disable(input) { + input.disabled = true; + } + function enable(input) { + input.disabled = false; + } + function autostart() { + if (window.ActiveStorage) { + start(); + } + } + setTimeout(autostart, 1); + class AttachmentUpload { + constructor(attachment, element) { + this.attachment = attachment; + this.element = element; + this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this); + } + start() { + this.directUpload.create(this.directUploadDidComplete.bind(this)); + this.dispatch("start"); + } + directUploadWillStoreFileWithXHR(xhr) { + xhr.upload.addEventListener("progress", (event => { + const progress = event.loaded / event.total * 100; + this.attachment.setUploadProgress(progress); + if (progress) { + this.dispatch("progress", { + progress: progress + }); + } + })); + } + directUploadDidComplete(error, attributes) { + if (error) { + this.dispatchError(error); + } else { + this.attachment.setAttributes({ + sgid: attributes.attachable_sgid, + url: this.createBlobUrl(attributes.signed_id, attributes.filename) + }); + this.dispatch("end"); + } + } + createBlobUrl(signedId, filename) { + return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename)); + } + dispatch(name, detail = {}) { + detail.attachment = this.attachment; + return dispatchEvent(this.element, `direct-upload:${name}`, { + detail: detail + }); + } + dispatchError(error) { + const event = this.dispatch("error", { + error: error + }); + if (!event.defaultPrevented) { + alert(error); + } + } + get directUploadUrl() { + return this.element.dataset.directUploadUrl; + } + get blobUrlTemplate() { + return this.element.dataset.blobUrlTemplate; + } + } + addEventListener("trix-attachment-add", (event => { + const {attachment: attachment, target: target} = event; + if (attachment.file) { + const upload = new AttachmentUpload(attachment, target); + upload.start(); + } + })); +})); diff --git a/backend/public/assets/actiontext-9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d.js.gz b/backend/public/assets/actiontext-9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d.js.gz new file mode 100644 index 0000000..393a007 Binary files /dev/null and b/backend/public/assets/actiontext-9ccbf682451d439611fe5a048e55157c56038840ebb4a8292437eb55fd31c83d.js.gz differ diff --git a/backend/public/assets/actiontext.esm-6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c.js b/backend/public/assets/actiontext.esm-6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c.js new file mode 100644 index 0000000..7902835 --- /dev/null +++ b/backend/public/assets/actiontext.esm-6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c.js @@ -0,0 +1,911 @@ +var sparkMd5 = { + exports: {} +}; + +(function(module, exports) { + (function(factory) { + { + module.exports = factory(); + } + })((function(undefined$1) { + var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ]; + function md5cycle(x, k) { + var a = x[0], b = x[1], c = x[2], d = x[3]; + a += (b & c | ~b & d) + k[0] - 680876936 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[1] - 389564586 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[2] + 606105819 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[3] - 1044525330 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[4] - 176418897 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[5] + 1200080426 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[6] - 1473231341 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[7] - 45705983 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[8] + 1770035416 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[9] - 1958414417 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[10] - 42063 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[11] - 1990404162 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[12] + 1804603682 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[13] - 40341101 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[14] - 1502002290 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[15] + 1236535329 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & d | c & ~d) + k[1] - 165796510 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[6] - 1069501632 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[11] + 643717713 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[0] - 373897302 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[5] - 701558691 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[10] + 38016083 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[15] - 660478335 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[4] - 405537848 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[9] + 568446438 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[14] - 1019803690 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[3] - 187363961 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[8] + 1163531501 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[13] - 1444681467 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[2] - 51403784 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[7] + 1735328473 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[12] - 1926607734 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b ^ c ^ d) + k[5] - 378558 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[8] - 2022574463 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[11] + 1839030562 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[14] - 35309556 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[1] - 1530992060 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[4] + 1272893353 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[7] - 155497632 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[10] - 1094730640 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[13] + 681279174 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[0] - 358537222 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[3] - 722521979 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[6] + 76029189 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[9] - 640364487 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[12] - 421815835 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[15] + 530742520 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[2] - 995338651 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; + b = (b << 21 | b >>> 11) + c | 0; + x[0] = a + x[0] | 0; + x[1] = b + x[1] | 0; + x[2] = c + x[2] | 0; + x[3] = d + x[3] | 0; + } + function md5blk(s) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + } + function md5blk_array(a) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + } + function md51(s) { + var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function md51_array(a) { + var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0); + length = a.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function rhex(n) { + var s = "", j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15]; + } + return s; + } + function hex(x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(""); + } + if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ; + if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) { + (function() { + function clamp(val, length) { + val = val | 0 || 0; + if (val < 0) { + return Math.max(val + length, 0); + } + return Math.min(val, length); + } + ArrayBuffer.prototype.slice = function(from, to) { + var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray; + if (to !== undefined$1) { + end = clamp(to, length); + } + if (begin > end) { + return new ArrayBuffer(0); + } + num = end - begin; + target = new ArrayBuffer(num); + targetArray = new Uint8Array(target); + sourceArray = new Uint8Array(this, begin, num); + targetArray.set(sourceArray); + return target; + }; + })(); + } + function toUtf8(str) { + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + return str; + } + function utf8Str2ArrayBuffer(str, returnUInt8Array) { + var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i; + for (i = 0; i < length; i += 1) { + arr[i] = str.charCodeAt(i); + } + return returnUInt8Array ? arr : buff; + } + function arrayBuffer2Utf8Str(buff) { + return String.fromCharCode.apply(null, new Uint8Array(buff)); + } + function concatenateArrayBuffers(first, second, returnUInt8Array) { + var result = new Uint8Array(first.byteLength + second.byteLength); + result.set(new Uint8Array(first)); + result.set(new Uint8Array(second), first.byteLength); + return returnUInt8Array ? result : result.buffer; + } + function hexToBinaryString(hex) { + var bytes = [], length = hex.length, x; + for (x = 0; x < length - 1; x += 2) { + bytes.push(parseInt(hex.substr(x, 2), 16)); + } + return String.fromCharCode.apply(String, bytes); + } + function SparkMD5() { + this.reset(); + } + SparkMD5.prototype.append = function(str) { + this.appendBinary(toUtf8(str)); + return this; + }; + SparkMD5.prototype.appendBinary = function(contents) { + this._buff += contents; + this._length += contents.length; + var length = this._buff.length, i; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i))); + } + this._buff = this._buff.substring(i - 64); + return this; + }; + SparkMD5.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.prototype.reset = function() { + this._buff = ""; + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.prototype.getState = function() { + return { + buff: this._buff, + length: this._length, + hash: this._hash.slice() + }; + }; + SparkMD5.prototype.setState = function(state) { + this._buff = state.buff; + this._length = state.length; + this._hash = state.hash; + return this; + }; + SparkMD5.prototype.destroy = function() { + delete this._hash; + delete this._buff; + delete this._length; + }; + SparkMD5.prototype._finish = function(tail, length) { + var i = length, tmp, lo, hi; + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(this._hash, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(this._hash, tail); + }; + SparkMD5.hash = function(str, raw) { + return SparkMD5.hashBinary(toUtf8(str), raw); + }; + SparkMD5.hashBinary = function(content, raw) { + var hash = md51(content), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + SparkMD5.ArrayBuffer = function() { + this.reset(); + }; + SparkMD5.ArrayBuffer.prototype.append = function(arr) { + var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i; + this._length += arr.byteLength; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i))); + } + this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0); + return this; + }; + SparkMD5.ArrayBuffer.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.ArrayBuffer.prototype.reset = function() { + this._buff = new Uint8Array(0); + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.ArrayBuffer.prototype.getState = function() { + var state = SparkMD5.prototype.getState.call(this); + state.buff = arrayBuffer2Utf8Str(state.buff); + return state; + }; + SparkMD5.ArrayBuffer.prototype.setState = function(state) { + state.buff = utf8Str2ArrayBuffer(state.buff, true); + return SparkMD5.prototype.setState.call(this, state); + }; + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + SparkMD5.ArrayBuffer.hash = function(arr, raw) { + var hash = md51_array(new Uint8Array(arr)), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + return SparkMD5; + })); +})(sparkMd5); + +var SparkMD5 = sparkMd5.exports; + +const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; + +class FileChecksum { + static create(file, callback) { + const instance = new FileChecksum(file); + instance.create(callback); + } + constructor(file) { + this.file = file; + this.chunkSize = 2097152; + this.chunkCount = Math.ceil(this.file.size / this.chunkSize); + this.chunkIndex = 0; + } + create(callback) { + this.callback = callback; + this.md5Buffer = new SparkMD5.ArrayBuffer; + this.fileReader = new FileReader; + this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event))); + this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event))); + this.readNextChunk(); + } + fileReaderDidLoad(event) { + this.md5Buffer.append(event.target.result); + if (!this.readNextChunk()) { + const binaryDigest = this.md5Buffer.end(true); + const base64digest = btoa(binaryDigest); + this.callback(null, base64digest); + } + } + fileReaderDidError(event) { + this.callback(`Error reading ${this.file.name}`); + } + readNextChunk() { + if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) { + const start = this.chunkIndex * this.chunkSize; + const end = Math.min(start + this.chunkSize, this.file.size); + const bytes = fileSlice.call(this.file, start, end); + this.fileReader.readAsArrayBuffer(bytes); + this.chunkIndex++; + return true; + } else { + return false; + } + } +} + +function getMetaValue(name) { + const element = findElement(document.head, `meta[name="${name}"]`); + if (element) { + return element.getAttribute("content"); + } +} + +function findElements(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + const elements = root.querySelectorAll(selector); + return toArray(elements); +} + +function findElement(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + return root.querySelector(selector); +} + +function dispatchEvent(element, type, eventInit = {}) { + const {disabled: disabled} = element; + const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit; + const event = document.createEvent("Event"); + event.initEvent(type, bubbles || true, cancelable || true); + event.detail = detail || {}; + try { + element.disabled = false; + element.dispatchEvent(event); + } finally { + element.disabled = disabled; + } + return event; +} + +function toArray(value) { + if (Array.isArray(value)) { + return value; + } else if (Array.from) { + return Array.from(value); + } else { + return [].slice.call(value); + } +} + +class BlobRecord { + constructor(file, checksum, url, customHeaders = {}) { + this.file = file; + this.attributes = { + filename: file.name, + content_type: file.type || "application/octet-stream", + byte_size: file.size, + checksum: checksum + }; + this.xhr = new XMLHttpRequest; + this.xhr.open("POST", url, true); + this.xhr.responseType = "json"; + this.xhr.setRequestHeader("Content-Type", "application/json"); + this.xhr.setRequestHeader("Accept", "application/json"); + this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + Object.keys(customHeaders).forEach((headerKey => { + this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]); + })); + const csrfToken = getMetaValue("csrf-token"); + if (csrfToken != undefined) { + this.xhr.setRequestHeader("X-CSRF-Token", csrfToken); + } + this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); + this.xhr.addEventListener("error", (event => this.requestDidError(event))); + } + get status() { + return this.xhr.status; + } + get response() { + const {responseType: responseType, response: response} = this.xhr; + if (responseType == "json") { + return response; + } else { + return JSON.parse(response); + } + } + create(callback) { + this.callback = callback; + this.xhr.send(JSON.stringify({ + blob: this.attributes + })); + } + requestDidLoad(event) { + if (this.status >= 200 && this.status < 300) { + const {response: response} = this; + const {direct_upload: direct_upload} = response; + delete response.direct_upload; + this.attributes = response; + this.directUploadData = direct_upload; + this.callback(null, this.toJSON()); + } else { + this.requestDidError(event); + } + } + requestDidError(event) { + this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`); + } + toJSON() { + const result = {}; + for (const key in this.attributes) { + result[key] = this.attributes[key]; + } + return result; + } +} + +class BlobUpload { + constructor(blob) { + this.blob = blob; + this.file = blob.file; + const {url: url, headers: headers} = blob.directUploadData; + this.xhr = new XMLHttpRequest; + this.xhr.open("PUT", url, true); + this.xhr.responseType = "text"; + for (const key in headers) { + this.xhr.setRequestHeader(key, headers[key]); + } + this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); + this.xhr.addEventListener("error", (event => this.requestDidError(event))); + } + create(callback) { + this.callback = callback; + this.xhr.send(this.file.slice()); + } + requestDidLoad(event) { + const {status: status, response: response} = this.xhr; + if (status >= 200 && status < 300) { + this.callback(null, response); + } else { + this.requestDidError(event); + } + } + requestDidError(event) { + this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`); + } +} + +let id = 0; + +class DirectUpload { + constructor(file, url, delegate, customHeaders = {}) { + this.id = ++id; + this.file = file; + this.url = url; + this.delegate = delegate; + this.customHeaders = customHeaders; + } + create(callback) { + FileChecksum.create(this.file, ((error, checksum) => { + if (error) { + callback(error); + return; + } + const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders); + notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr); + blob.create((error => { + if (error) { + callback(error); + } else { + const upload = new BlobUpload(blob); + notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr); + upload.create((error => { + if (error) { + callback(error); + } else { + callback(null, blob.toJSON()); + } + })); + } + })); + })); + } +} + +function notify(object, methodName, ...messages) { + if (object && typeof object[methodName] == "function") { + return object[methodName](...messages); + } +} + +class DirectUploadController { + constructor(input, file) { + this.input = input; + this.file = file; + this.directUpload = new DirectUpload(this.file, this.url, this); + this.dispatch("initialize"); + } + start(callback) { + const hiddenInput = document.createElement("input"); + hiddenInput.type = "hidden"; + hiddenInput.name = this.input.name; + this.input.insertAdjacentElement("beforebegin", hiddenInput); + this.dispatch("start"); + this.directUpload.create(((error, attributes) => { + if (error) { + hiddenInput.parentNode.removeChild(hiddenInput); + this.dispatchError(error); + } else { + hiddenInput.value = attributes.signed_id; + } + this.dispatch("end"); + callback(error); + })); + } + uploadRequestDidProgress(event) { + const progress = event.loaded / event.total * 100; + if (progress) { + this.dispatch("progress", { + progress: progress + }); + } + } + get url() { + return this.input.getAttribute("data-direct-upload-url"); + } + dispatch(name, detail = {}) { + detail.file = this.file; + detail.id = this.directUpload.id; + return dispatchEvent(this.input, `direct-upload:${name}`, { + detail: detail + }); + } + dispatchError(error) { + const event = this.dispatch("error", { + error: error + }); + if (!event.defaultPrevented) { + alert(error); + } + } + directUploadWillCreateBlobWithXHR(xhr) { + this.dispatch("before-blob-request", { + xhr: xhr + }); + } + directUploadWillStoreFileWithXHR(xhr) { + this.dispatch("before-storage-request", { + xhr: xhr + }); + xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event))); + } +} + +const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])"; + +class DirectUploadsController { + constructor(form) { + this.form = form; + this.inputs = findElements(form, inputSelector).filter((input => input.files.length)); + } + start(callback) { + const controllers = this.createDirectUploadControllers(); + const startNextController = () => { + const controller = controllers.shift(); + if (controller) { + controller.start((error => { + if (error) { + callback(error); + this.dispatch("end"); + } else { + startNextController(); + } + })); + } else { + callback(); + this.dispatch("end"); + } + }; + this.dispatch("start"); + startNextController(); + } + createDirectUploadControllers() { + const controllers = []; + this.inputs.forEach((input => { + toArray(input.files).forEach((file => { + const controller = new DirectUploadController(input, file); + controllers.push(controller); + })); + })); + return controllers; + } + dispatch(name, detail = {}) { + return dispatchEvent(this.form, `direct-uploads:${name}`, { + detail: detail + }); + } +} + +const processingAttribute = "data-direct-uploads-processing"; + +const submitButtonsByForm = new WeakMap; + +let started = false; + +function start() { + if (!started) { + started = true; + document.addEventListener("click", didClick, true); + document.addEventListener("submit", didSubmitForm, true); + document.addEventListener("ajax:before", didSubmitRemoteElement); + } +} + +function didClick(event) { + const button = event.target.closest("button, input"); + if (button && button.type === "submit" && button.form) { + submitButtonsByForm.set(button.form, button); + } +} + +function didSubmitForm(event) { + handleFormSubmissionEvent(event); +} + +function didSubmitRemoteElement(event) { + if (event.target.tagName == "FORM") { + handleFormSubmissionEvent(event); + } +} + +function handleFormSubmissionEvent(event) { + const form = event.target; + if (form.hasAttribute(processingAttribute)) { + event.preventDefault(); + return; + } + const controller = new DirectUploadsController(form); + const {inputs: inputs} = controller; + if (inputs.length) { + event.preventDefault(); + form.setAttribute(processingAttribute, ""); + inputs.forEach(disable); + controller.start((error => { + form.removeAttribute(processingAttribute); + if (error) { + inputs.forEach(enable); + } else { + submitForm(form); + } + })); + } +} + +function submitForm(form) { + let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]"); + if (button) { + const {disabled: disabled} = button; + button.disabled = false; + button.focus(); + button.click(); + button.disabled = disabled; + } else { + button = document.createElement("input"); + button.type = "submit"; + button.style.display = "none"; + form.appendChild(button); + button.click(); + form.removeChild(button); + } + submitButtonsByForm.delete(form); +} + +function disable(input) { + input.disabled = true; +} + +function enable(input) { + input.disabled = false; +} + +function autostart() { + if (window.ActiveStorage) { + start(); + } +} + +setTimeout(autostart, 1); + +class AttachmentUpload { + constructor(attachment, element) { + this.attachment = attachment; + this.element = element; + this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this); + } + start() { + this.directUpload.create(this.directUploadDidComplete.bind(this)); + this.dispatch("start"); + } + directUploadWillStoreFileWithXHR(xhr) { + xhr.upload.addEventListener("progress", (event => { + const progress = event.loaded / event.total * 100; + this.attachment.setUploadProgress(progress); + if (progress) { + this.dispatch("progress", { + progress: progress + }); + } + })); + } + directUploadDidComplete(error, attributes) { + if (error) { + this.dispatchError(error); + } else { + this.attachment.setAttributes({ + sgid: attributes.attachable_sgid, + url: this.createBlobUrl(attributes.signed_id, attributes.filename) + }); + this.dispatch("end"); + } + } + createBlobUrl(signedId, filename) { + return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename)); + } + dispatch(name, detail = {}) { + detail.attachment = this.attachment; + return dispatchEvent(this.element, `direct-upload:${name}`, { + detail: detail + }); + } + dispatchError(error) { + const event = this.dispatch("error", { + error: error + }); + if (!event.defaultPrevented) { + alert(error); + } + } + get directUploadUrl() { + return this.element.dataset.directUploadUrl; + } + get blobUrlTemplate() { + return this.element.dataset.blobUrlTemplate; + } +} + +addEventListener("trix-attachment-add", (event => { + const {attachment: attachment, target: target} = event; + if (attachment.file) { + const upload = new AttachmentUpload(attachment, target); + upload.start(); + } +})); diff --git a/backend/public/assets/actiontext.esm-6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c.js.gz b/backend/public/assets/actiontext.esm-6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c.js.gz new file mode 100644 index 0000000..8339b17 Binary files /dev/null and b/backend/public/assets/actiontext.esm-6790d4daf5458cd6eb8de2d56e754a340caeba909cb2952a35fb478955493d8c.js.gz differ diff --git a/backend/public/assets/activestorage-cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2.js b/backend/public/assets/activestorage-cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2.js new file mode 100644 index 0000000..754c727 --- /dev/null +++ b/backend/public/assets/activestorage-cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2.js @@ -0,0 +1,830 @@ +(function(global, factory) { + typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, + factory(global.ActiveStorage = {})); +})(this, (function(exports) { + "use strict"; + var sparkMd5 = { + exports: {} + }; + (function(module, exports) { + (function(factory) { + { + module.exports = factory(); + } + })((function(undefined$1) { + var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ]; + function md5cycle(x, k) { + var a = x[0], b = x[1], c = x[2], d = x[3]; + a += (b & c | ~b & d) + k[0] - 680876936 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[1] - 389564586 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[2] + 606105819 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[3] - 1044525330 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[4] - 176418897 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[5] + 1200080426 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[6] - 1473231341 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[7] - 45705983 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[8] + 1770035416 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[9] - 1958414417 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[10] - 42063 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[11] - 1990404162 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[12] + 1804603682 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[13] - 40341101 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[14] - 1502002290 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[15] + 1236535329 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & d | c & ~d) + k[1] - 165796510 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[6] - 1069501632 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[11] + 643717713 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[0] - 373897302 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[5] - 701558691 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[10] + 38016083 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[15] - 660478335 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[4] - 405537848 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[9] + 568446438 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[14] - 1019803690 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[3] - 187363961 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[8] + 1163531501 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[13] - 1444681467 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[2] - 51403784 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[7] + 1735328473 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[12] - 1926607734 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b ^ c ^ d) + k[5] - 378558 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[8] - 2022574463 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[11] + 1839030562 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[14] - 35309556 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[1] - 1530992060 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[4] + 1272893353 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[7] - 155497632 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[10] - 1094730640 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[13] + 681279174 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[0] - 358537222 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[3] - 722521979 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[6] + 76029189 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[9] - 640364487 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[12] - 421815835 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[15] + 530742520 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[2] - 995338651 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; + b = (b << 21 | b >>> 11) + c | 0; + x[0] = a + x[0] | 0; + x[1] = b + x[1] | 0; + x[2] = c + x[2] | 0; + x[3] = d + x[3] | 0; + } + function md5blk(s) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + } + function md5blk_array(a) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + } + function md51(s) { + var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function md51_array(a) { + var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0); + length = a.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function rhex(n) { + var s = "", j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15]; + } + return s; + } + function hex(x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(""); + } + if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ; + if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) { + (function() { + function clamp(val, length) { + val = val | 0 || 0; + if (val < 0) { + return Math.max(val + length, 0); + } + return Math.min(val, length); + } + ArrayBuffer.prototype.slice = function(from, to) { + var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray; + if (to !== undefined$1) { + end = clamp(to, length); + } + if (begin > end) { + return new ArrayBuffer(0); + } + num = end - begin; + target = new ArrayBuffer(num); + targetArray = new Uint8Array(target); + sourceArray = new Uint8Array(this, begin, num); + targetArray.set(sourceArray); + return target; + }; + })(); + } + function toUtf8(str) { + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + return str; + } + function utf8Str2ArrayBuffer(str, returnUInt8Array) { + var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i; + for (i = 0; i < length; i += 1) { + arr[i] = str.charCodeAt(i); + } + return returnUInt8Array ? arr : buff; + } + function arrayBuffer2Utf8Str(buff) { + return String.fromCharCode.apply(null, new Uint8Array(buff)); + } + function concatenateArrayBuffers(first, second, returnUInt8Array) { + var result = new Uint8Array(first.byteLength + second.byteLength); + result.set(new Uint8Array(first)); + result.set(new Uint8Array(second), first.byteLength); + return returnUInt8Array ? result : result.buffer; + } + function hexToBinaryString(hex) { + var bytes = [], length = hex.length, x; + for (x = 0; x < length - 1; x += 2) { + bytes.push(parseInt(hex.substr(x, 2), 16)); + } + return String.fromCharCode.apply(String, bytes); + } + function SparkMD5() { + this.reset(); + } + SparkMD5.prototype.append = function(str) { + this.appendBinary(toUtf8(str)); + return this; + }; + SparkMD5.prototype.appendBinary = function(contents) { + this._buff += contents; + this._length += contents.length; + var length = this._buff.length, i; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i))); + } + this._buff = this._buff.substring(i - 64); + return this; + }; + SparkMD5.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.prototype.reset = function() { + this._buff = ""; + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.prototype.getState = function() { + return { + buff: this._buff, + length: this._length, + hash: this._hash.slice() + }; + }; + SparkMD5.prototype.setState = function(state) { + this._buff = state.buff; + this._length = state.length; + this._hash = state.hash; + return this; + }; + SparkMD5.prototype.destroy = function() { + delete this._hash; + delete this._buff; + delete this._length; + }; + SparkMD5.prototype._finish = function(tail, length) { + var i = length, tmp, lo, hi; + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(this._hash, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(this._hash, tail); + }; + SparkMD5.hash = function(str, raw) { + return SparkMD5.hashBinary(toUtf8(str), raw); + }; + SparkMD5.hashBinary = function(content, raw) { + var hash = md51(content), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + SparkMD5.ArrayBuffer = function() { + this.reset(); + }; + SparkMD5.ArrayBuffer.prototype.append = function(arr) { + var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i; + this._length += arr.byteLength; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i))); + } + this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0); + return this; + }; + SparkMD5.ArrayBuffer.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.ArrayBuffer.prototype.reset = function() { + this._buff = new Uint8Array(0); + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.ArrayBuffer.prototype.getState = function() { + var state = SparkMD5.prototype.getState.call(this); + state.buff = arrayBuffer2Utf8Str(state.buff); + return state; + }; + SparkMD5.ArrayBuffer.prototype.setState = function(state) { + state.buff = utf8Str2ArrayBuffer(state.buff, true); + return SparkMD5.prototype.setState.call(this, state); + }; + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + SparkMD5.ArrayBuffer.hash = function(arr, raw) { + var hash = md51_array(new Uint8Array(arr)), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + return SparkMD5; + })); + })(sparkMd5); + var SparkMD5 = sparkMd5.exports; + const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; + class FileChecksum { + static create(file, callback) { + const instance = new FileChecksum(file); + instance.create(callback); + } + constructor(file) { + this.file = file; + this.chunkSize = 2097152; + this.chunkCount = Math.ceil(this.file.size / this.chunkSize); + this.chunkIndex = 0; + } + create(callback) { + this.callback = callback; + this.md5Buffer = new SparkMD5.ArrayBuffer; + this.fileReader = new FileReader; + this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event))); + this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event))); + this.readNextChunk(); + } + fileReaderDidLoad(event) { + this.md5Buffer.append(event.target.result); + if (!this.readNextChunk()) { + const binaryDigest = this.md5Buffer.end(true); + const base64digest = btoa(binaryDigest); + this.callback(null, base64digest); + } + } + fileReaderDidError(event) { + this.callback(`Error reading ${this.file.name}`); + } + readNextChunk() { + if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) { + const start = this.chunkIndex * this.chunkSize; + const end = Math.min(start + this.chunkSize, this.file.size); + const bytes = fileSlice.call(this.file, start, end); + this.fileReader.readAsArrayBuffer(bytes); + this.chunkIndex++; + return true; + } else { + return false; + } + } + } + function getMetaValue(name) { + const element = findElement(document.head, `meta[name="${name}"]`); + if (element) { + return element.getAttribute("content"); + } + } + function findElements(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + const elements = root.querySelectorAll(selector); + return toArray(elements); + } + function findElement(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + return root.querySelector(selector); + } + function dispatchEvent(element, type, eventInit = {}) { + const {disabled: disabled} = element; + const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit; + const event = document.createEvent("Event"); + event.initEvent(type, bubbles || true, cancelable || true); + event.detail = detail || {}; + try { + element.disabled = false; + element.dispatchEvent(event); + } finally { + element.disabled = disabled; + } + return event; + } + function toArray(value) { + if (Array.isArray(value)) { + return value; + } else if (Array.from) { + return Array.from(value); + } else { + return [].slice.call(value); + } + } + class BlobRecord { + constructor(file, checksum, url, customHeaders = {}) { + this.file = file; + this.attributes = { + filename: file.name, + content_type: file.type || "application/octet-stream", + byte_size: file.size, + checksum: checksum + }; + this.xhr = new XMLHttpRequest; + this.xhr.open("POST", url, true); + this.xhr.responseType = "json"; + this.xhr.setRequestHeader("Content-Type", "application/json"); + this.xhr.setRequestHeader("Accept", "application/json"); + this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + Object.keys(customHeaders).forEach((headerKey => { + this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]); + })); + const csrfToken = getMetaValue("csrf-token"); + if (csrfToken != undefined) { + this.xhr.setRequestHeader("X-CSRF-Token", csrfToken); + } + this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); + this.xhr.addEventListener("error", (event => this.requestDidError(event))); + } + get status() { + return this.xhr.status; + } + get response() { + const {responseType: responseType, response: response} = this.xhr; + if (responseType == "json") { + return response; + } else { + return JSON.parse(response); + } + } + create(callback) { + this.callback = callback; + this.xhr.send(JSON.stringify({ + blob: this.attributes + })); + } + requestDidLoad(event) { + if (this.status >= 200 && this.status < 300) { + const {response: response} = this; + const {direct_upload: direct_upload} = response; + delete response.direct_upload; + this.attributes = response; + this.directUploadData = direct_upload; + this.callback(null, this.toJSON()); + } else { + this.requestDidError(event); + } + } + requestDidError(event) { + this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`); + } + toJSON() { + const result = {}; + for (const key in this.attributes) { + result[key] = this.attributes[key]; + } + return result; + } + } + class BlobUpload { + constructor(blob) { + this.blob = blob; + this.file = blob.file; + const {url: url, headers: headers} = blob.directUploadData; + this.xhr = new XMLHttpRequest; + this.xhr.open("PUT", url, true); + this.xhr.responseType = "text"; + for (const key in headers) { + this.xhr.setRequestHeader(key, headers[key]); + } + this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); + this.xhr.addEventListener("error", (event => this.requestDidError(event))); + } + create(callback) { + this.callback = callback; + this.xhr.send(this.file.slice()); + } + requestDidLoad(event) { + const {status: status, response: response} = this.xhr; + if (status >= 200 && status < 300) { + this.callback(null, response); + } else { + this.requestDidError(event); + } + } + requestDidError(event) { + this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`); + } + } + let id = 0; + class DirectUpload { + constructor(file, url, delegate, customHeaders = {}) { + this.id = ++id; + this.file = file; + this.url = url; + this.delegate = delegate; + this.customHeaders = customHeaders; + } + create(callback) { + FileChecksum.create(this.file, ((error, checksum) => { + if (error) { + callback(error); + return; + } + const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders); + notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr); + blob.create((error => { + if (error) { + callback(error); + } else { + const upload = new BlobUpload(blob); + notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr); + upload.create((error => { + if (error) { + callback(error); + } else { + callback(null, blob.toJSON()); + } + })); + } + })); + })); + } + } + function notify(object, methodName, ...messages) { + if (object && typeof object[methodName] == "function") { + return object[methodName](...messages); + } + } + class DirectUploadController { + constructor(input, file) { + this.input = input; + this.file = file; + this.directUpload = new DirectUpload(this.file, this.url, this); + this.dispatch("initialize"); + } + start(callback) { + const hiddenInput = document.createElement("input"); + hiddenInput.type = "hidden"; + hiddenInput.name = this.input.name; + this.input.insertAdjacentElement("beforebegin", hiddenInput); + this.dispatch("start"); + this.directUpload.create(((error, attributes) => { + if (error) { + hiddenInput.parentNode.removeChild(hiddenInput); + this.dispatchError(error); + } else { + hiddenInput.value = attributes.signed_id; + } + this.dispatch("end"); + callback(error); + })); + } + uploadRequestDidProgress(event) { + const progress = event.loaded / event.total * 100; + if (progress) { + this.dispatch("progress", { + progress: progress + }); + } + } + get url() { + return this.input.getAttribute("data-direct-upload-url"); + } + dispatch(name, detail = {}) { + detail.file = this.file; + detail.id = this.directUpload.id; + return dispatchEvent(this.input, `direct-upload:${name}`, { + detail: detail + }); + } + dispatchError(error) { + const event = this.dispatch("error", { + error: error + }); + if (!event.defaultPrevented) { + alert(error); + } + } + directUploadWillCreateBlobWithXHR(xhr) { + this.dispatch("before-blob-request", { + xhr: xhr + }); + } + directUploadWillStoreFileWithXHR(xhr) { + this.dispatch("before-storage-request", { + xhr: xhr + }); + xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event))); + } + } + const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])"; + class DirectUploadsController { + constructor(form) { + this.form = form; + this.inputs = findElements(form, inputSelector).filter((input => input.files.length)); + } + start(callback) { + const controllers = this.createDirectUploadControllers(); + const startNextController = () => { + const controller = controllers.shift(); + if (controller) { + controller.start((error => { + if (error) { + callback(error); + this.dispatch("end"); + } else { + startNextController(); + } + })); + } else { + callback(); + this.dispatch("end"); + } + }; + this.dispatch("start"); + startNextController(); + } + createDirectUploadControllers() { + const controllers = []; + this.inputs.forEach((input => { + toArray(input.files).forEach((file => { + const controller = new DirectUploadController(input, file); + controllers.push(controller); + })); + })); + return controllers; + } + dispatch(name, detail = {}) { + return dispatchEvent(this.form, `direct-uploads:${name}`, { + detail: detail + }); + } + } + const processingAttribute = "data-direct-uploads-processing"; + const submitButtonsByForm = new WeakMap; + let started = false; + function start() { + if (!started) { + started = true; + document.addEventListener("click", didClick, true); + document.addEventListener("submit", didSubmitForm, true); + document.addEventListener("ajax:before", didSubmitRemoteElement); + } + } + function didClick(event) { + const button = event.target.closest("button, input"); + if (button && button.type === "submit" && button.form) { + submitButtonsByForm.set(button.form, button); + } + } + function didSubmitForm(event) { + handleFormSubmissionEvent(event); + } + function didSubmitRemoteElement(event) { + if (event.target.tagName == "FORM") { + handleFormSubmissionEvent(event); + } + } + function handleFormSubmissionEvent(event) { + const form = event.target; + if (form.hasAttribute(processingAttribute)) { + event.preventDefault(); + return; + } + const controller = new DirectUploadsController(form); + const {inputs: inputs} = controller; + if (inputs.length) { + event.preventDefault(); + form.setAttribute(processingAttribute, ""); + inputs.forEach(disable); + controller.start((error => { + form.removeAttribute(processingAttribute); + if (error) { + inputs.forEach(enable); + } else { + submitForm(form); + } + })); + } + } + function submitForm(form) { + let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]"); + if (button) { + const {disabled: disabled} = button; + button.disabled = false; + button.focus(); + button.click(); + button.disabled = disabled; + } else { + button = document.createElement("input"); + button.type = "submit"; + button.style.display = "none"; + form.appendChild(button); + button.click(); + form.removeChild(button); + } + submitButtonsByForm.delete(form); + } + function disable(input) { + input.disabled = true; + } + function enable(input) { + input.disabled = false; + } + function autostart() { + if (window.ActiveStorage) { + start(); + } + } + setTimeout(autostart, 1); + exports.DirectUpload = DirectUpload; + exports.DirectUploadController = DirectUploadController; + exports.DirectUploadsController = DirectUploadsController; + exports.dispatchEvent = dispatchEvent; + exports.start = start; + Object.defineProperty(exports, "__esModule", { + value: true + }); +})); diff --git a/backend/public/assets/activestorage-cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2.js.gz b/backend/public/assets/activestorage-cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2.js.gz new file mode 100644 index 0000000..41703fb Binary files /dev/null and b/backend/public/assets/activestorage-cf22a497d1956e8f0d3ec50f45d68961aa0d138ee062802c36ae384efb260aa2.js.gz differ diff --git a/backend/public/assets/activestorage.esm-8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485.js b/backend/public/assets/activestorage.esm-8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485.js new file mode 100644 index 0000000..1ac9835 --- /dev/null +++ b/backend/public/assets/activestorage.esm-8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485.js @@ -0,0 +1,848 @@ +var sparkMd5 = { + exports: {} +}; + +(function(module, exports) { + (function(factory) { + { + module.exports = factory(); + } + })((function(undefined$1) { + var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ]; + function md5cycle(x, k) { + var a = x[0], b = x[1], c = x[2], d = x[3]; + a += (b & c | ~b & d) + k[0] - 680876936 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[1] - 389564586 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[2] + 606105819 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[3] - 1044525330 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[4] - 176418897 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[5] + 1200080426 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[6] - 1473231341 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[7] - 45705983 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[8] + 1770035416 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[9] - 1958414417 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[10] - 42063 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[11] - 1990404162 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[12] + 1804603682 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[13] - 40341101 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[14] - 1502002290 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[15] + 1236535329 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & d | c & ~d) + k[1] - 165796510 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[6] - 1069501632 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[11] + 643717713 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[0] - 373897302 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[5] - 701558691 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[10] + 38016083 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[15] - 660478335 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[4] - 405537848 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[9] + 568446438 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[14] - 1019803690 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[3] - 187363961 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[8] + 1163531501 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[13] - 1444681467 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[2] - 51403784 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[7] + 1735328473 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[12] - 1926607734 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b ^ c ^ d) + k[5] - 378558 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[8] - 2022574463 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[11] + 1839030562 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[14] - 35309556 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[1] - 1530992060 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[4] + 1272893353 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[7] - 155497632 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[10] - 1094730640 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[13] + 681279174 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[0] - 358537222 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[3] - 722521979 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[6] + 76029189 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[9] - 640364487 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[12] - 421815835 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[15] + 530742520 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[2] - 995338651 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; + b = (b << 21 | b >>> 11) + c | 0; + x[0] = a + x[0] | 0; + x[1] = b + x[1] | 0; + x[2] = c + x[2] | 0; + x[3] = d + x[3] | 0; + } + function md5blk(s) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + } + function md5blk_array(a) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + } + function md51(s) { + var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function md51_array(a) { + var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0); + length = a.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function rhex(n) { + var s = "", j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15]; + } + return s; + } + function hex(x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(""); + } + if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ; + if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) { + (function() { + function clamp(val, length) { + val = val | 0 || 0; + if (val < 0) { + return Math.max(val + length, 0); + } + return Math.min(val, length); + } + ArrayBuffer.prototype.slice = function(from, to) { + var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray; + if (to !== undefined$1) { + end = clamp(to, length); + } + if (begin > end) { + return new ArrayBuffer(0); + } + num = end - begin; + target = new ArrayBuffer(num); + targetArray = new Uint8Array(target); + sourceArray = new Uint8Array(this, begin, num); + targetArray.set(sourceArray); + return target; + }; + })(); + } + function toUtf8(str) { + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + return str; + } + function utf8Str2ArrayBuffer(str, returnUInt8Array) { + var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i; + for (i = 0; i < length; i += 1) { + arr[i] = str.charCodeAt(i); + } + return returnUInt8Array ? arr : buff; + } + function arrayBuffer2Utf8Str(buff) { + return String.fromCharCode.apply(null, new Uint8Array(buff)); + } + function concatenateArrayBuffers(first, second, returnUInt8Array) { + var result = new Uint8Array(first.byteLength + second.byteLength); + result.set(new Uint8Array(first)); + result.set(new Uint8Array(second), first.byteLength); + return returnUInt8Array ? result : result.buffer; + } + function hexToBinaryString(hex) { + var bytes = [], length = hex.length, x; + for (x = 0; x < length - 1; x += 2) { + bytes.push(parseInt(hex.substr(x, 2), 16)); + } + return String.fromCharCode.apply(String, bytes); + } + function SparkMD5() { + this.reset(); + } + SparkMD5.prototype.append = function(str) { + this.appendBinary(toUtf8(str)); + return this; + }; + SparkMD5.prototype.appendBinary = function(contents) { + this._buff += contents; + this._length += contents.length; + var length = this._buff.length, i; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i))); + } + this._buff = this._buff.substring(i - 64); + return this; + }; + SparkMD5.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.prototype.reset = function() { + this._buff = ""; + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.prototype.getState = function() { + return { + buff: this._buff, + length: this._length, + hash: this._hash.slice() + }; + }; + SparkMD5.prototype.setState = function(state) { + this._buff = state.buff; + this._length = state.length; + this._hash = state.hash; + return this; + }; + SparkMD5.prototype.destroy = function() { + delete this._hash; + delete this._buff; + delete this._length; + }; + SparkMD5.prototype._finish = function(tail, length) { + var i = length, tmp, lo, hi; + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(this._hash, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(this._hash, tail); + }; + SparkMD5.hash = function(str, raw) { + return SparkMD5.hashBinary(toUtf8(str), raw); + }; + SparkMD5.hashBinary = function(content, raw) { + var hash = md51(content), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + SparkMD5.ArrayBuffer = function() { + this.reset(); + }; + SparkMD5.ArrayBuffer.prototype.append = function(arr) { + var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i; + this._length += arr.byteLength; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i))); + } + this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0); + return this; + }; + SparkMD5.ArrayBuffer.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.ArrayBuffer.prototype.reset = function() { + this._buff = new Uint8Array(0); + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.ArrayBuffer.prototype.getState = function() { + var state = SparkMD5.prototype.getState.call(this); + state.buff = arrayBuffer2Utf8Str(state.buff); + return state; + }; + SparkMD5.ArrayBuffer.prototype.setState = function(state) { + state.buff = utf8Str2ArrayBuffer(state.buff, true); + return SparkMD5.prototype.setState.call(this, state); + }; + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + SparkMD5.ArrayBuffer.hash = function(arr, raw) { + var hash = md51_array(new Uint8Array(arr)), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + return SparkMD5; + })); +})(sparkMd5); + +var SparkMD5 = sparkMd5.exports; + +const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; + +class FileChecksum { + static create(file, callback) { + const instance = new FileChecksum(file); + instance.create(callback); + } + constructor(file) { + this.file = file; + this.chunkSize = 2097152; + this.chunkCount = Math.ceil(this.file.size / this.chunkSize); + this.chunkIndex = 0; + } + create(callback) { + this.callback = callback; + this.md5Buffer = new SparkMD5.ArrayBuffer; + this.fileReader = new FileReader; + this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event))); + this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event))); + this.readNextChunk(); + } + fileReaderDidLoad(event) { + this.md5Buffer.append(event.target.result); + if (!this.readNextChunk()) { + const binaryDigest = this.md5Buffer.end(true); + const base64digest = btoa(binaryDigest); + this.callback(null, base64digest); + } + } + fileReaderDidError(event) { + this.callback(`Error reading ${this.file.name}`); + } + readNextChunk() { + if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) { + const start = this.chunkIndex * this.chunkSize; + const end = Math.min(start + this.chunkSize, this.file.size); + const bytes = fileSlice.call(this.file, start, end); + this.fileReader.readAsArrayBuffer(bytes); + this.chunkIndex++; + return true; + } else { + return false; + } + } +} + +function getMetaValue(name) { + const element = findElement(document.head, `meta[name="${name}"]`); + if (element) { + return element.getAttribute("content"); + } +} + +function findElements(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + const elements = root.querySelectorAll(selector); + return toArray(elements); +} + +function findElement(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + return root.querySelector(selector); +} + +function dispatchEvent(element, type, eventInit = {}) { + const {disabled: disabled} = element; + const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit; + const event = document.createEvent("Event"); + event.initEvent(type, bubbles || true, cancelable || true); + event.detail = detail || {}; + try { + element.disabled = false; + element.dispatchEvent(event); + } finally { + element.disabled = disabled; + } + return event; +} + +function toArray(value) { + if (Array.isArray(value)) { + return value; + } else if (Array.from) { + return Array.from(value); + } else { + return [].slice.call(value); + } +} + +class BlobRecord { + constructor(file, checksum, url, customHeaders = {}) { + this.file = file; + this.attributes = { + filename: file.name, + content_type: file.type || "application/octet-stream", + byte_size: file.size, + checksum: checksum + }; + this.xhr = new XMLHttpRequest; + this.xhr.open("POST", url, true); + this.xhr.responseType = "json"; + this.xhr.setRequestHeader("Content-Type", "application/json"); + this.xhr.setRequestHeader("Accept", "application/json"); + this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + Object.keys(customHeaders).forEach((headerKey => { + this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]); + })); + const csrfToken = getMetaValue("csrf-token"); + if (csrfToken != undefined) { + this.xhr.setRequestHeader("X-CSRF-Token", csrfToken); + } + this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); + this.xhr.addEventListener("error", (event => this.requestDidError(event))); + } + get status() { + return this.xhr.status; + } + get response() { + const {responseType: responseType, response: response} = this.xhr; + if (responseType == "json") { + return response; + } else { + return JSON.parse(response); + } + } + create(callback) { + this.callback = callback; + this.xhr.send(JSON.stringify({ + blob: this.attributes + })); + } + requestDidLoad(event) { + if (this.status >= 200 && this.status < 300) { + const {response: response} = this; + const {direct_upload: direct_upload} = response; + delete response.direct_upload; + this.attributes = response; + this.directUploadData = direct_upload; + this.callback(null, this.toJSON()); + } else { + this.requestDidError(event); + } + } + requestDidError(event) { + this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`); + } + toJSON() { + const result = {}; + for (const key in this.attributes) { + result[key] = this.attributes[key]; + } + return result; + } +} + +class BlobUpload { + constructor(blob) { + this.blob = blob; + this.file = blob.file; + const {url: url, headers: headers} = blob.directUploadData; + this.xhr = new XMLHttpRequest; + this.xhr.open("PUT", url, true); + this.xhr.responseType = "text"; + for (const key in headers) { + this.xhr.setRequestHeader(key, headers[key]); + } + this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); + this.xhr.addEventListener("error", (event => this.requestDidError(event))); + } + create(callback) { + this.callback = callback; + this.xhr.send(this.file.slice()); + } + requestDidLoad(event) { + const {status: status, response: response} = this.xhr; + if (status >= 200 && status < 300) { + this.callback(null, response); + } else { + this.requestDidError(event); + } + } + requestDidError(event) { + this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`); + } +} + +let id = 0; + +class DirectUpload { + constructor(file, url, delegate, customHeaders = {}) { + this.id = ++id; + this.file = file; + this.url = url; + this.delegate = delegate; + this.customHeaders = customHeaders; + } + create(callback) { + FileChecksum.create(this.file, ((error, checksum) => { + if (error) { + callback(error); + return; + } + const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders); + notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr); + blob.create((error => { + if (error) { + callback(error); + } else { + const upload = new BlobUpload(blob); + notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr); + upload.create((error => { + if (error) { + callback(error); + } else { + callback(null, blob.toJSON()); + } + })); + } + })); + })); + } +} + +function notify(object, methodName, ...messages) { + if (object && typeof object[methodName] == "function") { + return object[methodName](...messages); + } +} + +class DirectUploadController { + constructor(input, file) { + this.input = input; + this.file = file; + this.directUpload = new DirectUpload(this.file, this.url, this); + this.dispatch("initialize"); + } + start(callback) { + const hiddenInput = document.createElement("input"); + hiddenInput.type = "hidden"; + hiddenInput.name = this.input.name; + this.input.insertAdjacentElement("beforebegin", hiddenInput); + this.dispatch("start"); + this.directUpload.create(((error, attributes) => { + if (error) { + hiddenInput.parentNode.removeChild(hiddenInput); + this.dispatchError(error); + } else { + hiddenInput.value = attributes.signed_id; + } + this.dispatch("end"); + callback(error); + })); + } + uploadRequestDidProgress(event) { + const progress = event.loaded / event.total * 100; + if (progress) { + this.dispatch("progress", { + progress: progress + }); + } + } + get url() { + return this.input.getAttribute("data-direct-upload-url"); + } + dispatch(name, detail = {}) { + detail.file = this.file; + detail.id = this.directUpload.id; + return dispatchEvent(this.input, `direct-upload:${name}`, { + detail: detail + }); + } + dispatchError(error) { + const event = this.dispatch("error", { + error: error + }); + if (!event.defaultPrevented) { + alert(error); + } + } + directUploadWillCreateBlobWithXHR(xhr) { + this.dispatch("before-blob-request", { + xhr: xhr + }); + } + directUploadWillStoreFileWithXHR(xhr) { + this.dispatch("before-storage-request", { + xhr: xhr + }); + xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event))); + } +} + +const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])"; + +class DirectUploadsController { + constructor(form) { + this.form = form; + this.inputs = findElements(form, inputSelector).filter((input => input.files.length)); + } + start(callback) { + const controllers = this.createDirectUploadControllers(); + const startNextController = () => { + const controller = controllers.shift(); + if (controller) { + controller.start((error => { + if (error) { + callback(error); + this.dispatch("end"); + } else { + startNextController(); + } + })); + } else { + callback(); + this.dispatch("end"); + } + }; + this.dispatch("start"); + startNextController(); + } + createDirectUploadControllers() { + const controllers = []; + this.inputs.forEach((input => { + toArray(input.files).forEach((file => { + const controller = new DirectUploadController(input, file); + controllers.push(controller); + })); + })); + return controllers; + } + dispatch(name, detail = {}) { + return dispatchEvent(this.form, `direct-uploads:${name}`, { + detail: detail + }); + } +} + +const processingAttribute = "data-direct-uploads-processing"; + +const submitButtonsByForm = new WeakMap; + +let started = false; + +function start() { + if (!started) { + started = true; + document.addEventListener("click", didClick, true); + document.addEventListener("submit", didSubmitForm, true); + document.addEventListener("ajax:before", didSubmitRemoteElement); + } +} + +function didClick(event) { + const button = event.target.closest("button, input"); + if (button && button.type === "submit" && button.form) { + submitButtonsByForm.set(button.form, button); + } +} + +function didSubmitForm(event) { + handleFormSubmissionEvent(event); +} + +function didSubmitRemoteElement(event) { + if (event.target.tagName == "FORM") { + handleFormSubmissionEvent(event); + } +} + +function handleFormSubmissionEvent(event) { + const form = event.target; + if (form.hasAttribute(processingAttribute)) { + event.preventDefault(); + return; + } + const controller = new DirectUploadsController(form); + const {inputs: inputs} = controller; + if (inputs.length) { + event.preventDefault(); + form.setAttribute(processingAttribute, ""); + inputs.forEach(disable); + controller.start((error => { + form.removeAttribute(processingAttribute); + if (error) { + inputs.forEach(enable); + } else { + submitForm(form); + } + })); + } +} + +function submitForm(form) { + let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]"); + if (button) { + const {disabled: disabled} = button; + button.disabled = false; + button.focus(); + button.click(); + button.disabled = disabled; + } else { + button = document.createElement("input"); + button.type = "submit"; + button.style.display = "none"; + form.appendChild(button); + button.click(); + form.removeChild(button); + } + submitButtonsByForm.delete(form); +} + +function disable(input) { + input.disabled = true; +} + +function enable(input) { + input.disabled = false; +} + +function autostart() { + if (window.ActiveStorage) { + start(); + } +} + +setTimeout(autostart, 1); + +export { DirectUpload, DirectUploadController, DirectUploadsController, dispatchEvent, start }; diff --git a/backend/public/assets/activestorage.esm-8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485.js.gz b/backend/public/assets/activestorage.esm-8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485.js.gz new file mode 100644 index 0000000..074d5a2 Binary files /dev/null and b/backend/public/assets/activestorage.esm-8bb028228e622c50501b3eb269cbe4044a46da07b565a90e5ae6f221dc06e485.js.gz differ diff --git a/backend/public/assets/manifest-6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167.js b/backend/public/assets/manifest-6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167.js new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/backend/public/assets/manifest-6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167.js @@ -0,0 +1,3 @@ + + + diff --git a/backend/public/assets/manifest-6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167.js.gz b/backend/public/assets/manifest-6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167.js.gz new file mode 100644 index 0000000..a8e8ffe Binary files /dev/null and b/backend/public/assets/manifest-6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167.js.gz differ diff --git a/backend/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js b/backend/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js new file mode 100644 index 0000000..1cd185f --- /dev/null +++ b/backend/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js @@ -0,0 +1,13720 @@ +/* +Trix 2.1.10 +Copyright © 2024 37signals, LLC + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Trix = factory()); +})(this, (function () { 'use strict'; + + var name = "trix"; + var version = "2.1.10"; + var description = "A rich text editor for everyday writing"; + var main = "dist/trix.umd.min.js"; + var module = "dist/trix.esm.min.js"; + var style = "dist/trix.css"; + var files = [ + "dist/*.css", + "dist/*.js", + "dist/*.map", + "src/{inspector,trix}/*.js" + ]; + var repository = { + type: "git", + url: "git+https://github.com/basecamp/trix.git" + }; + var keywords = [ + "rich text", + "wysiwyg", + "editor" + ]; + var author = "37signals, LLC"; + var license = "MIT"; + var bugs = { + url: "https://github.com/basecamp/trix/issues" + }; + var homepage = "https://trix-editor.org/"; + var devDependencies = { + "@babel/core": "^7.16.0", + "@babel/preset-env": "^7.16.4", + "@rollup/plugin-babel": "^5.3.0", + "@rollup/plugin-commonjs": "^22.0.2", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.3.0", + "@web/dev-server": "^0.1.34", + "babel-eslint": "^10.1.0", + concurrently: "^7.4.0", + eslint: "^7.32.0", + esm: "^3.2.25", + karma: "6.4.1", + "karma-chrome-launcher": "3.2.0", + "karma-qunit": "^4.1.2", + "karma-sauce-launcher": "^4.3.6", + "node-sass": "^7.0.1", + qunit: "2.19.1", + rangy: "^1.3.0", + rollup: "^2.56.3", + "rollup-plugin-includepaths": "^0.2.4", + "rollup-plugin-terser": "^7.0.2", + svgo: "^2.8.0", + webdriverio: "^7.19.5" + }; + var resolutions = { + webdriverio: "^7.19.5" + }; + var scripts = { + "build-css": "node-sass --functions=./assets/trix/stylesheets/functions assets/trix.scss dist/trix.css", + "build-js": "rollup -c", + "build-assets": "cp -f assets/*.html dist/", + build: "yarn run build-js && yarn run build-css && yarn run build-assets", + watch: "rollup -c -w", + lint: "eslint .", + pretest: "yarn run lint && yarn run build", + test: "karma start", + prerelease: "yarn version && yarn test", + release: "npm adduser && npm publish", + postrelease: "git push && git push --tags", + dev: "web-dev-server --app-index index.html --root-dir dist --node-resolve --open", + start: "yarn build-assets && concurrently --kill-others --names js,css,dev-server 'yarn watch' 'yarn build-css --watch' 'yarn dev'" + }; + var dependencies = { + dompurify: "^3.2.3" + }; + var _package = { + name: name, + version: version, + description: description, + main: main, + module: module, + style: style, + files: files, + repository: repository, + keywords: keywords, + author: author, + license: license, + bugs: bugs, + homepage: homepage, + devDependencies: devDependencies, + resolutions: resolutions, + scripts: scripts, + dependencies: dependencies + }; + + const attachmentSelector = "[data-trix-attachment]"; + const attachments = { + preview: { + presentation: "gallery", + caption: { + name: true, + size: true + } + }, + file: { + caption: { + size: true + } + } + }; + + const attributes = { + default: { + tagName: "div", + parse: false + }, + quote: { + tagName: "blockquote", + nestable: true + }, + heading1: { + tagName: "h1", + terminal: true, + breakOnReturn: true, + group: false + }, + code: { + tagName: "pre", + terminal: true, + htmlAttributes: ["language"], + text: { + plaintext: true + } + }, + bulletList: { + tagName: "ul", + parse: false + }, + bullet: { + tagName: "li", + listAttribute: "bulletList", + group: false, + nestable: true, + test(element) { + return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName; + } + }, + numberList: { + tagName: "ol", + parse: false + }, + number: { + tagName: "li", + listAttribute: "numberList", + group: false, + nestable: true, + test(element) { + return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName; + } + }, + attachmentGallery: { + tagName: "div", + exclusive: true, + terminal: true, + parse: false, + group: false + } + }; + const tagName$1 = element => { + var _element$tagName; + return element === null || element === void 0 || (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase(); + }; + + const androidVersionMatch = navigator.userAgent.match(/android\s([0-9]+.*Chrome)/i); + const androidVersion = androidVersionMatch && parseInt(androidVersionMatch[1]); + var browser$1 = { + // Android emits composition events when moving the cursor through existing text + // Introduced in Chrome 65: https://bugs.chromium.org/p/chromium/issues/detail?id=764439#c9 + composesExistingText: /Android.*Chrome/.test(navigator.userAgent), + // Android 13, especially on Samsung keyboards, emits extra compositionend and beforeinput events + // that can make the input handler lose the current selection or enter an infinite input -> render -> input + // loop. + recentAndroid: androidVersion && androidVersion > 12, + samsungAndroid: androidVersion && navigator.userAgent.match(/Android.*SM-/), + // IE 11 activates resizing handles on editable elements that have "layout" + forcesObjectResizing: /Trident.*rv:11/.test(navigator.userAgent), + // https://www.w3.org/TR/input-events-1/ + https://www.w3.org/TR/input-events-2/ + supportsInputEvents: typeof InputEvent !== "undefined" && ["data", "getTargetRanges", "inputType"].every(prop => prop in InputEvent.prototype) + }; + + var css$3 = { + attachment: "attachment", + attachmentCaption: "attachment__caption", + attachmentCaptionEditor: "attachment__caption-editor", + attachmentMetadata: "attachment__metadata", + attachmentMetadataContainer: "attachment__metadata-container", + attachmentName: "attachment__name", + attachmentProgress: "attachment__progress", + attachmentSize: "attachment__size", + attachmentToolbar: "attachment__toolbar", + attachmentGallery: "attachment-gallery" + }; + + var lang$1 = { + attachFiles: "Attach Files", + bold: "Bold", + bullets: "Bullets", + byte: "Byte", + bytes: "Bytes", + captionPlaceholder: "Add a caption…", + code: "Code", + heading1: "Heading", + indent: "Increase Level", + italic: "Italic", + link: "Link", + numbers: "Numbers", + outdent: "Decrease Level", + quote: "Quote", + redo: "Redo", + remove: "Remove", + strike: "Strikethrough", + undo: "Undo", + unlink: "Unlink", + url: "URL", + urlPlaceholder: "Enter a URL…", + GB: "GB", + KB: "KB", + MB: "MB", + PB: "PB", + TB: "TB" + }; + + /* eslint-disable + no-case-declarations, + */ + const sizes = [lang$1.bytes, lang$1.KB, lang$1.MB, lang$1.GB, lang$1.TB, lang$1.PB]; + var file_size_formatting = { + prefix: "IEC", + precision: 2, + formatter(number) { + switch (number) { + case 0: + return "0 ".concat(lang$1.bytes); + case 1: + return "1 ".concat(lang$1.byte); + default: + let base; + if (this.prefix === "SI") { + base = 1000; + } else if (this.prefix === "IEC") { + base = 1024; + } + const exp = Math.floor(Math.log(number) / Math.log(base)); + const humanSize = number / Math.pow(base, exp); + const string = humanSize.toFixed(this.precision); + const withoutInsignificantZeros = string.replace(/0*$/, "").replace(/\.$/, ""); + return "".concat(withoutInsignificantZeros, " ").concat(sizes[exp]); + } + } + }; + + const ZERO_WIDTH_SPACE = "\uFEFF"; + const NON_BREAKING_SPACE = "\u00A0"; + const OBJECT_REPLACEMENT_CHARACTER = "\uFFFC"; + + const extend = function (properties) { + for (const key in properties) { + const value = properties[key]; + this[key] = value; + } + return this; + }; + + const html$2 = document.documentElement; + const match = html$2.matches; + const handleEvent = function (eventName) { + let { + onElement, + matchingSelector, + withCallback, + inPhase, + preventDefault, + times + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const element = onElement ? onElement : html$2; + const selector = matchingSelector; + const useCapture = inPhase === "capturing"; + const handler = function (event) { + if (times != null && --times === 0) { + handler.destroy(); + } + const target = findClosestElementFromNode(event.target, { + matchingSelector: selector + }); + if (target != null) { + withCallback === null || withCallback === void 0 || withCallback.call(target, event, target); + if (preventDefault) { + event.preventDefault(); + } + } + }; + handler.destroy = () => element.removeEventListener(eventName, handler, useCapture); + element.addEventListener(eventName, handler, useCapture); + return handler; + }; + const handleEventOnce = function (eventName) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + options.times = 1; + return handleEvent(eventName, options); + }; + const triggerEvent = function (eventName) { + let { + onElement, + bubbles, + cancelable, + attributes + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const element = onElement != null ? onElement : html$2; + bubbles = bubbles !== false; + cancelable = cancelable !== false; + const event = document.createEvent("Events"); + event.initEvent(eventName, bubbles, cancelable); + if (attributes != null) { + extend.call(event, attributes); + } + return element.dispatchEvent(event); + }; + const elementMatchesSelector = function (element, selector) { + if ((element === null || element === void 0 ? void 0 : element.nodeType) === 1) { + return match.call(element, selector); + } + }; + const findClosestElementFromNode = function (node) { + let { + matchingSelector, + untilNode + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + while (node && node.nodeType !== Node.ELEMENT_NODE) { + node = node.parentNode; + } + if (node == null) { + return; + } + if (matchingSelector != null) { + if (node.closest && untilNode == null) { + return node.closest(matchingSelector); + } else { + while (node && node !== untilNode) { + if (elementMatchesSelector(node, matchingSelector)) { + return node; + } + node = node.parentNode; + } + } + } else { + return node; + } + }; + const findInnerElement = function (element) { + while ((_element = element) !== null && _element !== void 0 && _element.firstElementChild) { + var _element; + element = element.firstElementChild; + } + return element; + }; + const innerElementIsActive = element => document.activeElement !== element && elementContainsNode(element, document.activeElement); + const elementContainsNode = function (element, node) { + if (!element || !node) { + return; + } + while (node) { + if (node === element) { + return true; + } + node = node.parentNode; + } + }; + const findNodeFromContainerAndOffset = function (container, offset) { + if (!container) { + return; + } + if (container.nodeType === Node.TEXT_NODE) { + return container; + } else if (offset === 0) { + return container.firstChild != null ? container.firstChild : container; + } else { + return container.childNodes.item(offset - 1); + } + }; + const findElementFromContainerAndOffset = function (container, offset) { + const node = findNodeFromContainerAndOffset(container, offset); + return findClosestElementFromNode(node); + }; + const findChildIndexOfNode = function (node) { + var _node; + if (!((_node = node) !== null && _node !== void 0 && _node.parentNode)) { + return; + } + let childIndex = 0; + node = node.previousSibling; + while (node) { + childIndex++; + node = node.previousSibling; + } + return childIndex; + }; + const removeNode = node => { + var _node$parentNode; + return node === null || node === void 0 || (_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 ? void 0 : _node$parentNode.removeChild(node); + }; + const walkTree = function (tree) { + let { + onlyNodesOfType, + usingFilter, + expandEntityReferences + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const whatToShow = (() => { + switch (onlyNodesOfType) { + case "element": + return NodeFilter.SHOW_ELEMENT; + case "text": + return NodeFilter.SHOW_TEXT; + case "comment": + return NodeFilter.SHOW_COMMENT; + default: + return NodeFilter.SHOW_ALL; + } + })(); + return document.createTreeWalker(tree, whatToShow, usingFilter != null ? usingFilter : null, expandEntityReferences === true); + }; + const tagName = element => { + var _element$tagName; + return element === null || element === void 0 || (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase(); + }; + const makeElement = function (tag) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let key, value; + if (typeof tag === "object") { + options = tag; + tag = options.tagName; + } else { + options = { + attributes: options + }; + } + const element = document.createElement(tag); + if (options.editable != null) { + if (options.attributes == null) { + options.attributes = {}; + } + options.attributes.contenteditable = options.editable; + } + if (options.attributes) { + for (key in options.attributes) { + value = options.attributes[key]; + element.setAttribute(key, value); + } + } + if (options.style) { + for (key in options.style) { + value = options.style[key]; + element.style[key] = value; + } + } + if (options.data) { + for (key in options.data) { + value = options.data[key]; + element.dataset[key] = value; + } + } + if (options.className) { + options.className.split(" ").forEach(className => { + element.classList.add(className); + }); + } + if (options.textContent) { + element.textContent = options.textContent; + } + if (options.childNodes) { + [].concat(options.childNodes).forEach(childNode => { + element.appendChild(childNode); + }); + } + return element; + }; + let blockTagNames = undefined; + const getBlockTagNames = function () { + if (blockTagNames != null) { + return blockTagNames; + } + blockTagNames = []; + for (const key in attributes) { + const attributes$1 = attributes[key]; + if (attributes$1.tagName) { + blockTagNames.push(attributes$1.tagName); + } + } + return blockTagNames; + }; + const nodeIsBlockContainer = node => nodeIsBlockStartComment(node === null || node === void 0 ? void 0 : node.firstChild); + const nodeProbablyIsBlockContainer = function (node) { + return getBlockTagNames().includes(tagName(node)) && !getBlockTagNames().includes(tagName(node.firstChild)); + }; + const nodeIsBlockStart = function (node) { + let { + strict + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + strict: true + }; + if (strict) { + return nodeIsBlockStartComment(node); + } else { + return nodeIsBlockStartComment(node) || !nodeIsBlockStartComment(node.firstChild) && nodeProbablyIsBlockContainer(node); + } + }; + const nodeIsBlockStartComment = node => nodeIsCommentNode(node) && (node === null || node === void 0 ? void 0 : node.data) === "block"; + const nodeIsCommentNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.COMMENT_NODE; + const nodeIsCursorTarget = function (node) { + let { + name + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + if (!node) { + return; + } + if (nodeIsTextNode(node)) { + if (node.data === ZERO_WIDTH_SPACE) { + if (name) { + return node.parentNode.dataset.trixCursorTarget === name; + } else { + return true; + } + } + } else { + return nodeIsCursorTarget(node.firstChild); + } + }; + const nodeIsAttachmentElement = node => elementMatchesSelector(node, attachmentSelector); + const nodeIsEmptyTextNode = node => nodeIsTextNode(node) && (node === null || node === void 0 ? void 0 : node.data) === ""; + const nodeIsTextNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.TEXT_NODE; + + const input = { + level2Enabled: true, + getLevel() { + if (this.level2Enabled && browser$1.supportsInputEvents) { + return 2; + } else { + return 0; + } + }, + pickFiles(callback) { + const input = makeElement("input", { + type: "file", + multiple: true, + hidden: true, + id: this.fileInputId + }); + input.addEventListener("change", () => { + callback(input.files); + removeNode(input); + }); + removeNode(document.getElementById(this.fileInputId)); + document.body.appendChild(input); + input.click(); + } + }; + + var key_names = { + 8: "backspace", + 9: "tab", + 13: "return", + 27: "escape", + 37: "left", + 39: "right", + 46: "delete", + 68: "d", + 72: "h", + 79: "o" + }; + + var parser = { + removeBlankTableCells: false, + tableCellSeparator: " | ", + tableRowSeparator: "\n" + }; + + var text_attributes = { + bold: { + tagName: "strong", + inheritable: true, + parser(element) { + const style = window.getComputedStyle(element); + return style.fontWeight === "bold" || style.fontWeight >= 600; + } + }, + italic: { + tagName: "em", + inheritable: true, + parser(element) { + const style = window.getComputedStyle(element); + return style.fontStyle === "italic"; + } + }, + href: { + groupTagName: "a", + parser(element) { + const matchingSelector = "a:not(".concat(attachmentSelector, ")"); + const link = element.closest(matchingSelector); + if (link) { + return link.getAttribute("href"); + } + } + }, + strike: { + tagName: "del", + inheritable: true + }, + frozen: { + style: { + backgroundColor: "highlight" + } + } + }; + + var toolbar = { + getDefaultHTML() { + return "
\n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n\n \n \n \n\n \n\n \n \n \n \n
\n\n
\n
\n \n
\n
"); + } + }; + + const undo = { + interval: 5000 + }; + + var config = /*#__PURE__*/Object.freeze({ + __proto__: null, + attachments: attachments, + blockAttributes: attributes, + browser: browser$1, + css: css$3, + fileSize: file_size_formatting, + input: input, + keyNames: key_names, + lang: lang$1, + parser: parser, + textAttributes: text_attributes, + toolbar: toolbar, + undo: undo + }); + + class BasicObject { + static proxyMethod(expression) { + const { + name, + toMethod, + toProperty, + optional + } = parseProxyMethodExpression(expression); + this.prototype[name] = function () { + let subject; + let object; + if (toMethod) { + if (optional) { + var _this$toMethod; + object = (_this$toMethod = this[toMethod]) === null || _this$toMethod === void 0 ? void 0 : _this$toMethod.call(this); + } else { + object = this[toMethod](); + } + } else if (toProperty) { + object = this[toProperty]; + } + if (optional) { + var _object; + subject = (_object = object) === null || _object === void 0 ? void 0 : _object[name]; + if (subject) { + return apply$1.call(subject, object, arguments); + } + } else { + subject = object[name]; + return apply$1.call(subject, object, arguments); + } + }; + } + } + const parseProxyMethodExpression = function (expression) { + const match = expression.match(proxyMethodExpressionPattern); + if (!match) { + throw new Error("can't parse @proxyMethod expression: ".concat(expression)); + } + const args = { + name: match[4] + }; + if (match[2] != null) { + args.toMethod = match[1]; + } else { + args.toProperty = match[1]; + } + if (match[3] != null) { + args.optional = true; + } + return args; + }; + const { + apply: apply$1 + } = Function.prototype; + const proxyMethodExpressionPattern = new RegExp("\ +^\ +(.+?)\ +(\\(\\))?\ +(\\?)?\ +\\.\ +(.+?)\ +$\ +"); + + var _Array$from, _$codePointAt$1, _$1, _String$fromCodePoint; + class UTF16String extends BasicObject { + static box() { + let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + if (value instanceof this) { + return value; + } else { + return this.fromUCS2String(value === null || value === void 0 ? void 0 : value.toString()); + } + } + static fromUCS2String(ucs2String) { + return new this(ucs2String, ucs2decode(ucs2String)); + } + static fromCodepoints(codepoints) { + return new this(ucs2encode(codepoints), codepoints); + } + constructor(ucs2String, codepoints) { + super(...arguments); + this.ucs2String = ucs2String; + this.codepoints = codepoints; + this.length = this.codepoints.length; + this.ucs2Length = this.ucs2String.length; + } + offsetToUCS2Offset(offset) { + return ucs2encode(this.codepoints.slice(0, Math.max(0, offset))).length; + } + offsetFromUCS2Offset(ucs2Offset) { + return ucs2decode(this.ucs2String.slice(0, Math.max(0, ucs2Offset))).length; + } + slice() { + return this.constructor.fromCodepoints(this.codepoints.slice(...arguments)); + } + charAt(offset) { + return this.slice(offset, offset + 1); + } + isEqualTo(value) { + return this.constructor.box(value).ucs2String === this.ucs2String; + } + toJSON() { + return this.ucs2String; + } + getCacheKey() { + return this.ucs2String; + } + toString() { + return this.ucs2String; + } + } + const hasArrayFrom = ((_Array$from = Array.from) === null || _Array$from === void 0 ? void 0 : _Array$from.call(Array, "\ud83d\udc7c").length) === 1; + const hasStringCodePointAt$1 = ((_$codePointAt$1 = (_$1 = " ").codePointAt) === null || _$codePointAt$1 === void 0 ? void 0 : _$codePointAt$1.call(_$1, 0)) != null; + const hasStringFromCodePoint = ((_String$fromCodePoint = String.fromCodePoint) === null || _String$fromCodePoint === void 0 ? void 0 : _String$fromCodePoint.call(String, 32, 128124)) === " \ud83d\udc7c"; + + // UCS-2 conversion helpers ported from Mathias Bynens' Punycode.js: + // https://github.com/bestiejs/punycode.js#punycodeucs2 + + let ucs2decode, ucs2encode; + + // Creates an array containing the numeric code points of each Unicode + // character in the string. While JavaScript uses UCS-2 internally, + // this function will convert a pair of surrogate halves (each of which + // UCS-2 exposes as separate characters) into a single code point, + // matching UTF-16. + if (hasArrayFrom && hasStringCodePointAt$1) { + ucs2decode = string => Array.from(string).map(char => char.codePointAt(0)); + } else { + ucs2decode = function (string) { + const output = []; + let counter = 0; + const { + length + } = string; + while (counter < length) { + let value = string.charCodeAt(counter++); + if (0xd800 <= value && value <= 0xdbff && counter < length) { + // high surrogate, and there is a next character + const extra = string.charCodeAt(counter++); + if ((extra & 0xfc00) === 0xdc00) { + // low surrogate + value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; + } else { + // unmatched surrogate; only append this code unit, in case the + // next code unit is the high surrogate of a surrogate pair + counter--; + } + } + output.push(value); + } + return output; + }; + } + + // Creates a string based on an array of numeric code points. + if (hasStringFromCodePoint) { + ucs2encode = array => String.fromCodePoint(...Array.from(array || [])); + } else { + ucs2encode = function (array) { + const characters = (() => { + const result = []; + Array.from(array).forEach(value => { + let output = ""; + if (value > 0xffff) { + value -= 0x10000; + output += String.fromCharCode(value >>> 10 & 0x3ff | 0xd800); + value = 0xdc00 | value & 0x3ff; + } + result.push(output + String.fromCharCode(value)); + }); + return result; + })(); + return characters.join(""); + }; + } + + let id$2 = 0; + class TrixObject extends BasicObject { + static fromJSONString(jsonString) { + return this.fromJSON(JSON.parse(jsonString)); + } + constructor() { + super(...arguments); + this.id = ++id$2; + } + hasSameConstructorAs(object) { + return this.constructor === (object === null || object === void 0 ? void 0 : object.constructor); + } + isEqualTo(object) { + return this === object; + } + inspect() { + const parts = []; + const contents = this.contentsForInspection() || {}; + for (const key in contents) { + const value = contents[key]; + parts.push("".concat(key, "=").concat(value)); + } + return "#<".concat(this.constructor.name, ":").concat(this.id).concat(parts.length ? " ".concat(parts.join(", ")) : "", ">"); + } + contentsForInspection() {} + toJSONString() { + return JSON.stringify(this); + } + toUTF16String() { + return UTF16String.box(this); + } + getCacheKey() { + return this.id.toString(); + } + } + + /* eslint-disable + id-length, + */ + const arraysAreEqual = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + if (a.length !== b.length) { + return false; + } + for (let index = 0; index < a.length; index++) { + const value = a[index]; + if (value !== b[index]) { + return false; + } + } + return true; + }; + const arrayStartsWith = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + return arraysAreEqual(a.slice(0, b.length), b); + }; + const spliceArray = function (array) { + const result = array.slice(0); + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + result.splice(...args); + return result; + }; + const summarizeArrayChange = function () { + let oldArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let newArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + const added = []; + const removed = []; + const existingValues = new Set(); + oldArray.forEach(value => { + existingValues.add(value); + }); + const currentValues = new Set(); + newArray.forEach(value => { + currentValues.add(value); + if (!existingValues.has(value)) { + added.push(value); + } + }); + oldArray.forEach(value => { + if (!currentValues.has(value)) { + removed.push(value); + } + }); + return { + added, + removed + }; + }; + + // https://github.com/mathiasbynens/unicode-2.1.8/blob/master/Bidi_Class/Right_To_Left/regex.js + const RTL_PATTERN = /[\u05BE\u05C0\u05C3\u05D0-\u05EA\u05F0-\u05F4\u061B\u061F\u0621-\u063A\u0640-\u064A\u066D\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D5\u06E5\u06E6\u200F\u202B\u202E\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE72\uFE74\uFE76-\uFEFC]/; + const getDirection = function () { + const input = makeElement("input", { + dir: "auto", + name: "x", + dirName: "x.dir" + }); + const textArea = makeElement("textarea", { + dir: "auto", + name: "y", + dirName: "y.dir" + }); + const form = makeElement("form"); + form.appendChild(input); + form.appendChild(textArea); + const supportsDirName = function () { + try { + return new FormData(form).has(textArea.dirName); + } catch (error) { + return false; + } + }(); + const supportsDirSelector = function () { + try { + return input.matches(":dir(ltr),:dir(rtl)"); + } catch (error) { + return false; + } + }(); + if (supportsDirName) { + return function (string) { + textArea.value = string; + return new FormData(form).get(textArea.dirName); + }; + } else if (supportsDirSelector) { + return function (string) { + input.value = string; + if (input.matches(":dir(rtl)")) { + return "rtl"; + } else { + return "ltr"; + } + }; + } else { + return function (string) { + const char = string.trim().charAt(0); + if (RTL_PATTERN.test(char)) { + return "rtl"; + } else { + return "ltr"; + } + }; + } + }(); + + let allAttributeNames = null; + let blockAttributeNames = null; + let textAttributeNames = null; + let listAttributeNames = null; + const getAllAttributeNames = () => { + if (!allAttributeNames) { + allAttributeNames = getTextAttributeNames().concat(getBlockAttributeNames()); + } + return allAttributeNames; + }; + const getBlockConfig = attributeName => attributes[attributeName]; + const getBlockAttributeNames = () => { + if (!blockAttributeNames) { + blockAttributeNames = Object.keys(attributes); + } + return blockAttributeNames; + }; + const getTextConfig = attributeName => text_attributes[attributeName]; + const getTextAttributeNames = () => { + if (!textAttributeNames) { + textAttributeNames = Object.keys(text_attributes); + } + return textAttributeNames; + }; + const getListAttributeNames = () => { + if (!listAttributeNames) { + listAttributeNames = []; + for (const key in attributes) { + const { + listAttribute + } = attributes[key]; + if (listAttribute != null) { + listAttributeNames.push(listAttribute); + } + } + } + return listAttributeNames; + }; + + /* eslint-disable + */ + const installDefaultCSSForTagName = function (tagName, defaultCSS) { + const styleElement = insertStyleElementForTagName(tagName); + styleElement.textContent = defaultCSS.replace(/%t/g, tagName); + }; + const insertStyleElementForTagName = function (tagName) { + const element = document.createElement("style"); + element.setAttribute("type", "text/css"); + element.setAttribute("data-tag-name", tagName.toLowerCase()); + const nonce = getCSPNonce(); + if (nonce) { + element.setAttribute("nonce", nonce); + } + document.head.insertBefore(element, document.head.firstChild); + return element; + }; + const getCSPNonce = function () { + const element = getMetaElement("trix-csp-nonce") || getMetaElement("csp-nonce"); + if (element) { + const { + nonce, + content + } = element; + return nonce == "" ? content : nonce; + } + }; + const getMetaElement = name => document.head.querySelector("meta[name=".concat(name, "]")); + + const testTransferData = { + "application/x-trix-feature-detection": "test" + }; + const dataTransferIsPlainText = function (dataTransfer) { + const text = dataTransfer.getData("text/plain"); + const html = dataTransfer.getData("text/html"); + if (text && html) { + const { + body + } = new DOMParser().parseFromString(html, "text/html"); + if (body.textContent === text) { + return !body.querySelector("*"); + } + } else { + return text === null || text === void 0 ? void 0 : text.length; + } + }; + const dataTransferIsMsOfficePaste = _ref => { + let { + dataTransfer + } = _ref; + return dataTransfer.types.includes("Files") && dataTransfer.types.includes("text/html") && dataTransfer.getData("text/html").includes("urn:schemas-microsoft-com:office:office"); + }; + const dataTransferIsWritable = function (dataTransfer) { + if (!(dataTransfer !== null && dataTransfer !== void 0 && dataTransfer.setData)) return false; + for (const key in testTransferData) { + const value = testTransferData[key]; + try { + dataTransfer.setData(key, value); + if (!dataTransfer.getData(key) === value) return false; + } catch (error) { + return false; + } + } + return true; + }; + const keyEventIsKeyboardCommand = function () { + if (/Mac|^iP/.test(navigator.platform)) { + return event => event.metaKey; + } else { + return event => event.ctrlKey; + } + }(); + function shouldRenderInmmediatelyToDealWithIOSDictation(inputEvent) { + if (/iPhone|iPad/.test(navigator.userAgent)) { + // Handle garbled content and duplicated newlines when using dictation on iOS 18+. Upon dictation completion, iOS sends + // the list of insertText / insertParagraph events in a quick sequence. If we don't render + // the editor synchronously, the internal range fails to update and results in garbled content or duplicated newlines. + // + // This workaround is necessary because iOS doesn't send composing events as expected while dictating: + // https://bugs.webkit.org/show_bug.cgi?id=261764 + return !inputEvent.inputType || inputEvent.inputType === "insertParagraph"; + } else { + return false; + } + } + + const defer = fn => setTimeout(fn, 1); + + /* eslint-disable + id-length, + */ + const copyObject = function () { + let object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + const result = {}; + for (const key in object) { + const value = object[key]; + result[key] = value; + } + return result; + }; + const objectsAreEqual = function () { + let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + if (Object.keys(a).length !== Object.keys(b).length) { + return false; + } + for (const key in a) { + const value = a[key]; + if (value !== b[key]) { + return false; + } + } + return true; + }; + + const normalizeRange = function (range) { + if (range == null) return; + if (!Array.isArray(range)) { + range = [range, range]; + } + return [copyValue(range[0]), copyValue(range[1] != null ? range[1] : range[0])]; + }; + const rangeIsCollapsed = function (range) { + if (range == null) return; + const [start, end] = normalizeRange(range); + return rangeValuesAreEqual(start, end); + }; + const rangesAreEqual = function (leftRange, rightRange) { + if (leftRange == null || rightRange == null) return; + const [leftStart, leftEnd] = normalizeRange(leftRange); + const [rightStart, rightEnd] = normalizeRange(rightRange); + return rangeValuesAreEqual(leftStart, rightStart) && rangeValuesAreEqual(leftEnd, rightEnd); + }; + const copyValue = function (value) { + if (typeof value === "number") { + return value; + } else { + return copyObject(value); + } + }; + const rangeValuesAreEqual = function (left, right) { + if (typeof left === "number") { + return left === right; + } else { + return objectsAreEqual(left, right); + } + }; + + class SelectionChangeObserver extends BasicObject { + constructor() { + super(...arguments); + this.update = this.update.bind(this); + this.selectionManagers = []; + } + start() { + if (!this.started) { + this.started = true; + document.addEventListener("selectionchange", this.update, true); + } + } + stop() { + if (this.started) { + this.started = false; + return document.removeEventListener("selectionchange", this.update, true); + } + } + registerSelectionManager(selectionManager) { + if (!this.selectionManagers.includes(selectionManager)) { + this.selectionManagers.push(selectionManager); + return this.start(); + } + } + unregisterSelectionManager(selectionManager) { + this.selectionManagers = this.selectionManagers.filter(sm => sm !== selectionManager); + if (this.selectionManagers.length === 0) { + return this.stop(); + } + } + notifySelectionManagersOfSelectionChange() { + return this.selectionManagers.map(selectionManager => selectionManager.selectionDidChange()); + } + update() { + this.notifySelectionManagersOfSelectionChange(); + } + reset() { + this.update(); + } + } + const selectionChangeObserver = new SelectionChangeObserver(); + const getDOMSelection = function () { + const selection = window.getSelection(); + if (selection.rangeCount > 0) { + return selection; + } + }; + const getDOMRange = function () { + var _getDOMSelection; + const domRange = (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.getRangeAt(0); + if (domRange) { + if (!domRangeIsPrivate(domRange)) { + return domRange; + } + } + }; + const setDOMRange = function (domRange) { + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(domRange); + return selectionChangeObserver.update(); + }; + + // In Firefox, clicking certain elements changes the selection to a + // private element used to draw its UI. Attempting to access properties of those + // elements throws an error. + // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 + const domRangeIsPrivate = domRange => nodeIsPrivate(domRange.startContainer) || nodeIsPrivate(domRange.endContainer); + const nodeIsPrivate = node => !Object.getPrototypeOf(node); + + /* eslint-disable + id-length, + no-useless-escape, + */ + const normalizeSpaces = string => string.replace(new RegExp("".concat(ZERO_WIDTH_SPACE), "g"), "").replace(new RegExp("".concat(NON_BREAKING_SPACE), "g"), " "); + const normalizeNewlines = string => string.replace(/\r\n?/g, "\n"); + const breakableWhitespacePattern = new RegExp("[^\\S".concat(NON_BREAKING_SPACE, "]")); + const squishBreakableWhitespace = string => string + // Replace all breakable whitespace characters with a space + .replace(new RegExp("".concat(breakableWhitespacePattern.source), "g"), " ") + // Replace two or more spaces with a single space + .replace(/\ {2,}/g, " "); + const summarizeStringChange = function (oldString, newString) { + let added, removed; + oldString = UTF16String.box(oldString); + newString = UTF16String.box(newString); + if (newString.length < oldString.length) { + [removed, added] = utf16StringDifferences(oldString, newString); + } else { + [added, removed] = utf16StringDifferences(newString, oldString); + } + return { + added, + removed + }; + }; + const utf16StringDifferences = function (a, b) { + if (a.isEqualTo(b)) { + return ["", ""]; + } + const diffA = utf16StringDifference(a, b); + const { + length + } = diffA.utf16String; + let diffB; + if (length) { + const { + offset + } = diffA; + const codepoints = a.codepoints.slice(0, offset).concat(a.codepoints.slice(offset + length)); + diffB = utf16StringDifference(b, UTF16String.fromCodepoints(codepoints)); + } else { + diffB = utf16StringDifference(b, a); + } + return [diffA.utf16String.toString(), diffB.utf16String.toString()]; + }; + const utf16StringDifference = function (a, b) { + let leftIndex = 0; + let rightIndexA = a.length; + let rightIndexB = b.length; + while (leftIndex < rightIndexA && a.charAt(leftIndex).isEqualTo(b.charAt(leftIndex))) { + leftIndex++; + } + while (rightIndexA > leftIndex + 1 && a.charAt(rightIndexA - 1).isEqualTo(b.charAt(rightIndexB - 1))) { + rightIndexA--; + rightIndexB--; + } + return { + utf16String: a.slice(leftIndex, rightIndexA), + offset: leftIndex + }; + }; + + class Hash extends TrixObject { + static fromCommonAttributesOfObjects() { + let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + if (!objects.length) { + return new this(); + } + let hash = box(objects[0]); + let keys = hash.getKeys(); + objects.slice(1).forEach(object => { + keys = hash.getKeysCommonToHash(box(object)); + hash = hash.slice(keys); + }); + return hash; + } + static box(values) { + return box(values); + } + constructor() { + let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + super(...arguments); + this.values = copy(values); + } + add(key, value) { + return this.merge(object(key, value)); + } + remove(key) { + return new Hash(copy(this.values, key)); + } + get(key) { + return this.values[key]; + } + has(key) { + return key in this.values; + } + merge(values) { + return new Hash(merge(this.values, unbox(values))); + } + slice(keys) { + const values = {}; + Array.from(keys).forEach(key => { + if (this.has(key)) { + values[key] = this.values[key]; + } + }); + return new Hash(values); + } + getKeys() { + return Object.keys(this.values); + } + getKeysCommonToHash(hash) { + hash = box(hash); + return this.getKeys().filter(key => this.values[key] === hash.values[key]); + } + isEqualTo(values) { + return arraysAreEqual(this.toArray(), box(values).toArray()); + } + isEmpty() { + return this.getKeys().length === 0; + } + toArray() { + if (!this.array) { + const result = []; + for (const key in this.values) { + const value = this.values[key]; + result.push(result.push(key, value)); + } + this.array = result.slice(0); + } + return this.array; + } + toObject() { + return copy(this.values); + } + toJSON() { + return this.toObject(); + } + contentsForInspection() { + return { + values: JSON.stringify(this.values) + }; + } + } + const object = function (key, value) { + const result = {}; + result[key] = value; + return result; + }; + const merge = function (object, values) { + const result = copy(object); + for (const key in values) { + const value = values[key]; + result[key] = value; + } + return result; + }; + const copy = function (object, keyToRemove) { + const result = {}; + const sortedKeys = Object.keys(object).sort(); + sortedKeys.forEach(key => { + if (key !== keyToRemove) { + result[key] = object[key]; + } + }); + return result; + }; + const box = function (object) { + if (object instanceof Hash) { + return object; + } else { + return new Hash(object); + } + }; + const unbox = function (object) { + if (object instanceof Hash) { + return object.values; + } else { + return object; + } + }; + + class ObjectGroup { + static groupObjects() { + let ungroupedObjects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let { + depth, + asTree + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let group; + if (asTree) { + if (depth == null) { + depth = 0; + } + } + const objects = []; + Array.from(ungroupedObjects).forEach(object => { + var _object$canBeGrouped2; + if (group) { + var _object$canBeGrouped, _group$canBeGroupedWi, _group; + if ((_object$canBeGrouped = object.canBeGrouped) !== null && _object$canBeGrouped !== void 0 && _object$canBeGrouped.call(object, depth) && (_group$canBeGroupedWi = (_group = group[group.length - 1]).canBeGroupedWith) !== null && _group$canBeGroupedWi !== void 0 && _group$canBeGroupedWi.call(_group, object, depth)) { + group.push(object); + return; + } else { + objects.push(new this(group, { + depth, + asTree + })); + group = null; + } + } + if ((_object$canBeGrouped2 = object.canBeGrouped) !== null && _object$canBeGrouped2 !== void 0 && _object$canBeGrouped2.call(object, depth)) { + group = [object]; + } else { + objects.push(object); + } + }); + if (group) { + objects.push(new this(group, { + depth, + asTree + })); + } + return objects; + } + constructor() { + let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + let { + depth, + asTree + } = arguments.length > 1 ? arguments[1] : undefined; + this.objects = objects; + if (asTree) { + this.depth = depth; + this.objects = this.constructor.groupObjects(this.objects, { + asTree, + depth: this.depth + 1 + }); + } + } + getObjects() { + return this.objects; + } + getDepth() { + return this.depth; + } + getCacheKey() { + const keys = ["objectGroup"]; + Array.from(this.getObjects()).forEach(object => { + keys.push(object.getCacheKey()); + }); + return keys.join("/"); + } + } + + class ObjectMap extends BasicObject { + constructor() { + let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + this.objects = {}; + Array.from(objects).forEach(object => { + const hash = JSON.stringify(object); + if (this.objects[hash] == null) { + this.objects[hash] = object; + } + }); + } + find(object) { + const hash = JSON.stringify(object); + return this.objects[hash]; + } + } + + class ElementStore { + constructor(elements) { + this.reset(elements); + } + add(element) { + const key = getKey(element); + this.elements[key] = element; + } + remove(element) { + const key = getKey(element); + const value = this.elements[key]; + if (value) { + delete this.elements[key]; + return value; + } + } + reset() { + let elements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + this.elements = {}; + Array.from(elements).forEach(element => { + this.add(element); + }); + return elements; + } + } + const getKey = element => element.dataset.trixStoreKey; + + class Operation extends BasicObject { + isPerforming() { + return this.performing === true; + } + hasPerformed() { + return this.performed === true; + } + hasSucceeded() { + return this.performed && this.succeeded; + } + hasFailed() { + return this.performed && !this.succeeded; + } + getPromise() { + if (!this.promise) { + this.promise = new Promise((resolve, reject) => { + this.performing = true; + return this.perform((succeeded, result) => { + this.succeeded = succeeded; + this.performing = false; + this.performed = true; + if (this.succeeded) { + resolve(result); + } else { + reject(result); + } + }); + }); + } + return this.promise; + } + perform(callback) { + return callback(false); + } + release() { + var _this$promise, _this$promise$cancel; + (_this$promise = this.promise) === null || _this$promise === void 0 || (_this$promise$cancel = _this$promise.cancel) === null || _this$promise$cancel === void 0 || _this$promise$cancel.call(_this$promise); + this.promise = null; + this.performing = null; + this.performed = null; + this.succeeded = null; + } + } + Operation.proxyMethod("getPromise().then"); + Operation.proxyMethod("getPromise().catch"); + + class ObjectView extends BasicObject { + constructor(object) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + super(...arguments); + this.object = object; + this.options = options; + this.childViews = []; + this.rootView = this; + } + getNodes() { + if (!this.nodes) { + this.nodes = this.createNodes(); + } + return this.nodes.map(node => node.cloneNode(true)); + } + invalidate() { + var _this$parentView; + this.nodes = null; + this.childViews = []; + return (_this$parentView = this.parentView) === null || _this$parentView === void 0 ? void 0 : _this$parentView.invalidate(); + } + invalidateViewForObject(object) { + var _this$findViewForObje; + return (_this$findViewForObje = this.findViewForObject(object)) === null || _this$findViewForObje === void 0 ? void 0 : _this$findViewForObje.invalidate(); + } + findOrCreateCachedChildView(viewClass, object, options) { + let view = this.getCachedViewForObject(object); + if (view) { + this.recordChildView(view); + } else { + view = this.createChildView(...arguments); + this.cacheViewForObject(view, object); + } + return view; + } + createChildView(viewClass, object) { + let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + if (object instanceof ObjectGroup) { + options.viewClass = viewClass; + viewClass = ObjectGroupView; + } + const view = new viewClass(object, options); + return this.recordChildView(view); + } + recordChildView(view) { + view.parentView = this; + view.rootView = this.rootView; + this.childViews.push(view); + return view; + } + getAllChildViews() { + let views = []; + this.childViews.forEach(childView => { + views.push(childView); + views = views.concat(childView.getAllChildViews()); + }); + return views; + } + findElement() { + return this.findElementForObject(this.object); + } + findElementForObject(object) { + const id = object === null || object === void 0 ? void 0 : object.id; + if (id) { + return this.rootView.element.querySelector("[data-trix-id='".concat(id, "']")); + } + } + findViewForObject(object) { + for (const view of this.getAllChildViews()) { + if (view.object === object) { + return view; + } + } + } + getViewCache() { + if (this.rootView === this) { + if (this.isViewCachingEnabled()) { + if (!this.viewCache) { + this.viewCache = {}; + } + return this.viewCache; + } + } else { + return this.rootView.getViewCache(); + } + } + isViewCachingEnabled() { + return this.shouldCacheViews !== false; + } + enableViewCaching() { + this.shouldCacheViews = true; + } + disableViewCaching() { + this.shouldCacheViews = false; + } + getCachedViewForObject(object) { + var _this$getViewCache; + return (_this$getViewCache = this.getViewCache()) === null || _this$getViewCache === void 0 ? void 0 : _this$getViewCache[object.getCacheKey()]; + } + cacheViewForObject(view, object) { + const cache = this.getViewCache(); + if (cache) { + cache[object.getCacheKey()] = view; + } + } + garbageCollectCachedViews() { + const cache = this.getViewCache(); + if (cache) { + const views = this.getAllChildViews().concat(this); + const objectKeys = views.map(view => view.object.getCacheKey()); + for (const key in cache) { + if (!objectKeys.includes(key)) { + delete cache[key]; + } + } + } + } + } + class ObjectGroupView extends ObjectView { + constructor() { + super(...arguments); + this.objectGroup = this.object; + this.viewClass = this.options.viewClass; + delete this.options.viewClass; + } + getChildViews() { + if (!this.childViews.length) { + Array.from(this.objectGroup.getObjects()).forEach(object => { + this.findOrCreateCachedChildView(this.viewClass, object, this.options); + }); + } + return this.childViews; + } + createNodes() { + const element = this.createContainerElement(); + this.getChildViews().forEach(view => { + Array.from(view.getNodes()).forEach(node => { + element.appendChild(node); + }); + }); + return [element]; + } + createContainerElement() { + let depth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.objectGroup.getDepth(); + return this.getChildViews()[0].createContainerElement(depth); + } + } + + /*! @license DOMPurify 3.2.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.3/LICENSE */ + + const { + entries, + setPrototypeOf, + isFrozen, + getPrototypeOf, + getOwnPropertyDescriptor + } = Object; + let { + freeze, + seal, + create + } = Object; // eslint-disable-line import/no-mutable-exports + let { + apply, + construct + } = typeof Reflect !== 'undefined' && Reflect; + if (!freeze) { + freeze = function freeze(x) { + return x; + }; + } + if (!seal) { + seal = function seal(x) { + return x; + }; + } + if (!apply) { + apply = function apply(fun, thisValue, args) { + return fun.apply(thisValue, args); + }; + } + if (!construct) { + construct = function construct(Func, args) { + return new Func(...args); + }; + } + const arrayForEach = unapply(Array.prototype.forEach); + const arrayPop = unapply(Array.prototype.pop); + const arrayPush = unapply(Array.prototype.push); + const stringToLowerCase = unapply(String.prototype.toLowerCase); + const stringToString = unapply(String.prototype.toString); + const stringMatch = unapply(String.prototype.match); + const stringReplace = unapply(String.prototype.replace); + const stringIndexOf = unapply(String.prototype.indexOf); + const stringTrim = unapply(String.prototype.trim); + const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty); + const regExpTest = unapply(RegExp.prototype.test); + const typeErrorCreate = unconstruct(TypeError); + /** + * Creates a new function that calls the given function with a specified thisArg and arguments. + * + * @param func - The function to be wrapped and called. + * @returns A new function that calls the given function with a specified thisArg and arguments. + */ + function unapply(func) { + return function (thisArg) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + return apply(func, thisArg, args); + }; + } + /** + * Creates a new function that constructs an instance of the given constructor function with the provided arguments. + * + * @param func - The constructor function to be wrapped and called. + * @returns A new function that constructs an instance of the given constructor function with the provided arguments. + */ + function unconstruct(func) { + return function () { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + return construct(func, args); + }; + } + /** + * Add properties to a lookup table + * + * @param set - The set to which elements will be added. + * @param array - The array containing elements to be added to the set. + * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set. + * @returns The modified set with added elements. + */ + function addToSet(set, array) { + let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase; + if (setPrototypeOf) { + // Make 'in' and truthy checks like Boolean(set.constructor) + // independent of any properties defined on Object.prototype. + // Prevent prototype setters from intercepting set as a this value. + setPrototypeOf(set, null); + } + let l = array.length; + while (l--) { + let element = array[l]; + if (typeof element === 'string') { + const lcElement = transformCaseFunc(element); + if (lcElement !== element) { + // Config presets (e.g. tags.js, attrs.js) are immutable. + if (!isFrozen(array)) { + array[l] = lcElement; + } + element = lcElement; + } + } + set[element] = true; + } + return set; + } + /** + * Clean up an array to harden against CSPP + * + * @param array - The array to be cleaned. + * @returns The cleaned version of the array + */ + function cleanArray(array) { + for (let index = 0; index < array.length; index++) { + const isPropertyExist = objectHasOwnProperty(array, index); + if (!isPropertyExist) { + array[index] = null; + } + } + return array; + } + /** + * Shallow clone an object + * + * @param object - The object to be cloned. + * @returns A new object that copies the original. + */ + function clone(object) { + const newObject = create(null); + for (const [property, value] of entries(object)) { + const isPropertyExist = objectHasOwnProperty(object, property); + if (isPropertyExist) { + if (Array.isArray(value)) { + newObject[property] = cleanArray(value); + } else if (value && typeof value === 'object' && value.constructor === Object) { + newObject[property] = clone(value); + } else { + newObject[property] = value; + } + } + } + return newObject; + } + /** + * This method automatically checks if the prop is function or getter and behaves accordingly. + * + * @param object - The object to look up the getter function in its prototype chain. + * @param prop - The property name for which to find the getter function. + * @returns The getter function found in the prototype chain or a fallback function. + */ + 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; + } + const 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', 'section', 'select', 'shadow', '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']); + const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']); + const 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']); + // List of SVG elements that are disallowed by default. + // We still need to know them so that we can do namespace + // checks properly in case one wants to add them to + // allow-list. + const 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']); + const 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']); + // Similarly to SVG, we want to know all MathML elements, + // even those that we disallow by default. + const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']); + const text = freeze(['#text']); + const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', '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', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']); + const 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', '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']); + const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', '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']); + const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']); + + // eslint-disable-next-line unicorn/better-regex + const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode + const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm); + const TMPLIT_EXPR = seal(/\$\{[\w\W]*}/gm); // eslint-disable-line unicorn/better-regex + const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape + const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape + const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape + ); + + const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); + const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex + ); + + const DOCTYPE_NAME = seal(/^html$/i); + const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); + var EXPRESSIONS = /*#__PURE__*/Object.freeze({ + __proto__: null, + ARIA_ATTR: ARIA_ATTR, + ATTR_WHITESPACE: ATTR_WHITESPACE, + CUSTOM_ELEMENT: CUSTOM_ELEMENT, + DATA_ATTR: DATA_ATTR, + DOCTYPE_NAME: DOCTYPE_NAME, + ERB_EXPR: ERB_EXPR, + IS_ALLOWED_URI: IS_ALLOWED_URI, + IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA, + MUSTACHE_EXPR: MUSTACHE_EXPR, + TMPLIT_EXPR: TMPLIT_EXPR + }); + + /* eslint-disable @typescript-eslint/indent */ + // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType + const NODE_TYPE = { + element: 1, + attribute: 2, + text: 3, + cdataSection: 4, + entityReference: 5, + // Deprecated + entityNode: 6, + // Deprecated + progressingInstruction: 7, + comment: 8, + document: 9, + documentType: 10, + documentFragment: 11, + notation: 12 // Deprecated + }; + + const getGlobal = function getGlobal() { + return typeof window === 'undefined' ? null : window; + }; + /** + * Creates a no-op policy for internal use only. + * Don't export this function outside this module! + * @param trustedTypes The policy factory. + * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix). + * @return The policy created (or null, if Trusted Types + * are not supported or creating the policy failed). + */ + const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) { + if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') { + return null; + } + // Allow the callers to control the unique policy name + // by adding a data-tt-policy-suffix to the script element with the DOMPurify. + // Policy creation with duplicate names throws in Trusted Types. + 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(html) { + return html; + }, + createScriptURL(scriptUrl) { + return scriptUrl; + } + }); + } catch (_) { + // Policy creation failed (most likely another DOMPurify script has + // already run). Skip creating the policy, as this will only cause errors + // if TT are enforced. + console.warn('TrustedTypes policy ' + policyName + ' could not be created.'); + return null; + } + }; + const _createHooksMap = function _createHooksMap() { + return { + afterSanitizeAttributes: [], + afterSanitizeElements: [], + afterSanitizeShadowDOM: [], + beforeSanitizeAttributes: [], + beforeSanitizeElements: [], + beforeSanitizeShadowDOM: [], + uponSanitizeAttribute: [], + uponSanitizeElement: [], + uponSanitizeShadowNode: [] + }; + }; + function createDOMPurify() { + let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal(); + const DOMPurify = root => createDOMPurify(root); + DOMPurify.version = '3.2.3'; + DOMPurify.removed = []; + if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) { + // Not running in a browser, provide a factory function + // so that you can pass your own Window + DOMPurify.isSupported = false; + return DOMPurify; + } + let { + document + } = window; + const originalDocument = document; + const currentScript = originalDocument.currentScript; + const { + DocumentFragment, + HTMLTemplateElement, + Node, + Element, + NodeFilter, + NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap, + HTMLFormElement, + DOMParser, + trustedTypes + } = window; + 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'); + // As per issue #47, the web-components registry is inherited by a + // new document created via createHTMLDocument. As per the spec + // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries) + // a new empty registry is used when creating a template contents owner + // document, so we use that as our parent document to ensure nothing + // is inherited. + if (typeof HTMLTemplateElement === 'function') { + const template = document.createElement('template'); + if (template.content && template.content.ownerDocument) { + document = template.content.ownerDocument; + } + } + let trustedTypesPolicy; + let emptyHTML = ''; + const { + implementation, + createNodeIterator, + createDocumentFragment, + getElementsByTagName + } = document; + const { + importNode + } = originalDocument; + let hooks = _createHooksMap(); + /** + * Expose whether this browser supports running the full DOMPurify. + */ + DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined; + const { + MUSTACHE_EXPR, + ERB_EXPR, + TMPLIT_EXPR, + DATA_ATTR, + ARIA_ATTR, + IS_SCRIPT_OR_DATA, + ATTR_WHITESPACE, + CUSTOM_ELEMENT + } = EXPRESSIONS; + let { + IS_ALLOWED_URI: IS_ALLOWED_URI$1 + } = EXPRESSIONS; + /** + * We consider the elements and attributes below to be safe. Ideally + * don't add any new ones but feel free to remove unwanted ones. + */ + /* allowed element names */ + let ALLOWED_TAGS = null; + const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]); + /* Allowed attribute names */ + let ALLOWED_ATTR = null; + const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]); + /* + * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements. + * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements) + * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list) + * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`. + */ + 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 + } + })); + /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */ + let FORBID_TAGS = null; + /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */ + let FORBID_ATTR = null; + /* Decide if ARIA attributes are okay */ + let ALLOW_ARIA_ATTR = true; + /* Decide if custom data attributes are okay */ + let ALLOW_DATA_ATTR = true; + /* Decide if unknown protocols are okay */ + let ALLOW_UNKNOWN_PROTOCOLS = false; + /* Decide if self-closing tags in attributes are allowed. + * Usually removed due to a mXSS issue in jQuery 3.0 */ + let ALLOW_SELF_CLOSE_IN_ATTR = true; + /* Output should be safe for common template engines. + * This means, DOMPurify removes data attributes, mustaches and ERB + */ + let SAFE_FOR_TEMPLATES = false; + /* Output should be safe even for XML used within HTML and alike. + * This means, DOMPurify removes comments when containing risky content. + */ + let SAFE_FOR_XML = true; + /* Decide if document with ... should be returned */ + let WHOLE_DOCUMENT = false; + /* Track whether config is already set on this instance of DOMPurify. */ + let SET_CONFIG = false; + /* Decide if all elements (e.g. style, script) must be children of + * document.body. By default, browsers might move them to document.head */ + let FORCE_BODY = false; + /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html + * string (or a TrustedHTML object if Trusted Types are supported). + * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead + */ + let RETURN_DOM = false; + /* Decide if a DOM `DocumentFragment` should be returned, instead of a html + * string (or a TrustedHTML object if Trusted Types are supported) */ + let RETURN_DOM_FRAGMENT = false; + /* Try to return a Trusted Type object instead of a string, return a string in + * case Trusted Types are not supported */ + let RETURN_TRUSTED_TYPE = false; + /* Output should be free from DOM clobbering attacks? + * This sanitizes markups named with colliding, clobberable built-in DOM APIs. + */ + let SANITIZE_DOM = true; + /* Achieve full DOM Clobbering protection by isolating the namespace of named + * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules. + * + * HTML/DOM spec rules that enable DOM Clobbering: + * - Named Access on Window (§7.3.3) + * - DOM Tree Accessors (§3.1.5) + * - Form Element Parent-Child Relations (§4.10.3) + * - Iframe srcdoc / Nested WindowProxies (§4.8.5) + * - HTMLCollection (§4.2.10.2) + * + * Namespace isolation is implemented by prefixing `id` and `name` attributes + * with a constant string, i.e., `user-content-` + */ + let SANITIZE_NAMED_PROPS = false; + const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-'; + /* Keep element content when removing element? */ + let KEEP_CONTENT = true; + /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead + * of importing it into a new Document and returning a sanitized copy */ + let IN_PLACE = false; + /* Allow usage of profiles like html, svg and mathMl */ + let USE_PROFILES = {}; + /* Tags to ignore content of when KEEP_CONTENT is true */ + 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', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']); + /* Tags that are safe for data: URIs */ + let DATA_URI_TAGS = null; + const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']); + /* Attributes safe for values like "javascript:" */ + let URI_SAFE_ATTRIBUTES = null; + const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']); + const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML'; + const SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; + const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; + /* Document namespace */ + let NAMESPACE = HTML_NAMESPACE; + let IS_EMPTY_INPUT = false; + /* Allowed XHTML+XML namespaces */ + let ALLOWED_NAMESPACES = null; + const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString); + let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']); + let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']); + // Certain elements are allowed in both SVG and HTML + // namespace. We need to specify them explicitly + // so that they don't get erroneously deleted from + // HTML namespace. + const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']); + /* Parsing of strict XHTML documents */ + let PARSER_MEDIA_TYPE = null; + const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html']; + const DEFAULT_PARSER_MEDIA_TYPE = 'text/html'; + let transformCaseFunc = null; + /* Keep a reference to config to pass to hooks */ + let CONFIG = null; + /* Ideally, do not touch anything below this line */ + /* ______________________________________________ */ + const formElement = document.createElement('form'); + const isRegexOrFunction = function isRegexOrFunction(testValue) { + return testValue instanceof RegExp || testValue instanceof Function; + }; + /** + * _parseConfig + * + * @param cfg optional config literal + */ + // eslint-disable-next-line complexity + const _parseConfig = function _parseConfig() { + let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + if (CONFIG && CONFIG === cfg) { + return; + } + /* Shield configuration object from tampering */ + if (!cfg || typeof cfg !== 'object') { + cfg = {}; + } + /* Shield configuration object from prototype pollution */ + cfg = clone(cfg); + PARSER_MEDIA_TYPE = + // eslint-disable-next-line unicorn/prefer-includes + SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE; + // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is. + transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase; + /* Set configuration parameters */ + ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS; + ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR; + ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES; + URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES; + DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS; + FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS; + FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {}; + FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {}; + USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false; + ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true + ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true + ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false + ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true + SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false + SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true + WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false + RETURN_DOM = cfg.RETURN_DOM || false; // Default false + RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false + RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false + FORCE_BODY = cfg.FORCE_BODY || false; // Default false + SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true + SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false + KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true + IN_PLACE = cfg.IN_PLACE || false; // Default false + IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI; + NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE; + MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS; + HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS; + CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {}; + if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) { + CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck; + } + if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) { + CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck; + } + if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') { + CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements; + } + if (SAFE_FOR_TEMPLATES) { + ALLOW_DATA_ATTR = false; + } + if (RETURN_DOM_FRAGMENT) { + RETURN_DOM = true; + } + /* Parse profile info */ + if (USE_PROFILES) { + ALLOWED_TAGS = addToSet({}, text); + ALLOWED_ATTR = []; + if (USE_PROFILES.html === true) { + addToSet(ALLOWED_TAGS, html$1); + addToSet(ALLOWED_ATTR, html); + } + if (USE_PROFILES.svg === true) { + addToSet(ALLOWED_TAGS, svg$1); + addToSet(ALLOWED_ATTR, svg); + addToSet(ALLOWED_ATTR, xml); + } + if (USE_PROFILES.svgFilters === true) { + addToSet(ALLOWED_TAGS, svgFilters); + addToSet(ALLOWED_ATTR, svg); + addToSet(ALLOWED_ATTR, xml); + } + if (USE_PROFILES.mathMl === true) { + addToSet(ALLOWED_TAGS, mathMl$1); + addToSet(ALLOWED_ATTR, mathMl); + addToSet(ALLOWED_ATTR, xml); + } + } + /* Merge configuration parameters */ + if (cfg.ADD_TAGS) { + if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) { + ALLOWED_TAGS = clone(ALLOWED_TAGS); + } + addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc); + } + if (cfg.ADD_ATTR) { + if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) { + ALLOWED_ATTR = clone(ALLOWED_ATTR); + } + addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc); + } + if (cfg.ADD_URI_SAFE_ATTR) { + addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc); + } + if (cfg.FORBID_CONTENTS) { + if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) { + FORBID_CONTENTS = clone(FORBID_CONTENTS); + } + addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc); + } + /* Add #text in case KEEP_CONTENT is set to true */ + if (KEEP_CONTENT) { + ALLOWED_TAGS['#text'] = true; + } + /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */ + if (WHOLE_DOCUMENT) { + addToSet(ALLOWED_TAGS, ['html', 'head', 'body']); + } + /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */ + if (ALLOWED_TAGS.table) { + addToSet(ALLOWED_TAGS, ['tbody']); + delete FORBID_TAGS.tbody; + } + if (cfg.TRUSTED_TYPES_POLICY) { + if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') { + throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.'); + } + if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') { + throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.'); + } + // Overwrite existing TrustedTypes policy. + trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY; + // Sign local variables required by `sanitize`. + emptyHTML = trustedTypesPolicy.createHTML(''); + } else { + // Uninitialized policy, attempt to initialize the internal dompurify policy. + if (trustedTypesPolicy === undefined) { + trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); + } + // If creating the internal policy succeeded sign internal variables. + if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') { + emptyHTML = trustedTypesPolicy.createHTML(''); + } + } + // Prevent further manipulation of configuration. + // Not available in IE8, Safari 5, etc. + if (freeze) { + freeze(cfg); + } + CONFIG = cfg; + }; + /* Keep track of all possible SVG and MathML tags + * so that we can perform the namespace checks + * correctly. */ + const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]); + const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]); + /** + * @param element a DOM element whose namespace is being checked + * @returns Return false if the element has a + * namespace that a spec-compliant parser would never + * return. Return true otherwise. + */ + const _checkValidNamespace = function _checkValidNamespace(element) { + let parent = getParentNode(element); + // In JSDOM, if we're inside shadow DOM, then parentNode + // can be null. We just simulate parent in this case. + if (!parent || !parent.tagName) { + parent = { + namespaceURI: NAMESPACE, + tagName: 'template' + }; + } + const tagName = stringToLowerCase(element.tagName); + const parentTagName = stringToLowerCase(parent.tagName); + if (!ALLOWED_NAMESPACES[element.namespaceURI]) { + return false; + } + if (element.namespaceURI === SVG_NAMESPACE) { + // The only way to switch from HTML namespace to SVG + // is via . If it happens via any other tag, then + // it should be killed. + if (parent.namespaceURI === HTML_NAMESPACE) { + return tagName === 'svg'; + } + // The only way to switch from MathML to SVG is via` + // svg if parent is either or MathML + // text integration points. + if (parent.namespaceURI === MATHML_NAMESPACE) { + return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]); + } + // We only allow elements that are defined in SVG + // spec. All others are disallowed in SVG namespace. + return Boolean(ALL_SVG_TAGS[tagName]); + } + if (element.namespaceURI === MATHML_NAMESPACE) { + // The only way to switch from HTML namespace to MathML + // is via . If it happens via any other tag, then + // it should be killed. + if (parent.namespaceURI === HTML_NAMESPACE) { + return tagName === 'math'; + } + // The only way to switch from SVG to MathML is via + // and HTML integration points + if (parent.namespaceURI === SVG_NAMESPACE) { + return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName]; + } + // We only allow elements that are defined in MathML + // spec. All others are disallowed in MathML namespace. + return Boolean(ALL_MATHML_TAGS[tagName]); + } + if (element.namespaceURI === HTML_NAMESPACE) { + // The only way to switch from SVG to HTML is via + // HTML integration points, and from MathML to HTML + // is via MathML text integration points + if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) { + return false; + } + if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) { + return false; + } + // We disallow tags that are specific for MathML + // or SVG and should never appear in HTML namespace + return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]); + } + // For XHTML and XML documents that support custom namespaces + if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) { + return true; + } + // The code should never reach this place (this means + // that the element somehow got namespace that is not + // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES). + // Return false just in case. + return false; + }; + /** + * _forceRemove + * + * @param node a DOM node + */ + const _forceRemove = function _forceRemove(node) { + arrayPush(DOMPurify.removed, { + element: node + }); + try { + // eslint-disable-next-line unicorn/prefer-dom-node-remove + getParentNode(node).removeChild(node); + } catch (_) { + remove(node); + } + }; + /** + * _removeAttribute + * + * @param name an Attribute name + * @param element a DOM node + */ + const _removeAttribute = function _removeAttribute(name, element) { + try { + arrayPush(DOMPurify.removed, { + attribute: element.getAttributeNode(name), + from: element + }); + } catch (_) { + arrayPush(DOMPurify.removed, { + attribute: null, + from: element + }); + } + element.removeAttribute(name); + // We void attribute values for unremovable "is" attributes + if (name === 'is') { + if (RETURN_DOM || RETURN_DOM_FRAGMENT) { + try { + _forceRemove(element); + } catch (_) {} + } else { + try { + element.setAttribute(name, ''); + } catch (_) {} + } + } + }; + /** + * _initDocument + * + * @param dirty - a string of dirty markup + * @return a DOM, filled with the dirty markup + */ + const _initDocument = function _initDocument(dirty) { + /* Create a HTML document */ + let doc = null; + let leadingWhitespace = null; + if (FORCE_BODY) { + dirty = '' + dirty; + } else { + /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */ + const matches = stringMatch(dirty, /^[\r\n\t ]+/); + leadingWhitespace = matches && matches[0]; + } + if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) { + // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict) + dirty = '' + dirty + ''; + } + const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty; + /* + * Use the DOMParser API by default, fallback later if needs be + * DOMParser not work for svg when has multiple root element. + */ + if (NAMESPACE === HTML_NAMESPACE) { + try { + doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE); + } catch (_) {} + } + /* Use createHTMLDocument in case DOMParser is not available */ + if (!doc || !doc.documentElement) { + doc = implementation.createDocument(NAMESPACE, 'template', null); + try { + doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload; + } catch (_) { + // Syntax error if dirtyPayload is invalid xml + } + } + const body = doc.body || doc.documentElement; + if (dirty && leadingWhitespace) { + body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null); + } + /* Work on whole document or just its body */ + if (NAMESPACE === HTML_NAMESPACE) { + return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0]; + } + return WHOLE_DOCUMENT ? doc.documentElement : body; + }; + /** + * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. + * + * @param root The root element or node to start traversing on. + * @return The created NodeIterator + */ + const _createNodeIterator = function _createNodeIterator(root) { + return createNodeIterator.call(root.ownerDocument || root, root, + // eslint-disable-next-line no-bitwise + NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null); + }; + /** + * _isClobbered + * + * @param element element to check for clobbering attacks + * @return true if clobbered, false if safe + */ + const _isClobbered = function _isClobbered(element) { + return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function'); + }; + /** + * Checks whether the given object is a DOM node. + * + * @param value object to check whether it's a DOM node + * @return true is object is a DOM node + */ + const _isNode = function _isNode(value) { + return typeof Node === 'function' && value instanceof Node; + }; + function _executeHooks(hooks, currentNode, data) { + arrayForEach(hooks, hook => { + hook.call(DOMPurify, currentNode, data, CONFIG); + }); + } + /** + * _sanitizeElements + * + * @protect nodeName + * @protect textContent + * @protect removeChild + * @param currentNode to check for permission to exist + * @return true if node was killed, false if left alive + */ + const _sanitizeElements = function _sanitizeElements(currentNode) { + let content = null; + /* Execute a hook if present */ + _executeHooks(hooks.beforeSanitizeElements, currentNode, null); + /* Check if element is clobbered or can clobber */ + if (_isClobbered(currentNode)) { + _forceRemove(currentNode); + return true; + } + /* Now let's check the element's type and name */ + const tagName = transformCaseFunc(currentNode.nodeName); + /* Execute a hook if present */ + _executeHooks(hooks.uponSanitizeElement, currentNode, { + tagName, + allowedTags: ALLOWED_TAGS + }); + /* Detect mXSS attempts abusing namespace confusion */ + if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) { + _forceRemove(currentNode); + return true; + } + /* Remove any occurrence of processing instructions */ + if (currentNode.nodeType === NODE_TYPE.progressingInstruction) { + _forceRemove(currentNode); + return true; + } + /* Remove any kind of possibly harmful comments */ + if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) { + _forceRemove(currentNode); + return true; + } + /* Remove element if anything forbids its presence */ + if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { + /* Check if we have a custom element to handle */ + if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) { + if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) { + return false; + } + if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) { + return false; + } + } + /* Keep content except for bad-listed elements */ + if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) { + const parentNode = getParentNode(currentNode) || currentNode.parentNode; + const childNodes = getChildNodes(currentNode) || currentNode.childNodes; + if (childNodes && parentNode) { + const childCount = childNodes.length; + for (let i = childCount - 1; i >= 0; --i) { + const childClone = cloneNode(childNodes[i], true); + childClone.__removalCount = (currentNode.__removalCount || 0) + 1; + parentNode.insertBefore(childClone, getNextSibling(currentNode)); + } + } + } + _forceRemove(currentNode); + return true; + } + /* Check whether element has a valid namespace */ + if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) { + _forceRemove(currentNode); + return true; + } + /* Make sure that older browsers don't get fallback-tag mXSS */ + if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) { + _forceRemove(currentNode); + return true; + } + /* Sanitize element content to be template-safe */ + if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) { + /* Get the element's text content */ + content = currentNode.textContent; + arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => { + content = stringReplace(content, expr, ' '); + }); + if (currentNode.textContent !== content) { + arrayPush(DOMPurify.removed, { + element: currentNode.cloneNode() + }); + currentNode.textContent = content; + } + } + /* Execute a hook if present */ + _executeHooks(hooks.afterSanitizeElements, currentNode, null); + return false; + }; + /** + * _isValidAttribute + * + * @param lcTag Lowercase tag name of containing element. + * @param lcName Lowercase attribute name. + * @param value Attribute value. + * @return Returns true if `value` is valid, otherwise false. + */ + // eslint-disable-next-line complexity + const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) { + /* Make sure attribute cannot clobber */ + if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) { + return false; + } + /* Allow valid data-* attributes: At least one character after "-" + (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes) + XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804) + We don't need to check the value; it's always URI safe. */ + if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ;else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ;else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) { + if ( + // First condition does a very basic check if a) it's basically a valid custom element tagname AND + // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck + // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck + _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) || + // Alternative, second condition checks if it's an `is`-attribute, AND + // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck + lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ;else { + return false; + } + /* Check value is safe. First, is attr inert? If so, is safe */ + } else if (URI_SAFE_ATTRIBUTES[lcName]) ;else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ;else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ;else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ;else if (value) { + return false; + } else ; + return true; + }; + /** + * _isBasicCustomElement + * checks if at least one dash is included in tagName, and it's not the first char + * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name + * + * @param tagName name of the tag of the node to sanitize + * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false. + */ + const _isBasicCustomElement = function _isBasicCustomElement(tagName) { + return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT); + }; + /** + * _sanitizeAttributes + * + * @protect attributes + * @protect nodeName + * @protect removeAttribute + * @protect setAttribute + * + * @param currentNode to sanitize + */ + const _sanitizeAttributes = function _sanitizeAttributes(currentNode) { + /* Execute a hook if present */ + _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null); + const { + attributes + } = currentNode; + /* Check if we have attributes; if not we might have a text node */ + if (!attributes || _isClobbered(currentNode)) { + return; + } + const hookEvent = { + attrName: '', + attrValue: '', + keepAttr: true, + allowedAttributes: ALLOWED_ATTR, + forceKeepAttr: undefined + }; + let l = attributes.length; + /* Go backwards over all attributes; safely remove bad ones */ + while (l--) { + const attr = attributes[l]; + const { + name, + namespaceURI, + value: attrValue + } = attr; + const lcName = transformCaseFunc(name); + let value = name === 'value' ? attrValue : stringTrim(attrValue); + /* Execute a hook if present */ + hookEvent.attrName = lcName; + hookEvent.attrValue = value; + hookEvent.keepAttr = true; + hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set + _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent); + value = hookEvent.attrValue; + /* Full DOM Clobbering protection via namespace isolation, + * Prefix id and name attributes with `user-content-` + */ + if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) { + // Remove the attribute with this value + _removeAttribute(name, currentNode); + // Prefix the value and later re-create the attribute with the sanitized value + value = SANITIZE_NAMED_PROPS_PREFIX + value; + } + /* Work around a security issue with comments inside attributes */ + if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) { + _removeAttribute(name, currentNode); + continue; + } + /* Did the hooks approve of the attribute? */ + if (hookEvent.forceKeepAttr) { + continue; + } + /* Remove attribute */ + _removeAttribute(name, currentNode); + /* Did the hooks approve of the attribute? */ + if (!hookEvent.keepAttr) { + continue; + } + /* Work around a security issue in jQuery 3.0 */ + if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) { + _removeAttribute(name, currentNode); + continue; + } + /* Sanitize attribute content to be template-safe */ + if (SAFE_FOR_TEMPLATES) { + arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => { + value = stringReplace(value, expr, ' '); + }); + } + /* Is `value` valid for this attribute? */ + const lcTag = transformCaseFunc(currentNode.nodeName); + if (!_isValidAttribute(lcTag, lcName, value)) { + continue; + } + /* Handle attributes that require Trusted Types */ + if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') { + if (namespaceURI) ;else { + switch (trustedTypes.getAttributeType(lcTag, lcName)) { + case 'TrustedHTML': + { + value = trustedTypesPolicy.createHTML(value); + break; + } + case 'TrustedScriptURL': + { + value = trustedTypesPolicy.createScriptURL(value); + break; + } + } + } + } + /* Handle invalid data-* attribute set by try-catching it */ + try { + if (namespaceURI) { + currentNode.setAttributeNS(namespaceURI, name, value); + } else { + /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */ + currentNode.setAttribute(name, value); + } + if (_isClobbered(currentNode)) { + _forceRemove(currentNode); + } else { + arrayPop(DOMPurify.removed); + } + } catch (_) {} + } + /* Execute a hook if present */ + _executeHooks(hooks.afterSanitizeAttributes, currentNode, null); + }; + /** + * _sanitizeShadowDOM + * + * @param fragment to iterate over recursively + */ + const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) { + let shadowNode = null; + const shadowIterator = _createNodeIterator(fragment); + /* Execute a hook if present */ + _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null); + while (shadowNode = shadowIterator.nextNode()) { + /* Execute a hook if present */ + _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null); + /* Sanitize tags and elements */ + _sanitizeElements(shadowNode); + /* Check attributes next */ + _sanitizeAttributes(shadowNode); + /* Deep shadow DOM detected */ + if (shadowNode.content instanceof DocumentFragment) { + _sanitizeShadowDOM(shadowNode.content); + } + } + /* Execute a hook if present */ + _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null); + }; + // eslint-disable-next-line complexity + DOMPurify.sanitize = function (dirty) { + let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let body = null; + let importedNode = null; + let currentNode = null; + let returnNode = null; + /* Make sure we have a string to sanitize. + DO NOT return early, as this will return the wrong type if + the user has requested a DOM object rather than a string */ + IS_EMPTY_INPUT = !dirty; + if (IS_EMPTY_INPUT) { + dirty = ''; + } + /* Stringify, in case dirty is an object */ + if (typeof dirty !== 'string' && !_isNode(dirty)) { + if (typeof dirty.toString === 'function') { + dirty = dirty.toString(); + if (typeof dirty !== 'string') { + throw typeErrorCreate('dirty is not a string, aborting'); + } + } else { + throw typeErrorCreate('toString is not a function'); + } + } + /* Return dirty HTML if DOMPurify cannot run */ + if (!DOMPurify.isSupported) { + return dirty; + } + /* Assign config vars */ + if (!SET_CONFIG) { + _parseConfig(cfg); + } + /* Clean up removed elements */ + DOMPurify.removed = []; + /* Check if dirty is correctly typed for IN_PLACE */ + if (typeof dirty === 'string') { + IN_PLACE = false; + } + if (IN_PLACE) { + /* Do some early pre-sanitization to avoid unsafe root nodes */ + if (dirty.nodeName) { + const tagName = transformCaseFunc(dirty.nodeName); + if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { + throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place'); + } + } + } else if (dirty instanceof Node) { + /* If dirty is a DOM element, append to an empty document to avoid + elements being stripped by the parser */ + body = _initDocument(''); + importedNode = body.ownerDocument.importNode(dirty, true); + if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') { + /* Node is already a body, use as is */ + body = importedNode; + } else if (importedNode.nodeName === 'HTML') { + body = importedNode; + } else { + // eslint-disable-next-line unicorn/prefer-dom-node-append + body.appendChild(importedNode); + } + } else { + /* Exit directly if we have nothing to do */ + if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && + // eslint-disable-next-line unicorn/prefer-includes + dirty.indexOf('<') === -1) { + return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty; + } + /* Initialize the document to work on */ + body = _initDocument(dirty); + /* Check we have a DOM node from the data */ + if (!body) { + return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : ''; + } + } + /* Remove first element node (ours) if FORCE_BODY is set */ + if (body && FORCE_BODY) { + _forceRemove(body.firstChild); + } + /* Get node iterator */ + const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body); + /* Now start iterating over the created document */ + while (currentNode = nodeIterator.nextNode()) { + /* Sanitize tags and elements */ + _sanitizeElements(currentNode); + /* Check attributes next */ + _sanitizeAttributes(currentNode); + /* Shadow DOM detected, sanitize it */ + if (currentNode.content instanceof DocumentFragment) { + _sanitizeShadowDOM(currentNode.content); + } + } + /* If we sanitized `dirty` in-place, return it. */ + if (IN_PLACE) { + return dirty; + } + /* Return sanitized string or DOM */ + if (RETURN_DOM) { + if (RETURN_DOM_FRAGMENT) { + returnNode = createDocumentFragment.call(body.ownerDocument); + while (body.firstChild) { + // eslint-disable-next-line unicorn/prefer-dom-node-append + returnNode.appendChild(body.firstChild); + } + } else { + returnNode = body; + } + if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) { + /* + AdoptNode() is not used because internal state is not reset + (e.g. the past names map of a HTMLFormElement), this is safe + in theory but we would rather not risk another attack vector. + The state that is cloned by importNode() is explicitly defined + by the specs. + */ + returnNode = importNode.call(originalDocument, returnNode, true); + } + return returnNode; + } + let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML; + /* Serialize doctype if allowed */ + if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) { + serializedHTML = '\n' + serializedHTML; + } + /* Sanitize final string template-safe */ + if (SAFE_FOR_TEMPLATES) { + arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => { + serializedHTML = stringReplace(serializedHTML, expr, ' '); + }); + } + return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML; + }; + DOMPurify.setConfig = function () { + let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + _parseConfig(cfg); + SET_CONFIG = true; + }; + DOMPurify.clearConfig = function () { + CONFIG = null; + SET_CONFIG = false; + }; + DOMPurify.isValidAttribute = function (tag, attr, value) { + /* Initialize shared config vars if necessary. */ + if (!CONFIG) { + _parseConfig({}); + } + const lcTag = transformCaseFunc(tag); + const lcName = transformCaseFunc(attr); + return _isValidAttribute(lcTag, lcName, value); + }; + DOMPurify.addHook = function (entryPoint, hookFunction) { + if (typeof hookFunction !== 'function') { + return; + } + arrayPush(hooks[entryPoint], hookFunction); + }; + DOMPurify.removeHook = function (entryPoint) { + return arrayPop(hooks[entryPoint]); + }; + DOMPurify.removeHooks = function (entryPoint) { + hooks[entryPoint] = []; + }; + DOMPurify.removeAllHooks = function () { + hooks = _createHooksMap(); + }; + return DOMPurify; + } + var purify = createDOMPurify(); + + const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" "); + const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" "); + const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript".split(" "); + class HTMLSanitizer extends BasicObject { + static setHTML(element, html) { + const sanitizedElement = new this(html).sanitize(); + const sanitizedHtml = sanitizedElement.getHTML ? sanitizedElement.getHTML() : sanitizedElement.outerHTML; + element.innerHTML = sanitizedHtml; + } + static sanitize(html, options) { + const sanitizer = new this(html, options); + sanitizer.sanitize(); + return sanitizer; + } + constructor(html) { + let { + allowedAttributes, + forbiddenProtocols, + forbiddenElements + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + super(...arguments); + this.allowedAttributes = allowedAttributes || DEFAULT_ALLOWED_ATTRIBUTES; + this.forbiddenProtocols = forbiddenProtocols || DEFAULT_FORBIDDEN_PROTOCOLS; + this.forbiddenElements = forbiddenElements || DEFAULT_FORBIDDEN_ELEMENTS; + this.body = createBodyElementForHTML(html); + } + sanitize() { + this.sanitizeElements(); + this.normalizeListElementNesting(); + return purify.sanitize(this.body, { + ADD_ATTR: ["language"], + RETURN_DOM: true + }); + } + getHTML() { + return this.body.innerHTML; + } + getBody() { + return this.body; + } + + // Private + + sanitizeElements() { + const walker = walkTree(this.body); + const nodesToRemove = []; + while (walker.nextNode()) { + const node = walker.currentNode; + switch (node.nodeType) { + case Node.ELEMENT_NODE: + if (this.elementIsRemovable(node)) { + nodesToRemove.push(node); + } else { + this.sanitizeElement(node); + } + break; + case Node.COMMENT_NODE: + nodesToRemove.push(node); + break; + } + } + nodesToRemove.forEach(node => removeNode(node)); + return this.body; + } + sanitizeElement(element) { + if (element.hasAttribute("href")) { + if (this.forbiddenProtocols.includes(element.protocol)) { + element.removeAttribute("href"); + } + } + Array.from(element.attributes).forEach(_ref => { + let { + name + } = _ref; + if (!this.allowedAttributes.includes(name) && name.indexOf("data-trix") !== 0) { + element.removeAttribute(name); + } + }); + return element; + } + normalizeListElementNesting() { + Array.from(this.body.querySelectorAll("ul,ol")).forEach(listElement => { + const previousElement = listElement.previousElementSibling; + if (previousElement) { + if (tagName(previousElement) === "li") { + previousElement.appendChild(listElement); + } + } + }); + return this.body; + } + elementIsRemovable(element) { + if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) return; + return this.elementIsForbidden(element) || this.elementIsntSerializable(element); + } + elementIsForbidden(element) { + return this.forbiddenElements.includes(tagName(element)); + } + elementIsntSerializable(element) { + return element.getAttribute("data-trix-serialize") === "false" && !nodeIsAttachmentElement(element); + } + } + const createBodyElementForHTML = function () { + let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + // Remove everything after + html = html.replace(/<\/html[^>]*>[^]*$/i, ""); + const doc = document.implementation.createHTMLDocument(""); + doc.documentElement.innerHTML = html; + Array.from(doc.head.querySelectorAll("style")).forEach(element => { + doc.body.appendChild(element); + }); + return doc.body; + }; + + const { + css: css$2 + } = config; + class AttachmentView extends ObjectView { + constructor() { + super(...arguments); + this.attachment = this.object; + this.attachment.uploadProgressDelegate = this; + this.attachmentPiece = this.options.piece; + } + createContentNodes() { + return []; + } + createNodes() { + let innerElement; + const figure = innerElement = makeElement({ + tagName: "figure", + className: this.getClassName(), + data: this.getData(), + editable: false + }); + const href = this.getHref(); + if (href) { + innerElement = makeElement({ + tagName: "a", + editable: false, + attributes: { + href, + tabindex: -1 + } + }); + figure.appendChild(innerElement); + } + if (this.attachment.hasContent()) { + HTMLSanitizer.setHTML(innerElement, this.attachment.getContent()); + } else { + this.createContentNodes().forEach(node => { + innerElement.appendChild(node); + }); + } + innerElement.appendChild(this.createCaptionElement()); + if (this.attachment.isPending()) { + this.progressElement = makeElement({ + tagName: "progress", + attributes: { + class: css$2.attachmentProgress, + value: this.attachment.getUploadProgress(), + max: 100 + }, + data: { + trixMutable: true, + trixStoreKey: ["progressElement", this.attachment.id].join("/") + } + }); + figure.appendChild(this.progressElement); + } + return [createCursorTarget("left"), figure, createCursorTarget("right")]; + } + createCaptionElement() { + const figcaption = makeElement({ + tagName: "figcaption", + className: css$2.attachmentCaption + }); + const caption = this.attachmentPiece.getCaption(); + if (caption) { + figcaption.classList.add("".concat(css$2.attachmentCaption, "--edited")); + figcaption.textContent = caption; + } else { + let name, size; + const captionConfig = this.getCaptionConfig(); + if (captionConfig.name) { + name = this.attachment.getFilename(); + } + if (captionConfig.size) { + size = this.attachment.getFormattedFilesize(); + } + if (name) { + const nameElement = makeElement({ + tagName: "span", + className: css$2.attachmentName, + textContent: name + }); + figcaption.appendChild(nameElement); + } + if (size) { + if (name) { + figcaption.appendChild(document.createTextNode(" ")); + } + const sizeElement = makeElement({ + tagName: "span", + className: css$2.attachmentSize, + textContent: size + }); + figcaption.appendChild(sizeElement); + } + } + return figcaption; + } + getClassName() { + const names = [css$2.attachment, "".concat(css$2.attachment, "--").concat(this.attachment.getType())]; + const extension = this.attachment.getExtension(); + if (extension) { + names.push("".concat(css$2.attachment, "--").concat(extension)); + } + return names.join(" "); + } + getData() { + const data = { + trixAttachment: JSON.stringify(this.attachment), + trixContentType: this.attachment.getContentType(), + trixId: this.attachment.id + }; + const { + attributes + } = this.attachmentPiece; + if (!attributes.isEmpty()) { + data.trixAttributes = JSON.stringify(attributes); + } + if (this.attachment.isPending()) { + data.trixSerialize = false; + } + return data; + } + getHref() { + if (!htmlContainsTagName(this.attachment.getContent(), "a")) { + return this.attachment.getHref(); + } + } + getCaptionConfig() { + var _config$attachments$t; + const type = this.attachment.getType(); + const captionConfig = copyObject((_config$attachments$t = attachments[type]) === null || _config$attachments$t === void 0 ? void 0 : _config$attachments$t.caption); + if (type === "file") { + captionConfig.name = true; + } + return captionConfig; + } + findProgressElement() { + var _this$findElement; + return (_this$findElement = this.findElement()) === null || _this$findElement === void 0 ? void 0 : _this$findElement.querySelector("progress"); + } + + // Attachment delegate + + attachmentDidChangeUploadProgress() { + const value = this.attachment.getUploadProgress(); + const progressElement = this.findProgressElement(); + if (progressElement) { + progressElement.value = value; + } + } + } + const createCursorTarget = name => makeElement({ + tagName: "span", + textContent: ZERO_WIDTH_SPACE, + data: { + trixCursorTarget: name, + trixSerialize: false + } + }); + const htmlContainsTagName = function (html, tagName) { + const div = makeElement("div"); + HTMLSanitizer.setHTML(div, html || ""); + return div.querySelector(tagName); + }; + + class PreviewableAttachmentView extends AttachmentView { + constructor() { + super(...arguments); + this.attachment.previewDelegate = this; + } + createContentNodes() { + this.image = makeElement({ + tagName: "img", + attributes: { + src: "" + }, + data: { + trixMutable: true + } + }); + this.refresh(this.image); + return [this.image]; + } + createCaptionElement() { + const figcaption = super.createCaptionElement(...arguments); + if (!figcaption.textContent) { + figcaption.setAttribute("data-trix-placeholder", lang$1.captionPlaceholder); + } + return figcaption; + } + refresh(image) { + if (!image) { + var _this$findElement; + image = (_this$findElement = this.findElement()) === null || _this$findElement === void 0 ? void 0 : _this$findElement.querySelector("img"); + } + if (image) { + return this.updateAttributesForImage(image); + } + } + updateAttributesForImage(image) { + const url = this.attachment.getURL(); + const previewURL = this.attachment.getPreviewURL(); + image.src = previewURL || url; + if (previewURL === url) { + image.removeAttribute("data-trix-serialized-attributes"); + } else { + const serializedAttributes = JSON.stringify({ + src: url + }); + image.setAttribute("data-trix-serialized-attributes", serializedAttributes); + } + const width = this.attachment.getWidth(); + const height = this.attachment.getHeight(); + if (width != null) { + image.width = width; + } + if (height != null) { + image.height = height; + } + const storeKey = ["imageElement", this.attachment.id, image.src, image.width, image.height].join("/"); + image.dataset.trixStoreKey = storeKey; + } + + // Attachment delegate + + attachmentDidChangeAttributes() { + this.refresh(this.image); + return this.refresh(); + } + } + + /* eslint-disable + no-useless-escape, + no-var, + */ + class PieceView extends ObjectView { + constructor() { + super(...arguments); + this.piece = this.object; + this.attributes = this.piece.getAttributes(); + this.textConfig = this.options.textConfig; + this.context = this.options.context; + if (this.piece.attachment) { + this.attachment = this.piece.attachment; + } else { + this.string = this.piece.toString(); + } + } + createNodes() { + let nodes = this.attachment ? this.createAttachmentNodes() : this.createStringNodes(); + const element = this.createElement(); + if (element) { + const innerElement = findInnerElement(element); + Array.from(nodes).forEach(node => { + innerElement.appendChild(node); + }); + nodes = [element]; + } + return nodes; + } + createAttachmentNodes() { + const constructor = this.attachment.isPreviewable() ? PreviewableAttachmentView : AttachmentView; + const view = this.createChildView(constructor, this.piece.attachment, { + piece: this.piece + }); + return view.getNodes(); + } + createStringNodes() { + var _this$textConfig; + if ((_this$textConfig = this.textConfig) !== null && _this$textConfig !== void 0 && _this$textConfig.plaintext) { + return [document.createTextNode(this.string)]; + } else { + const nodes = []; + const iterable = this.string.split("\n"); + for (let index = 0; index < iterable.length; index++) { + const substring = iterable[index]; + if (index > 0) { + const element = makeElement("br"); + nodes.push(element); + } + if (substring.length) { + const node = document.createTextNode(this.preserveSpaces(substring)); + nodes.push(node); + } + } + return nodes; + } + } + createElement() { + let element, key, value; + const styles = {}; + for (key in this.attributes) { + value = this.attributes[key]; + const config = getTextConfig(key); + if (config) { + if (config.tagName) { + var innerElement; + const pendingElement = makeElement(config.tagName); + if (innerElement) { + innerElement.appendChild(pendingElement); + innerElement = pendingElement; + } else { + element = innerElement = pendingElement; + } + } + if (config.styleProperty) { + styles[config.styleProperty] = value; + } + if (config.style) { + for (key in config.style) { + value = config.style[key]; + styles[key] = value; + } + } + } + } + if (Object.keys(styles).length) { + if (!element) { + element = makeElement("span"); + } + for (key in styles) { + value = styles[key]; + element.style[key] = value; + } + } + return element; + } + createContainerElement() { + for (const key in this.attributes) { + const value = this.attributes[key]; + const config = getTextConfig(key); + if (config) { + if (config.groupTagName) { + const attributes = {}; + attributes[key] = value; + return makeElement(config.groupTagName, attributes); + } + } + } + } + preserveSpaces(string) { + if (this.context.isLast) { + string = string.replace(/\ $/, NON_BREAKING_SPACE); + } + string = string.replace(/(\S)\ {3}(\S)/g, "$1 ".concat(NON_BREAKING_SPACE, " $2")).replace(/\ {2}/g, "".concat(NON_BREAKING_SPACE, " ")).replace(/\ {2}/g, " ".concat(NON_BREAKING_SPACE)); + if (this.context.isFirst || this.context.followsWhitespace) { + string = string.replace(/^\ /, NON_BREAKING_SPACE); + } + return string; + } + } + + /* eslint-disable + no-var, + */ + class TextView extends ObjectView { + constructor() { + super(...arguments); + this.text = this.object; + this.textConfig = this.options.textConfig; + } + createNodes() { + const nodes = []; + const pieces = ObjectGroup.groupObjects(this.getPieces()); + const lastIndex = pieces.length - 1; + for (let index = 0; index < pieces.length; index++) { + const piece = pieces[index]; + const context = {}; + if (index === 0) { + context.isFirst = true; + } + if (index === lastIndex) { + context.isLast = true; + } + if (endsWithWhitespace(previousPiece)) { + context.followsWhitespace = true; + } + const view = this.findOrCreateCachedChildView(PieceView, piece, { + textConfig: this.textConfig, + context + }); + nodes.push(...Array.from(view.getNodes() || [])); + var previousPiece = piece; + } + return nodes; + } + getPieces() { + return Array.from(this.text.getPieces()).filter(piece => !piece.hasAttribute("blockBreak")); + } + } + const endsWithWhitespace = piece => /\s$/.test(piece === null || piece === void 0 ? void 0 : piece.toString()); + + const { + css: css$1 + } = config; + class BlockView extends ObjectView { + constructor() { + super(...arguments); + this.block = this.object; + this.attributes = this.block.getAttributes(); + } + createNodes() { + const comment = document.createComment("block"); + const nodes = [comment]; + if (this.block.isEmpty()) { + nodes.push(makeElement("br")); + } else { + var _getBlockConfig; + const textConfig = (_getBlockConfig = getBlockConfig(this.block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.text; + const textView = this.findOrCreateCachedChildView(TextView, this.block.text, { + textConfig + }); + nodes.push(...Array.from(textView.getNodes() || [])); + if (this.shouldAddExtraNewlineElement()) { + nodes.push(makeElement("br")); + } + } + if (this.attributes.length) { + return nodes; + } else { + let attributes$1; + const { + tagName + } = attributes.default; + if (this.block.isRTL()) { + attributes$1 = { + dir: "rtl" + }; + } + const element = makeElement({ + tagName, + attributes: attributes$1 + }); + nodes.forEach(node => element.appendChild(node)); + return [element]; + } + } + createContainerElement(depth) { + const attributes = {}; + let className; + const attributeName = this.attributes[depth]; + const { + tagName, + htmlAttributes = [] + } = getBlockConfig(attributeName); + if (depth === 0 && this.block.isRTL()) { + Object.assign(attributes, { + dir: "rtl" + }); + } + if (attributeName === "attachmentGallery") { + const size = this.block.getBlockBreakPosition(); + className = "".concat(css$1.attachmentGallery, " ").concat(css$1.attachmentGallery, "--").concat(size); + } + Object.entries(this.block.htmlAttributes).forEach(_ref => { + let [name, value] = _ref; + if (htmlAttributes.includes(name)) { + attributes[name] = value; + } + }); + return makeElement({ + tagName, + className, + attributes + }); + } + + // A single
at the end of a block element has no visual representation + // so add an extra one. + shouldAddExtraNewlineElement() { + return /\n\n$/.test(this.block.toString()); + } + } + + class DocumentView extends ObjectView { + static render(document) { + const element = makeElement("div"); + const view = new this(document, { + element + }); + view.render(); + view.sync(); + return element; + } + constructor() { + super(...arguments); + this.element = this.options.element; + this.elementStore = new ElementStore(); + this.setDocument(this.object); + } + setDocument(document) { + if (!document.isEqualTo(this.document)) { + this.document = this.object = document; + } + } + render() { + this.childViews = []; + this.shadowElement = makeElement("div"); + if (!this.document.isEmpty()) { + const objects = ObjectGroup.groupObjects(this.document.getBlocks(), { + asTree: true + }); + Array.from(objects).forEach(object => { + const view = this.findOrCreateCachedChildView(BlockView, object); + Array.from(view.getNodes()).map(node => this.shadowElement.appendChild(node)); + }); + } + } + isSynced() { + return elementsHaveEqualHTML(this.shadowElement, this.element); + } + sync() { + const fragment = this.createDocumentFragmentForSync(); + while (this.element.lastChild) { + this.element.removeChild(this.element.lastChild); + } + this.element.appendChild(fragment); + return this.didSync(); + } + + // Private + + didSync() { + this.elementStore.reset(findStoredElements(this.element)); + return defer(() => this.garbageCollectCachedViews()); + } + createDocumentFragmentForSync() { + const fragment = document.createDocumentFragment(); + Array.from(this.shadowElement.childNodes).forEach(node => { + fragment.appendChild(node.cloneNode(true)); + }); + Array.from(findStoredElements(fragment)).forEach(element => { + const storedElement = this.elementStore.remove(element); + if (storedElement) { + element.parentNode.replaceChild(storedElement, element); + } + }); + return fragment; + } + } + const findStoredElements = element => element.querySelectorAll("[data-trix-store-key]"); + const elementsHaveEqualHTML = (element, otherElement) => ignoreSpaces(element.innerHTML) === ignoreSpaces(otherElement.innerHTML); + const ignoreSpaces = html => html.replace(/ /g, " "); + + function _AsyncGenerator(e) { + var r, t; + function resume(r, t) { + try { + var n = e[r](t), + o = n.value, + u = o instanceof _OverloadYield; + Promise.resolve(u ? o.v : o).then(function (t) { + if (u) { + var i = "return" === r ? "return" : "next"; + if (!o.k || t.done) return resume(i, t); + t = e[i](t).value; + } + settle(n.done ? "return" : "normal", t); + }, function (e) { + resume("throw", e); + }); + } catch (e) { + settle("throw", e); + } + } + function settle(e, n) { + switch (e) { + case "return": + r.resolve({ + value: n, + done: !0 + }); + break; + case "throw": + r.reject(n); + break; + default: + r.resolve({ + value: n, + done: !1 + }); + } + (r = r.next) ? resume(r.key, r.arg) : t = null; + } + this._invoke = function (e, n) { + return new Promise(function (o, u) { + var i = { + key: e, + arg: n, + resolve: o, + reject: u, + next: null + }; + t ? t = t.next = i : (r = t = i, resume(e, n)); + }); + }, "function" != typeof e.return && (this.return = void 0); + } + _AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function () { + return this; + }, _AsyncGenerator.prototype.next = function (e) { + return this._invoke("next", e); + }, _AsyncGenerator.prototype.throw = function (e) { + return this._invoke("throw", e); + }, _AsyncGenerator.prototype.return = function (e) { + return this._invoke("return", e); + }; + function _OverloadYield(t, e) { + this.v = t, this.k = e; + } + function old_createMetadataMethodsForProperty(e, t, a, r) { + return { + getMetadata: function (o) { + old_assertNotFinished(r, "getMetadata"), old_assertMetadataKey(o); + var i = e[o]; + if (void 0 !== i) if (1 === t) { + var n = i.public; + if (void 0 !== n) return n[a]; + } else if (2 === t) { + var l = i.private; + if (void 0 !== l) return l.get(a); + } else if (Object.hasOwnProperty.call(i, "constructor")) return i.constructor; + }, + setMetadata: function (o, i) { + old_assertNotFinished(r, "setMetadata"), old_assertMetadataKey(o); + var n = e[o]; + if (void 0 === n && (n = e[o] = {}), 1 === t) { + var l = n.public; + void 0 === l && (l = n.public = {}), l[a] = i; + } else if (2 === t) { + var s = n.priv; + void 0 === s && (s = n.private = new Map()), s.set(a, i); + } else n.constructor = i; + } + }; + } + function old_convertMetadataMapToFinal(e, t) { + var a = e[Symbol.metadata || Symbol.for("Symbol.metadata")], + r = Object.getOwnPropertySymbols(t); + if (0 !== r.length) { + for (var o = 0; o < r.length; o++) { + var i = r[o], + n = t[i], + l = a ? a[i] : null, + s = n.public, + c = l ? l.public : null; + s && c && Object.setPrototypeOf(s, c); + var d = n.private; + if (d) { + var u = Array.from(d.values()), + f = l ? l.private : null; + f && (u = u.concat(f)), n.private = u; + } + l && Object.setPrototypeOf(n, l); + } + a && Object.setPrototypeOf(t, a), e[Symbol.metadata || Symbol.for("Symbol.metadata")] = t; + } + } + function old_createAddInitializerMethod(e, t) { + return function (a) { + old_assertNotFinished(t, "addInitializer"), old_assertCallable(a, "An initializer"), e.push(a); + }; + } + function old_memberDec(e, t, a, r, o, i, n, l, s) { + var c; + switch (i) { + case 1: + c = "accessor"; + break; + case 2: + c = "method"; + break; + case 3: + c = "getter"; + break; + case 4: + c = "setter"; + break; + default: + c = "field"; + } + var d, + u, + f = { + kind: c, + name: l ? "#" + t : t, + isStatic: n, + isPrivate: l + }, + p = { + v: !1 + }; + if (0 !== i && (f.addInitializer = old_createAddInitializerMethod(o, p)), l) { + d = 2, u = Symbol(t); + var v = {}; + 0 === i ? (v.get = a.get, v.set = a.set) : 2 === i ? v.get = function () { + return a.value; + } : (1 !== i && 3 !== i || (v.get = function () { + return a.get.call(this); + }), 1 !== i && 4 !== i || (v.set = function (e) { + a.set.call(this, e); + })), f.access = v; + } else d = 1, u = t; + try { + return e(s, Object.assign(f, old_createMetadataMethodsForProperty(r, d, u, p))); + } finally { + p.v = !0; + } + } + function old_assertNotFinished(e, t) { + if (e.v) throw new Error("attempted to call " + t + " after decoration was finished"); + } + function old_assertMetadataKey(e) { + if ("symbol" != typeof e) throw new TypeError("Metadata keys must be symbols, received: " + e); + } + function old_assertCallable(e, t) { + if ("function" != typeof e) throw new TypeError(t + " must be a function"); + } + function old_assertValidReturnValue(e, t) { + var a = typeof t; + if (1 === e) { + if ("object" !== a || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); + void 0 !== t.get && old_assertCallable(t.get, "accessor.get"), void 0 !== t.set && old_assertCallable(t.set, "accessor.set"), void 0 !== t.init && old_assertCallable(t.init, "accessor.init"), void 0 !== t.initializer && old_assertCallable(t.initializer, "accessor.initializer"); + } else if ("function" !== a) { + var r; + throw r = 0 === e ? "field" : 10 === e ? "class" : "method", new TypeError(r + " decorators must return a function or void 0"); + } + } + function old_getInit(e) { + var t; + return null == (t = e.init) && (t = e.initializer) && "undefined" != typeof console && console.warn(".initializer has been renamed to .init as of March 2022"), t; + } + function old_applyMemberDec(e, t, a, r, o, i, n, l, s) { + var c, + d, + u, + f, + p, + v, + h = a[0]; + if (n ? c = 0 === o || 1 === o ? { + get: a[3], + set: a[4] + } : 3 === o ? { + get: a[3] + } : 4 === o ? { + set: a[3] + } : { + value: a[3] + } : 0 !== o && (c = Object.getOwnPropertyDescriptor(t, r)), 1 === o ? u = { + get: c.get, + set: c.set + } : 2 === o ? u = c.value : 3 === o ? u = c.get : 4 === o && (u = c.set), "function" == typeof h) void 0 !== (f = old_memberDec(h, r, c, l, s, o, i, n, u)) && (old_assertValidReturnValue(o, f), 0 === o ? d = f : 1 === o ? (d = old_getInit(f), p = f.get || u.get, v = f.set || u.set, u = { + get: p, + set: v + }) : u = f);else for (var y = h.length - 1; y >= 0; y--) { + var b; + if (void 0 !== (f = old_memberDec(h[y], r, c, l, s, o, i, n, u))) old_assertValidReturnValue(o, f), 0 === o ? b = f : 1 === o ? (b = old_getInit(f), p = f.get || u.get, v = f.set || u.set, u = { + get: p, + set: v + }) : u = f, void 0 !== b && (void 0 === d ? d = b : "function" == typeof d ? d = [d, b] : d.push(b)); + } + if (0 === o || 1 === o) { + if (void 0 === d) d = function (e, t) { + return t; + };else if ("function" != typeof d) { + var g = d; + d = function (e, t) { + for (var a = t, r = 0; r < g.length; r++) a = g[r].call(e, a); + return a; + }; + } else { + var m = d; + d = function (e, t) { + return m.call(e, t); + }; + } + e.push(d); + } + 0 !== o && (1 === o ? (c.get = u.get, c.set = u.set) : 2 === o ? c.value = u : 3 === o ? c.get = u : 4 === o && (c.set = u), n ? 1 === o ? (e.push(function (e, t) { + return u.get.call(e, t); + }), e.push(function (e, t) { + return u.set.call(e, t); + })) : 2 === o ? e.push(u) : e.push(function (e, t) { + return u.call(e, t); + }) : Object.defineProperty(t, r, c)); + } + function old_applyMemberDecs(e, t, a, r, o) { + for (var i, n, l = new Map(), s = new Map(), c = 0; c < o.length; c++) { + var d = o[c]; + if (Array.isArray(d)) { + var u, + f, + p, + v = d[1], + h = d[2], + y = d.length > 3, + b = v >= 5; + if (b ? (u = t, f = r, 0 !== (v -= 5) && (p = n = n || [])) : (u = t.prototype, f = a, 0 !== v && (p = i = i || [])), 0 !== v && !y) { + var g = b ? s : l, + m = g.get(h) || 0; + if (!0 === m || 3 === m && 4 !== v || 4 === m && 3 !== v) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h); + !m && v > 2 ? g.set(h, v) : g.set(h, !0); + } + old_applyMemberDec(e, u, d, h, v, b, y, f, p); + } + } + old_pushInitializers(e, i), old_pushInitializers(e, n); + } + function old_pushInitializers(e, t) { + t && e.push(function (e) { + for (var a = 0; a < t.length; a++) t[a].call(e); + return e; + }); + } + function old_applyClassDecs(e, t, a, r) { + if (r.length > 0) { + for (var o = [], i = t, n = t.name, l = r.length - 1; l >= 0; l--) { + var s = { + v: !1 + }; + try { + var c = Object.assign({ + kind: "class", + name: n, + addInitializer: old_createAddInitializerMethod(o, s) + }, old_createMetadataMethodsForProperty(a, 0, n, s)), + d = r[l](i, c); + } finally { + s.v = !0; + } + void 0 !== d && (old_assertValidReturnValue(10, d), i = d); + } + e.push(i, function () { + for (var e = 0; e < o.length; e++) o[e].call(i); + }); + } + } + function _applyDecs(e, t, a) { + var r = [], + o = {}, + i = {}; + return old_applyMemberDecs(r, e, i, o, t), old_convertMetadataMapToFinal(e.prototype, i), old_applyClassDecs(r, e, o, a), old_convertMetadataMapToFinal(e, o), r; + } + function applyDecs2203Factory() { + function createAddInitializerMethod(e, t) { + return function (r) { + !function (e, t) { + if (e.v) throw new Error("attempted to call " + t + " after decoration was finished"); + }(t, "addInitializer"), assertCallable(r, "An initializer"), e.push(r); + }; + } + function memberDec(e, t, r, a, n, i, s, o) { + var c; + switch (n) { + case 1: + c = "accessor"; + break; + case 2: + c = "method"; + break; + case 3: + c = "getter"; + break; + case 4: + c = "setter"; + break; + default: + c = "field"; + } + var l, + u, + f = { + kind: c, + name: s ? "#" + t : t, + static: i, + private: s + }, + p = { + v: !1 + }; + 0 !== n && (f.addInitializer = createAddInitializerMethod(a, p)), 0 === n ? s ? (l = r.get, u = r.set) : (l = function () { + return this[t]; + }, u = function (e) { + this[t] = e; + }) : 2 === n ? l = function () { + return r.value; + } : (1 !== n && 3 !== n || (l = function () { + return r.get.call(this); + }), 1 !== n && 4 !== n || (u = function (e) { + r.set.call(this, e); + })), f.access = l && u ? { + get: l, + set: u + } : l ? { + get: l + } : { + set: u + }; + try { + return e(o, f); + } finally { + p.v = !0; + } + } + function assertCallable(e, t) { + if ("function" != typeof e) throw new TypeError(t + " must be a function"); + } + function assertValidReturnValue(e, t) { + var r = typeof t; + if (1 === e) { + if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); + void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init"); + } else if ("function" !== r) { + var a; + throw a = 0 === e ? "field" : 10 === e ? "class" : "method", new TypeError(a + " decorators must return a function or void 0"); + } + } + function applyMemberDec(e, t, r, a, n, i, s, o) { + var c, + l, + u, + f, + p, + d, + h = r[0]; + if (s ? c = 0 === n || 1 === n ? { + get: r[3], + set: r[4] + } : 3 === n ? { + get: r[3] + } : 4 === n ? { + set: r[3] + } : { + value: r[3] + } : 0 !== n && (c = Object.getOwnPropertyDescriptor(t, a)), 1 === n ? u = { + get: c.get, + set: c.set + } : 2 === n ? u = c.value : 3 === n ? u = c.get : 4 === n && (u = c.set), "function" == typeof h) void 0 !== (f = memberDec(h, a, c, o, n, i, s, u)) && (assertValidReturnValue(n, f), 0 === n ? l = f : 1 === n ? (l = f.init, p = f.get || u.get, d = f.set || u.set, u = { + get: p, + set: d + }) : u = f);else for (var v = h.length - 1; v >= 0; v--) { + var g; + if (void 0 !== (f = memberDec(h[v], a, c, o, n, i, s, u))) assertValidReturnValue(n, f), 0 === n ? g = f : 1 === n ? (g = f.init, p = f.get || u.get, d = f.set || u.set, u = { + get: p, + set: d + }) : u = f, void 0 !== g && (void 0 === l ? l = g : "function" == typeof l ? l = [l, g] : l.push(g)); + } + if (0 === n || 1 === n) { + if (void 0 === l) l = function (e, t) { + return t; + };else if ("function" != typeof l) { + var y = l; + l = function (e, t) { + for (var r = t, a = 0; a < y.length; a++) r = y[a].call(e, r); + return r; + }; + } else { + var m = l; + l = function (e, t) { + return m.call(e, t); + }; + } + e.push(l); + } + 0 !== n && (1 === n ? (c.get = u.get, c.set = u.set) : 2 === n ? c.value = u : 3 === n ? c.get = u : 4 === n && (c.set = u), s ? 1 === n ? (e.push(function (e, t) { + return u.get.call(e, t); + }), e.push(function (e, t) { + return u.set.call(e, t); + })) : 2 === n ? e.push(u) : e.push(function (e, t) { + return u.call(e, t); + }) : Object.defineProperty(t, a, c)); + } + function pushInitializers(e, t) { + t && e.push(function (e) { + for (var r = 0; r < t.length; r++) t[r].call(e); + return e; + }); + } + return function (e, t, r) { + var a = []; + return function (e, t, r) { + for (var a, n, i = new Map(), s = new Map(), o = 0; o < r.length; o++) { + var c = r[o]; + if (Array.isArray(c)) { + var l, + u, + f = c[1], + p = c[2], + d = c.length > 3, + h = f >= 5; + if (h ? (l = t, 0 != (f -= 5) && (u = n = n || [])) : (l = t.prototype, 0 !== f && (u = a = a || [])), 0 !== f && !d) { + var v = h ? s : i, + g = v.get(p) || 0; + if (!0 === g || 3 === g && 4 !== f || 4 === g && 3 !== f) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + p); + !g && f > 2 ? v.set(p, f) : v.set(p, !0); + } + applyMemberDec(e, l, c, p, f, h, d, u); + } + } + pushInitializers(e, a), pushInitializers(e, n); + }(a, e, t), function (e, t, r) { + if (r.length > 0) { + for (var a = [], n = t, i = t.name, s = r.length - 1; s >= 0; s--) { + var o = { + v: !1 + }; + try { + var c = r[s](n, { + kind: "class", + name: i, + addInitializer: createAddInitializerMethod(a, o) + }); + } finally { + o.v = !0; + } + void 0 !== c && (assertValidReturnValue(10, c), n = c); + } + e.push(n, function () { + for (var e = 0; e < a.length; e++) a[e].call(n); + }); + } + }(a, e, r), a; + }; + } + var applyDecs2203Impl; + function _applyDecs2203(e, t, r) { + return (applyDecs2203Impl = applyDecs2203Impl || applyDecs2203Factory())(e, t, r); + } + function applyDecs2203RFactory() { + function createAddInitializerMethod(e, t) { + return function (r) { + !function (e, t) { + if (e.v) throw new Error("attempted to call " + t + " after decoration was finished"); + }(t, "addInitializer"), assertCallable(r, "An initializer"), e.push(r); + }; + } + function memberDec(e, t, r, n, a, i, s, o) { + var c; + switch (a) { + case 1: + c = "accessor"; + break; + case 2: + c = "method"; + break; + case 3: + c = "getter"; + break; + case 4: + c = "setter"; + break; + default: + c = "field"; + } + var l, + u, + f = { + kind: c, + name: s ? "#" + t : t, + static: i, + private: s + }, + p = { + v: !1 + }; + 0 !== a && (f.addInitializer = createAddInitializerMethod(n, p)), 0 === a ? s ? (l = r.get, u = r.set) : (l = function () { + return this[t]; + }, u = function (e) { + this[t] = e; + }) : 2 === a ? l = function () { + return r.value; + } : (1 !== a && 3 !== a || (l = function () { + return r.get.call(this); + }), 1 !== a && 4 !== a || (u = function (e) { + r.set.call(this, e); + })), f.access = l && u ? { + get: l, + set: u + } : l ? { + get: l + } : { + set: u + }; + try { + return e(o, f); + } finally { + p.v = !0; + } + } + function assertCallable(e, t) { + if ("function" != typeof e) throw new TypeError(t + " must be a function"); + } + function assertValidReturnValue(e, t) { + var r = typeof t; + if (1 === e) { + if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); + void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init"); + } else if ("function" !== r) { + var n; + throw n = 0 === e ? "field" : 10 === e ? "class" : "method", new TypeError(n + " decorators must return a function or void 0"); + } + } + function applyMemberDec(e, t, r, n, a, i, s, o) { + var c, + l, + u, + f, + p, + d, + h = r[0]; + if (s ? c = 0 === a || 1 === a ? { + get: r[3], + set: r[4] + } : 3 === a ? { + get: r[3] + } : 4 === a ? { + set: r[3] + } : { + value: r[3] + } : 0 !== a && (c = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? u = { + get: c.get, + set: c.set + } : 2 === a ? u = c.value : 3 === a ? u = c.get : 4 === a && (u = c.set), "function" == typeof h) void 0 !== (f = memberDec(h, n, c, o, a, i, s, u)) && (assertValidReturnValue(a, f), 0 === a ? l = f : 1 === a ? (l = f.init, p = f.get || u.get, d = f.set || u.set, u = { + get: p, + set: d + }) : u = f);else for (var v = h.length - 1; v >= 0; v--) { + var g; + if (void 0 !== (f = memberDec(h[v], n, c, o, a, i, s, u))) assertValidReturnValue(a, f), 0 === a ? g = f : 1 === a ? (g = f.init, p = f.get || u.get, d = f.set || u.set, u = { + get: p, + set: d + }) : u = f, void 0 !== g && (void 0 === l ? l = g : "function" == typeof l ? l = [l, g] : l.push(g)); + } + if (0 === a || 1 === a) { + if (void 0 === l) l = function (e, t) { + return t; + };else if ("function" != typeof l) { + var y = l; + l = function (e, t) { + for (var r = t, n = 0; n < y.length; n++) r = y[n].call(e, r); + return r; + }; + } else { + var m = l; + l = function (e, t) { + return m.call(e, t); + }; + } + e.push(l); + } + 0 !== a && (1 === a ? (c.get = u.get, c.set = u.set) : 2 === a ? c.value = u : 3 === a ? c.get = u : 4 === a && (c.set = u), s ? 1 === a ? (e.push(function (e, t) { + return u.get.call(e, t); + }), e.push(function (e, t) { + return u.set.call(e, t); + })) : 2 === a ? e.push(u) : e.push(function (e, t) { + return u.call(e, t); + }) : Object.defineProperty(t, n, c)); + } + function applyMemberDecs(e, t) { + for (var r, n, a = [], i = new Map(), s = new Map(), o = 0; o < t.length; o++) { + var c = t[o]; + if (Array.isArray(c)) { + var l, + u, + f = c[1], + p = c[2], + d = c.length > 3, + h = f >= 5; + if (h ? (l = e, 0 !== (f -= 5) && (u = n = n || [])) : (l = e.prototype, 0 !== f && (u = r = r || [])), 0 !== f && !d) { + var v = h ? s : i, + g = v.get(p) || 0; + if (!0 === g || 3 === g && 4 !== f || 4 === g && 3 !== f) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + p); + !g && f > 2 ? v.set(p, f) : v.set(p, !0); + } + applyMemberDec(a, l, c, p, f, h, d, u); + } + } + return pushInitializers(a, r), pushInitializers(a, n), a; + } + function pushInitializers(e, t) { + t && e.push(function (e) { + for (var r = 0; r < t.length; r++) t[r].call(e); + return e; + }); + } + return function (e, t, r) { + return { + e: applyMemberDecs(e, t), + get c() { + return function (e, t) { + if (t.length > 0) { + for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) { + var s = { + v: !1 + }; + try { + var o = t[i](n, { + kind: "class", + name: a, + addInitializer: createAddInitializerMethod(r, s) + }); + } finally { + s.v = !0; + } + void 0 !== o && (assertValidReturnValue(10, o), n = o); + } + return [n, function () { + for (var e = 0; e < r.length; e++) r[e].call(n); + }]; + } + }(e, r); + } + }; + }; + } + function _applyDecs2203R(e, t, r) { + return (_applyDecs2203R = applyDecs2203RFactory())(e, t, r); + } + function applyDecs2301Factory() { + function createAddInitializerMethod(e, t) { + return function (r) { + !function (e, t) { + if (e.v) throw new Error("attempted to call " + t + " after decoration was finished"); + }(t, "addInitializer"), assertCallable(r, "An initializer"), e.push(r); + }; + } + function assertInstanceIfPrivate(e, t) { + if (!e(t)) throw new TypeError("Attempted to access private element on non-instance"); + } + function memberDec(e, t, r, n, a, i, s, o, c) { + var u; + switch (a) { + case 1: + u = "accessor"; + break; + case 2: + u = "method"; + break; + case 3: + u = "getter"; + break; + case 4: + u = "setter"; + break; + default: + u = "field"; + } + var l, + f, + p = { + kind: u, + name: s ? "#" + t : t, + static: i, + private: s + }, + d = { + v: !1 + }; + if (0 !== a && (p.addInitializer = createAddInitializerMethod(n, d)), s || 0 !== a && 2 !== a) { + if (2 === a) l = function (e) { + return assertInstanceIfPrivate(c, e), r.value; + };else { + var h = 0 === a || 1 === a; + (h || 3 === a) && (l = s ? function (e) { + return assertInstanceIfPrivate(c, e), r.get.call(e); + } : function (e) { + return r.get.call(e); + }), (h || 4 === a) && (f = s ? function (e, t) { + assertInstanceIfPrivate(c, e), r.set.call(e, t); + } : function (e, t) { + r.set.call(e, t); + }); + } + } else l = function (e) { + return e[t]; + }, 0 === a && (f = function (e, r) { + e[t] = r; + }); + var v = s ? c.bind() : function (e) { + return t in e; + }; + p.access = l && f ? { + get: l, + set: f, + has: v + } : l ? { + get: l, + has: v + } : { + set: f, + has: v + }; + try { + return e(o, p); + } finally { + d.v = !0; + } + } + function assertCallable(e, t) { + if ("function" != typeof e) throw new TypeError(t + " must be a function"); + } + function assertValidReturnValue(e, t) { + var r = typeof t; + if (1 === e) { + if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); + void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init"); + } else if ("function" !== r) { + var n; + throw n = 0 === e ? "field" : 10 === e ? "class" : "method", new TypeError(n + " decorators must return a function or void 0"); + } + } + function curryThis2(e) { + return function (t) { + e(this, t); + }; + } + function applyMemberDec(e, t, r, n, a, i, s, o, c) { + var u, + l, + f, + p, + d, + h, + v, + g = r[0]; + if (s ? u = 0 === a || 1 === a ? { + get: (p = r[3], function () { + return p(this); + }), + set: curryThis2(r[4]) + } : 3 === a ? { + get: r[3] + } : 4 === a ? { + set: r[3] + } : { + value: r[3] + } : 0 !== a && (u = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? f = { + get: u.get, + set: u.set + } : 2 === a ? f = u.value : 3 === a ? f = u.get : 4 === a && (f = u.set), "function" == typeof g) void 0 !== (d = memberDec(g, n, u, o, a, i, s, f, c)) && (assertValidReturnValue(a, d), 0 === a ? l = d : 1 === a ? (l = d.init, h = d.get || f.get, v = d.set || f.set, f = { + get: h, + set: v + }) : f = d);else for (var y = g.length - 1; y >= 0; y--) { + var m; + if (void 0 !== (d = memberDec(g[y], n, u, o, a, i, s, f, c))) assertValidReturnValue(a, d), 0 === a ? m = d : 1 === a ? (m = d.init, h = d.get || f.get, v = d.set || f.set, f = { + get: h, + set: v + }) : f = d, void 0 !== m && (void 0 === l ? l = m : "function" == typeof l ? l = [l, m] : l.push(m)); + } + if (0 === a || 1 === a) { + if (void 0 === l) l = function (e, t) { + return t; + };else if ("function" != typeof l) { + var b = l; + l = function (e, t) { + for (var r = t, n = 0; n < b.length; n++) r = b[n].call(e, r); + return r; + }; + } else { + var I = l; + l = function (e, t) { + return I.call(e, t); + }; + } + e.push(l); + } + 0 !== a && (1 === a ? (u.get = f.get, u.set = f.set) : 2 === a ? u.value = f : 3 === a ? u.get = f : 4 === a && (u.set = f), s ? 1 === a ? (e.push(function (e, t) { + return f.get.call(e, t); + }), e.push(function (e, t) { + return f.set.call(e, t); + })) : 2 === a ? e.push(f) : e.push(function (e, t) { + return f.call(e, t); + }) : Object.defineProperty(t, n, u)); + } + function applyMemberDecs(e, t, r) { + for (var n, a, i, s = [], o = new Map(), c = new Map(), u = 0; u < t.length; u++) { + var l = t[u]; + if (Array.isArray(l)) { + var f, + p, + d = l[1], + h = l[2], + v = l.length > 3, + g = d >= 5, + y = r; + if (g ? (f = e, 0 !== (d -= 5) && (p = a = a || []), v && !i && (i = function (t) { + return _checkInRHS(t) === e; + }), y = i) : (f = e.prototype, 0 !== d && (p = n = n || [])), 0 !== d && !v) { + var m = g ? c : o, + b = m.get(h) || 0; + if (!0 === b || 3 === b && 4 !== d || 4 === b && 3 !== d) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h); + !b && d > 2 ? m.set(h, d) : m.set(h, !0); + } + applyMemberDec(s, f, l, h, d, g, v, p, y); + } + } + return pushInitializers(s, n), pushInitializers(s, a), s; + } + function pushInitializers(e, t) { + t && e.push(function (e) { + for (var r = 0; r < t.length; r++) t[r].call(e); + return e; + }); + } + return function (e, t, r, n) { + return { + e: applyMemberDecs(e, t, n), + get c() { + return function (e, t) { + if (t.length > 0) { + for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) { + var s = { + v: !1 + }; + try { + var o = t[i](n, { + kind: "class", + name: a, + addInitializer: createAddInitializerMethod(r, s) + }); + } finally { + s.v = !0; + } + void 0 !== o && (assertValidReturnValue(10, o), n = o); + } + return [n, function () { + for (var e = 0; e < r.length; e++) r[e].call(n); + }]; + } + }(e, r); + } + }; + }; + } + function _applyDecs2301(e, t, r, n) { + return (_applyDecs2301 = applyDecs2301Factory())(e, t, r, n); + } + function createAddInitializerMethod(e, t) { + return function (r) { + assertNotFinished(t, "addInitializer"), assertCallable(r, "An initializer"), e.push(r); + }; + } + function assertInstanceIfPrivate(e, t) { + if (!e(t)) throw new TypeError("Attempted to access private element on non-instance"); + } + function memberDec(e, t, r, a, n, i, s, o, c, l, u) { + var f; + switch (i) { + case 1: + f = "accessor"; + break; + case 2: + f = "method"; + break; + case 3: + f = "getter"; + break; + case 4: + f = "setter"; + break; + default: + f = "field"; + } + var d, + p, + h = { + kind: f, + name: o ? "#" + r : r, + static: s, + private: o, + metadata: u + }, + v = { + v: !1 + }; + if (0 !== i && (h.addInitializer = createAddInitializerMethod(n, v)), o || 0 !== i && 2 !== i) { + if (2 === i) d = function (e) { + return assertInstanceIfPrivate(l, e), a.value; + };else { + var y = 0 === i || 1 === i; + (y || 3 === i) && (d = o ? function (e) { + return assertInstanceIfPrivate(l, e), a.get.call(e); + } : function (e) { + return a.get.call(e); + }), (y || 4 === i) && (p = o ? function (e, t) { + assertInstanceIfPrivate(l, e), a.set.call(e, t); + } : function (e, t) { + a.set.call(e, t); + }); + } + } else d = function (e) { + return e[r]; + }, 0 === i && (p = function (e, t) { + e[r] = t; + }); + var m = o ? l.bind() : function (e) { + return r in e; + }; + h.access = d && p ? { + get: d, + set: p, + has: m + } : d ? { + get: d, + has: m + } : { + set: p, + has: m + }; + try { + return e.call(t, c, h); + } finally { + v.v = !0; + } + } + function assertNotFinished(e, t) { + if (e.v) throw new Error("attempted to call " + t + " after decoration was finished"); + } + function assertCallable(e, t) { + if ("function" != typeof e) throw new TypeError(t + " must be a function"); + } + function assertValidReturnValue(e, t) { + var r = typeof t; + if (1 === e) { + if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); + void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init"); + } else if ("function" !== r) { + var a; + throw a = 0 === e ? "field" : 5 === e ? "class" : "method", new TypeError(a + " decorators must return a function or void 0"); + } + } + function curryThis1(e) { + return function () { + return e(this); + }; + } + function curryThis2(e) { + return function (t) { + e(this, t); + }; + } + function applyMemberDec(e, t, r, a, n, i, s, o, c, l, u) { + var f, + d, + p, + h, + v, + y, + m = r[0]; + a || Array.isArray(m) || (m = [m]), o ? f = 0 === i || 1 === i ? { + get: curryThis1(r[3]), + set: curryThis2(r[4]) + } : 3 === i ? { + get: r[3] + } : 4 === i ? { + set: r[3] + } : { + value: r[3] + } : 0 !== i && (f = Object.getOwnPropertyDescriptor(t, n)), 1 === i ? p = { + get: f.get, + set: f.set + } : 2 === i ? p = f.value : 3 === i ? p = f.get : 4 === i && (p = f.set); + for (var g = a ? 2 : 1, b = m.length - 1; b >= 0; b -= g) { + var I; + if (void 0 !== (h = memberDec(m[b], a ? m[b - 1] : void 0, n, f, c, i, s, o, p, l, u))) assertValidReturnValue(i, h), 0 === i ? I = h : 1 === i ? (I = h.init, v = h.get || p.get, y = h.set || p.set, p = { + get: v, + set: y + }) : p = h, void 0 !== I && (void 0 === d ? d = I : "function" == typeof d ? d = [d, I] : d.push(I)); + } + if (0 === i || 1 === i) { + if (void 0 === d) d = function (e, t) { + return t; + };else if ("function" != typeof d) { + var w = d; + d = function (e, t) { + for (var r = t, a = w.length - 1; a >= 0; a--) r = w[a].call(e, r); + return r; + }; + } else { + var M = d; + d = function (e, t) { + return M.call(e, t); + }; + } + e.push(d); + } + 0 !== i && (1 === i ? (f.get = p.get, f.set = p.set) : 2 === i ? f.value = p : 3 === i ? f.get = p : 4 === i && (f.set = p), o ? 1 === i ? (e.push(function (e, t) { + return p.get.call(e, t); + }), e.push(function (e, t) { + return p.set.call(e, t); + })) : 2 === i ? e.push(p) : e.push(function (e, t) { + return p.call(e, t); + }) : Object.defineProperty(t, n, f)); + } + function applyMemberDecs(e, t, r, a) { + for (var n, i, s, o = [], c = new Map(), l = new Map(), u = 0; u < t.length; u++) { + var f = t[u]; + if (Array.isArray(f)) { + var d, + p, + h = f[1], + v = f[2], + y = f.length > 3, + m = 16 & h, + g = !!(8 & h), + b = r; + if (h &= 7, g ? (d = e, 0 !== h && (p = i = i || []), y && !s && (s = function (t) { + return _checkInRHS(t) === e; + }), b = s) : (d = e.prototype, 0 !== h && (p = n = n || [])), 0 !== h && !y) { + var I = g ? l : c, + w = I.get(v) || 0; + if (!0 === w || 3 === w && 4 !== h || 4 === w && 3 !== h) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + v); + I.set(v, !(!w && h > 2) || h); + } + applyMemberDec(o, d, f, m, v, h, g, y, p, b, a); + } + } + return pushInitializers(o, n), pushInitializers(o, i), o; + } + function pushInitializers(e, t) { + t && e.push(function (e) { + for (var r = 0; r < t.length; r++) t[r].call(e); + return e; + }); + } + function applyClassDecs(e, t, r, a) { + if (t.length) { + for (var n = [], i = e, s = e.name, o = r ? 2 : 1, c = t.length - 1; c >= 0; c -= o) { + var l = { + v: !1 + }; + try { + var u = t[c].call(r ? t[c - 1] : void 0, i, { + kind: "class", + name: s, + addInitializer: createAddInitializerMethod(n, l), + metadata: a + }); + } finally { + l.v = !0; + } + void 0 !== u && (assertValidReturnValue(5, u), i = u); + } + return [defineMetadata(i, a), function () { + for (var e = 0; e < n.length; e++) n[e].call(i); + }]; + } + } + function defineMetadata(e, t) { + return Object.defineProperty(e, Symbol.metadata || Symbol.for("Symbol.metadata"), { + configurable: !0, + enumerable: !0, + value: t + }); + } + function _applyDecs2305(e, t, r, a, n, i) { + if (arguments.length >= 6) var s = i[Symbol.metadata || Symbol.for("Symbol.metadata")]; + var o = Object.create(void 0 === s ? null : s), + c = applyMemberDecs(e, t, n, o); + return r.length || defineMetadata(e, o), { + e: c, + get c() { + return applyClassDecs(e, r, a, o); + } + }; + } + function _asyncGeneratorDelegate(t) { + var e = {}, + n = !1; + function pump(e, r) { + return n = !0, r = new Promise(function (n) { + n(t[e](r)); + }), { + done: !1, + value: new _OverloadYield(r, 1) + }; + } + return e["undefined" != typeof Symbol && Symbol.iterator || "@@iterator"] = function () { + return this; + }, e.next = function (t) { + return n ? (n = !1, t) : pump("next", t); + }, "function" == typeof t.throw && (e.throw = function (t) { + if (n) throw n = !1, t; + return pump("throw", t); + }), "function" == typeof t.return && (e.return = function (t) { + return n ? (n = !1, t) : pump("return", t); + }), e; + } + function _asyncIterator(r) { + var n, + t, + o, + e = 2; + for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) { + if (t && null != (n = r[t])) return n.call(r); + if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r)); + t = "@@asyncIterator", o = "@@iterator"; + } + throw new TypeError("Object is not async iterable"); + } + function AsyncFromSyncIterator(r) { + function AsyncFromSyncIteratorContinuation(r) { + if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); + var n = r.done; + return Promise.resolve(r.value).then(function (r) { + return { + value: r, + done: n + }; + }); + } + return AsyncFromSyncIterator = function (r) { + this.s = r, this.n = r.next; + }, AsyncFromSyncIterator.prototype = { + s: null, + n: null, + next: function () { + return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); + }, + return: function (r) { + var n = this.s.return; + return void 0 === n ? Promise.resolve({ + value: r, + done: !0 + }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); + }, + throw: function (r) { + var n = this.s.return; + return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); + } + }, new AsyncFromSyncIterator(r); + } + function _awaitAsyncGenerator(e) { + return new _OverloadYield(e, 0); + } + function _checkInRHS(e) { + if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); + return e; + } + function _defineAccessor(e, r, n, t) { + var c = { + configurable: !0, + enumerable: !0 + }; + return c[e] = t, Object.defineProperty(r, n, c); + } + function dispose_SuppressedError(r, e) { + return "undefined" != typeof SuppressedError ? dispose_SuppressedError = SuppressedError : (dispose_SuppressedError = function (r, e) { + this.suppressed = r, this.error = e, this.stack = new Error().stack; + }, dispose_SuppressedError.prototype = Object.create(Error.prototype, { + constructor: { + value: dispose_SuppressedError, + writable: !0, + configurable: !0 + } + })), new dispose_SuppressedError(r, e); + } + function _dispose(r, e, s) { + function next() { + for (; r.length > 0;) try { + var o = r.pop(), + p = o.d.call(o.v); + if (o.a) return Promise.resolve(p).then(next, err); + } catch (r) { + return err(r); + } + if (s) throw e; + } + function err(r) { + return e = s ? new dispose_SuppressedError(r, e) : r, s = !0, next(); + } + return next(); + } + function _importDeferProxy(e) { + var t = null, + constValue = function (e) { + return function () { + return e; + }; + }, + proxy = function (r) { + return function (n, o, f) { + return null === t && (t = e()), r(t, o, f); + }; + }; + return new Proxy({}, { + defineProperty: constValue(!1), + deleteProperty: constValue(!1), + get: proxy(Reflect.get), + getOwnPropertyDescriptor: proxy(Reflect.getOwnPropertyDescriptor), + getPrototypeOf: constValue(null), + isExtensible: constValue(!1), + has: proxy(Reflect.has), + ownKeys: proxy(Reflect.ownKeys), + preventExtensions: constValue(!0), + set: constValue(!1), + setPrototypeOf: constValue(!1) + }); + } + 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 = !0, + o = !1; + try { + if (i = (t = t.call(r)).next, 0 === l) { + if (Object(t) !== t) return; + f = !1; + } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); + } catch (r) { + o = !0, n = r; + } finally { + try { + if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; + } finally { + if (o) throw n; + } + } + return a; + } + } + function _iterableToArrayLimitLoose(e, r) { + var t = e && ("undefined" != typeof Symbol && e[Symbol.iterator] || e["@@iterator"]); + if (null != t) { + var o, + l = []; + for (t = t.call(e); e.length < r && !(o = t.next()).done;) l.push(o.value); + return l; + } + } + var REACT_ELEMENT_TYPE; + function _jsx(e, r, E, l) { + REACT_ELEMENT_TYPE || (REACT_ELEMENT_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103); + var o = e && e.defaultProps, + n = arguments.length - 3; + if (r || 0 === n || (r = { + children: void 0 + }), 1 === n) r.children = l;else if (n > 1) { + for (var t = new Array(n), f = 0; f < n; f++) t[f] = arguments[f + 3]; + r.children = t; + } + if (r && o) for (var i in o) void 0 === r[i] && (r[i] = o[i]);else r || (r = o || {}); + return { + $$typeof: REACT_ELEMENT_TYPE, + type: e, + key: void 0 === E ? null : "" + E, + ref: null, + props: r, + _owner: null + }; + } + function ownKeys(e, r) { + var t = Object.keys(e); + if (Object.getOwnPropertySymbols) { + var o = Object.getOwnPropertySymbols(e); + r && (o = o.filter(function (r) { + return Object.getOwnPropertyDescriptor(e, r).enumerable; + })), t.push.apply(t, o); + } + return t; + } + function _objectSpread2(e) { + for (var r = 1; r < arguments.length; r++) { + var t = null != arguments[r] ? arguments[r] : {}; + r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { + _defineProperty(e, r, t[r]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { + Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); + }); + } + return e; + } + function _regeneratorRuntime() { + "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ + _regeneratorRuntime = function () { + return e; + }; + var t, + e = {}, + r = Object.prototype, + n = r.hasOwnProperty, + o = Object.defineProperty || function (t, e, r) { + t[e] = r.value; + }, + i = "function" == typeof Symbol ? Symbol : {}, + a = i.iterator || "@@iterator", + c = i.asyncIterator || "@@asyncIterator", + u = i.toStringTag || "@@toStringTag"; + function define(t, e, r) { + return Object.defineProperty(t, e, { + value: r, + enumerable: !0, + configurable: !0, + writable: !0 + }), t[e]; + } + try { + define({}, ""); + } catch (t) { + define = function (t, e, r) { + return t[e] = r; + }; + } + function wrap(t, e, r, n) { + var i = e && e.prototype instanceof Generator ? e : Generator, + a = Object.create(i.prototype), + c = new Context(n || []); + return o(a, "_invoke", { + value: makeInvokeMethod(t, r, c) + }), a; + } + function tryCatch(t, e, r) { + try { + return { + type: "normal", + arg: t.call(e, r) + }; + } catch (t) { + return { + type: "throw", + arg: t + }; + } + } + e.wrap = wrap; + var h = "suspendedStart", + l = "suspendedYield", + f = "executing", + s = "completed", + y = {}; + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + var p = {}; + define(p, a, function () { + return this; + }); + var d = Object.getPrototypeOf, + v = d && d(d(values([]))); + v && v !== r && n.call(v, a) && (p = v); + var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); + function defineIteratorMethods(t) { + ["next", "throw", "return"].forEach(function (e) { + define(t, e, function (t) { + return this._invoke(e, t); + }); + }); + } + function AsyncIterator(t, e) { + function invoke(r, o, i, a) { + var c = tryCatch(t[r], t, o); + if ("throw" !== c.type) { + var u = c.arg, + h = u.value; + return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { + invoke("next", t, i, a); + }, function (t) { + invoke("throw", t, i, a); + }) : e.resolve(h).then(function (t) { + u.value = t, i(u); + }, function (t) { + return invoke("throw", t, i, a); + }); + } + a(c.arg); + } + var r; + o(this, "_invoke", { + value: function (t, n) { + function callInvokeWithMethodAndArg() { + return new e(function (e, r) { + invoke(t, n, e, r); + }); + } + return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); + } + }); + } + function makeInvokeMethod(e, r, n) { + var o = h; + return function (i, a) { + if (o === f) throw new Error("Generator is already running"); + if (o === s) { + if ("throw" === i) throw a; + return { + value: t, + done: !0 + }; + } + for (n.method = i, n.arg = a;;) { + var c = n.delegate; + if (c) { + var u = maybeInvokeDelegate(c, n); + if (u) { + if (u === y) continue; + return u; + } + } + if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { + if (o === h) throw o = s, n.arg; + n.dispatchException(n.arg); + } else "return" === n.method && n.abrupt("return", n.arg); + o = f; + var p = tryCatch(e, r, n); + if ("normal" === p.type) { + if (o = n.done ? s : l, p.arg === y) continue; + return { + value: p.arg, + done: n.done + }; + } + "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); + } + }; + } + function maybeInvokeDelegate(e, r) { + var n = r.method, + o = e.iterator[n]; + if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; + var i = tryCatch(o, e.iterator, r.arg); + if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; + var a = i.arg; + return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); + } + function pushTryEntry(t) { + var e = { + tryLoc: t[0] + }; + 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); + } + function resetTryEntry(t) { + var e = t.completion || {}; + e.type = "normal", delete e.arg, t.completion = e; + } + function Context(t) { + this.tryEntries = [{ + tryLoc: "root" + }], t.forEach(pushTryEntry, this), this.reset(!0); + } + function values(e) { + if (e || "" === e) { + var r = e[a]; + if (r) return r.call(e); + if ("function" == typeof e.next) return e; + if (!isNaN(e.length)) { + var o = -1, + i = function next() { + for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; + return next.value = t, next.done = !0, next; + }; + return i.next = i; + } + } + throw new TypeError(typeof e + " is not iterable"); + } + return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { + value: GeneratorFunctionPrototype, + configurable: !0 + }), o(GeneratorFunctionPrototype, "constructor", { + value: GeneratorFunction, + configurable: !0 + }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { + var e = "function" == typeof t && t.constructor; + return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); + }, e.mark = function (t) { + return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; + }, e.awrap = function (t) { + return { + __await: t + }; + }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { + return this; + }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { + void 0 === i && (i = Promise); + var a = new AsyncIterator(wrap(t, r, n, o), i); + return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { + return t.done ? t.value : a.next(); + }); + }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { + return this; + }), define(g, "toString", function () { + return "[object Generator]"; + }), e.keys = function (t) { + var e = Object(t), + r = []; + for (var n in e) r.push(n); + return r.reverse(), function next() { + for (; r.length;) { + var t = r.pop(); + if (t in e) return next.value = t, next.done = !1, next; + } + return next.done = !0, next; + }; + }, e.values = values, Context.prototype = { + constructor: Context, + reset: function (e) { + if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); + }, + stop: function () { + this.done = !0; + var t = this.tryEntries[0].completion; + if ("throw" === t.type) throw t.arg; + return this.rval; + }, + dispatchException: function (e) { + if (this.done) throw e; + var r = this; + function handle(n, o) { + return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; + } + for (var o = this.tryEntries.length - 1; o >= 0; --o) { + var i = this.tryEntries[o], + a = i.completion; + if ("root" === i.tryLoc) return handle("end"); + if (i.tryLoc <= this.prev) { + var c = n.call(i, "catchLoc"), + u = n.call(i, "finallyLoc"); + if (c && u) { + if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); + if (this.prev < i.finallyLoc) return handle(i.finallyLoc); + } else if (c) { + if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); + } else { + if (!u) throw new Error("try statement without catch or finally"); + if (this.prev < i.finallyLoc) return handle(i.finallyLoc); + } + } + } + }, + abrupt: function (t, e) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var o = this.tryEntries[r]; + if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { + var i = o; + break; + } + } + i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); + var a = i ? i.completion : {}; + return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); + }, + complete: function (t, e) { + if ("throw" === t.type) throw t.arg; + return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; + }, + finish: function (t) { + for (var e = this.tryEntries.length - 1; e >= 0; --e) { + var r = this.tryEntries[e]; + if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; + } + }, + catch: function (t) { + for (var e = this.tryEntries.length - 1; e >= 0; --e) { + var r = this.tryEntries[e]; + if (r.tryLoc === t) { + var n = r.completion; + if ("throw" === n.type) { + var o = n.arg; + resetTryEntry(r); + } + return o; + } + } + throw new Error("illegal catch attempt"); + }, + delegateYield: function (e, r, n) { + return this.delegate = { + iterator: values(e), + resultName: r, + nextLoc: n + }, "next" === this.method && (this.arg = t), y; + } + }, e; + } + function _typeof(o) { + "@babel/helpers - typeof"; + + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { + return typeof o; + } : function (o) { + return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; + }, _typeof(o); + } + function _using(o, e, n) { + if (null == e) return e; + if ("object" != typeof e) throw new TypeError("using declarations can only be used with objects, null, or undefined."); + if (n) var r = e[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")]; + if (null == r && (r = e[Symbol.dispose || Symbol.for("Symbol.dispose")]), "function" != typeof r) throw new TypeError("Property [Symbol.dispose] is not a function."); + return o.push({ + v: e, + d: r, + a: n + }), e; + } + function _wrapRegExp() { + _wrapRegExp = function (e, r) { + return new BabelRegExp(e, void 0, r); + }; + var e = RegExp.prototype, + r = new WeakMap(); + function BabelRegExp(e, t, p) { + var o = new RegExp(e, t); + return r.set(o, p || r.get(e)), _setPrototypeOf(o, BabelRegExp.prototype); + } + function buildGroups(e, t) { + var p = r.get(t); + return Object.keys(p).reduce(function (r, t) { + var o = p[t]; + if ("number" == typeof o) r[t] = e[o];else { + for (var i = 0; void 0 === e[o[i]] && i + 1 < o.length;) i++; + r[t] = e[o[i]]; + } + return r; + }, Object.create(null)); + } + return _inherits(BabelRegExp, RegExp), BabelRegExp.prototype.exec = function (r) { + var t = e.exec.call(this, r); + if (t) { + t.groups = buildGroups(t, this); + var p = t.indices; + p && (p.groups = buildGroups(p, this)); + } + return t; + }, BabelRegExp.prototype[Symbol.replace] = function (t, p) { + if ("string" == typeof p) { + var o = r.get(this); + return e[Symbol.replace].call(this, t, p.replace(/\$<([^>]+)>/g, function (e, r) { + var t = o[r]; + return "$" + (Array.isArray(t) ? t.join("$") : t); + })); + } + if ("function" == typeof p) { + var i = this; + return e[Symbol.replace].call(this, t, function () { + var e = arguments; + return "object" != typeof e[e.length - 1] && (e = [].slice.call(e)).push(buildGroups(e, i)), p.apply(this, e); + }); + } + return e[Symbol.replace].call(this, t, p); + }, _wrapRegExp.apply(this, arguments); + } + function _AwaitValue(value) { + this.wrapped = value; + } + function _wrapAsyncGenerator(fn) { + return function () { + return new _AsyncGenerator(fn.apply(this, arguments)); + }; + } + function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + function _asyncToGenerator(fn) { + return function () { + var self = this, + args = arguments; + return new Promise(function (resolve, reject) { + var gen = fn.apply(self, args); + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + _next(undefined); + }); + }; + } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); + return Constructor; + } + function _defineEnumerableProperties(obj, descs) { + for (var key in descs) { + var desc = descs[key]; + desc.configurable = desc.enumerable = true; + if ("value" in desc) desc.writable = true; + Object.defineProperty(obj, key, desc); + } + if (Object.getOwnPropertySymbols) { + var objectSymbols = Object.getOwnPropertySymbols(descs); + for (var i = 0; i < objectSymbols.length; i++) { + var sym = objectSymbols[i]; + var desc = descs[sym]; + desc.configurable = desc.enumerable = true; + if ("value" in desc) desc.writable = true; + Object.defineProperty(obj, sym, desc); + } + } + return obj; + } + function _defaults(obj, defaults) { + var keys = Object.getOwnPropertyNames(defaults); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var value = Object.getOwnPropertyDescriptor(defaults, key); + if (value && value.configurable && obj[key] === undefined) { + Object.defineProperty(obj, key, value); + } + } + return obj; + } + function _defineProperty(obj, key, value) { + key = _toPropertyKey(key); + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; + } + function _extends() { + _extends = Object.assign ? Object.assign.bind() : function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; + }; + return _extends.apply(this, arguments); + } + function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? Object(arguments[i]) : {}; + var ownKeys = Object.keys(source); + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + ownKeys.forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } + return target; + } + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + Object.defineProperty(subClass, "prototype", { + writable: false + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + _setPrototypeOf(subClass, superClass); + } + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + return _setPrototypeOf(o, p); + } + function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + function _construct(Parent, args, Class) { + if (_isNativeReflectConstruct()) { + _construct = Reflect.construct.bind(); + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + return _construct.apply(null, arguments); + } + function _isNativeFunction(fn) { + return Function.toString.call(fn).indexOf("[native code]") !== -1; + } + function _wrapNativeSuper(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + _wrapNativeSuper = function _wrapNativeSuper(Class) { + if (Class === null || !_isNativeFunction(Class)) return Class; + if (typeof Class !== "function") { + throw new TypeError("Super expression must either be null or a function"); + } + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + _cache.set(Class, Wrapper); + } + function Wrapper() { + return _construct(Class, arguments, _getPrototypeOf(this).constructor); + } + Wrapper.prototype = Object.create(Class.prototype, { + constructor: { + value: Wrapper, + enumerable: false, + writable: true, + configurable: true + } + }); + return _setPrototypeOf(Wrapper, Class); + }; + return _wrapNativeSuper(Class); + } + function _instanceof(left, right) { + if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { + return !!right[Symbol.hasInstance](left); + } else { + return left instanceof right; + } + } + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; + } + function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== "function") return null; + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + return (_getRequireWildcardCache = function (nodeInterop) { + return nodeInterop ? cacheNodeInterop : cacheBabelInterop; + })(nodeInterop); + } + function _interopRequireWildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) { + return obj; + } + if (obj === null || typeof obj !== "object" && typeof obj !== "function") { + return { + default: obj + }; + } + var cache = _getRequireWildcardCache(nodeInterop); + if (cache && cache.has(obj)) { + return cache.get(obj); + } + var newObj = {}; + var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var key in obj) { + if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + newObj.default = obj; + if (cache) { + cache.set(obj, newObj); + } + return newObj; + } + function _newArrowCheck(innerThis, boundThis) { + if (innerThis !== boundThis) { + throw new TypeError("Cannot instantiate an arrow function"); + } + } + function _objectDestructuringEmpty(obj) { + if (obj == null) throw new TypeError("Cannot destructure " + obj); + } + function _objectWithoutPropertiesLoose(source, excluded) { + if (source == null) return {}; + var target = {}; + var sourceKeys = Object.keys(source); + var key, i; + for (i = 0; i < sourceKeys.length; i++) { + key = sourceKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + target[key] = source[key]; + } + return target; + } + function _objectWithoutProperties(source, excluded) { + if (source == null) return {}; + var target = _objectWithoutPropertiesLoose(source, excluded); + var key, i; + if (Object.getOwnPropertySymbols) { + var sourceSymbolKeys = Object.getOwnPropertySymbols(source); + for (i = 0; i < sourceSymbolKeys.length; i++) { + key = sourceSymbolKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; + target[key] = source[key]; + } + } + return target; + } + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return self; + } + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } else if (call !== void 0) { + throw new TypeError("Derived constructors may only return object or undefined"); + } + return _assertThisInitialized(self); + } + function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + return _possibleConstructorReturn(this, result); + }; + } + function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + return object; + } + function _get() { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get.bind(); + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + if (desc.get) { + return desc.get.call(arguments.length < 3 ? target : receiver); + } + return desc.value; + }; + } + return _get.apply(this, arguments); + } + function set(target, property, value, receiver) { + if (typeof Reflect !== "undefined" && Reflect.set) { + set = Reflect.set; + } else { + set = function set(target, property, value, receiver) { + var base = _superPropBase(target, property); + var desc; + if (base) { + desc = Object.getOwnPropertyDescriptor(base, property); + if (desc.set) { + desc.set.call(receiver, value); + return true; + } else if (!desc.writable) { + return false; + } + } + desc = Object.getOwnPropertyDescriptor(receiver, property); + if (desc) { + if (!desc.writable) { + return false; + } + desc.value = value; + Object.defineProperty(receiver, property, desc); + } else { + _defineProperty(receiver, property, value); + } + return true; + }; + } + return set(target, property, value, receiver); + } + function _set(target, property, value, receiver, isStrict) { + var s = set(target, property, value, receiver || target); + if (!s && isStrict) { + throw new TypeError('failed to set property'); + } + return value; + } + function _taggedTemplateLiteral(strings, raw) { + if (!raw) { + raw = strings.slice(0); + } + return Object.freeze(Object.defineProperties(strings, { + raw: { + value: Object.freeze(raw) + } + })); + } + function _taggedTemplateLiteralLoose(strings, raw) { + if (!raw) { + raw = strings.slice(0); + } + strings.raw = raw; + return strings; + } + function _readOnlyError(name) { + throw new TypeError("\"" + name + "\" is read-only"); + } + function _writeOnlyError(name) { + throw new TypeError("\"" + name + "\" is write-only"); + } + function _classNameTDZError(name) { + throw new ReferenceError("Class \"" + name + "\" cannot be referenced in computed property keys."); + } + function _temporalUndefined() {} + function _tdz(name) { + throw new ReferenceError(name + " is not defined - temporal dead zone"); + } + function _temporalRef(val, name) { + return val === _temporalUndefined ? _tdz(name) : val; + } + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } + function _slicedToArrayLoose(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimitLoose(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } + function _toArray(arr) { + return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); + } + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + function _maybeArrayLike(next, arr, i) { + if (arr && !Array.isArray(arr) && typeof arr.length === "number") { + var len = arr.length; + return _arrayLikeToArray(arr, i !== void 0 && i < len ? i : len); + } + return next(arr, i); + } + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + 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 _createForOfIteratorHelper(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + if (!it) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + var F = function () {}; + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = it.call(o); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; + } + function _createForOfIteratorHelperLoose(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + if (it) return (it = it.call(o)).next.bind(it); + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + return function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }; + } + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _skipFirstGeneratorNext(fn) { + return function () { + var it = fn.apply(this, arguments); + it.next(); + return it; + }; + } + function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } + function _initializerWarningHelper(descriptor, context) { + throw new Error('Decorating class property failed. Please ensure that ' + 'transform-class-properties is enabled and runs after the decorators transform.'); + } + function _initializerDefineProperty(target, property, descriptor, context) { + if (!descriptor) return; + Object.defineProperty(target, property, { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: descriptor.writable, + value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 + }); + } + function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { + var desc = {}; + Object.keys(descriptor).forEach(function (key) { + desc[key] = descriptor[key]; + }); + desc.enumerable = !!desc.enumerable; + desc.configurable = !!desc.configurable; + if ('value' in desc || desc.initializer) { + desc.writable = true; + } + desc = decorators.slice().reverse().reduce(function (desc, decorator) { + return decorator(target, property, desc) || desc; + }, desc); + if (context && desc.initializer !== void 0) { + desc.value = desc.initializer ? desc.initializer.call(context) : void 0; + desc.initializer = undefined; + } + if (desc.initializer === void 0) { + Object.defineProperty(target, property, desc); + desc = null; + } + return desc; + } + var id$1 = 0; + function _classPrivateFieldLooseKey(name) { + return "__private_" + id$1++ + "_" + name; + } + function _classPrivateFieldLooseBase(receiver, privateKey) { + if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { + throw new TypeError("attempted to use private field on non-instance"); + } + return receiver; + } + function _classPrivateFieldGet(receiver, privateMap) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); + return _classApplyDescriptorGet(receiver, descriptor); + } + function _classPrivateFieldSet(receiver, privateMap, value) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); + _classApplyDescriptorSet(receiver, descriptor, value); + return value; + } + function _classPrivateFieldDestructureSet(receiver, privateMap) { + var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); + return _classApplyDescriptorDestructureSet(receiver, descriptor); + } + function _classExtractFieldDescriptor(receiver, privateMap, action) { + if (!privateMap.has(receiver)) { + throw new TypeError("attempted to " + action + " private field on non-instance"); + } + return privateMap.get(receiver); + } + function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + _classCheckPrivateStaticFieldDescriptor(descriptor, "get"); + return _classApplyDescriptorGet(receiver, descriptor); + } + function _classStaticPrivateFieldSpecSet(receiver, classConstructor, descriptor, value) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + _classCheckPrivateStaticFieldDescriptor(descriptor, "set"); + _classApplyDescriptorSet(receiver, descriptor, value); + return value; + } + function _classStaticPrivateMethodGet(receiver, classConstructor, method) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + return method; + } + function _classStaticPrivateMethodSet() { + throw new TypeError("attempted to set read only static private field"); + } + function _classApplyDescriptorGet(receiver, descriptor) { + if (descriptor.get) { + return descriptor.get.call(receiver); + } + return descriptor.value; + } + function _classApplyDescriptorSet(receiver, descriptor, value) { + if (descriptor.set) { + descriptor.set.call(receiver, value); + } else { + if (!descriptor.writable) { + throw new TypeError("attempted to set read only private field"); + } + descriptor.value = value; + } + } + function _classApplyDescriptorDestructureSet(receiver, descriptor) { + if (descriptor.set) { + if (!("__destrObj" in descriptor)) { + descriptor.__destrObj = { + set value(v) { + descriptor.set.call(receiver, v); + } + }; + } + return descriptor.__destrObj; + } else { + if (!descriptor.writable) { + throw new TypeError("attempted to set read only private field"); + } + return descriptor; + } + } + function _classStaticPrivateFieldDestructureSet(receiver, classConstructor, descriptor) { + _classCheckPrivateStaticAccess(receiver, classConstructor); + _classCheckPrivateStaticFieldDescriptor(descriptor, "set"); + return _classApplyDescriptorDestructureSet(receiver, descriptor); + } + function _classCheckPrivateStaticAccess(receiver, classConstructor) { + if (receiver !== classConstructor) { + throw new TypeError("Private static access of wrong provenance"); + } + } + function _classCheckPrivateStaticFieldDescriptor(descriptor, action) { + if (descriptor === undefined) { + throw new TypeError("attempted to " + action + " private static field before its declaration"); + } + } + function _decorate(decorators, factory, superClass, mixins) { + var api = _getDecoratorsApi(); + if (mixins) { + for (var i = 0; i < mixins.length; i++) { + api = mixins[i](api); + } + } + var r = factory(function initialize(O) { + api.initializeInstanceElements(O, decorated.elements); + }, superClass); + var decorated = api.decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators); + api.initializeClassElements(r.F, decorated.elements); + return api.runClassFinishers(r.F, decorated.finishers); + } + function _getDecoratorsApi() { + _getDecoratorsApi = function () { + return api; + }; + var api = { + elementsDefinitionOrder: [["method"], ["field"]], + initializeInstanceElements: function (O, elements) { + ["method", "field"].forEach(function (kind) { + elements.forEach(function (element) { + if (element.kind === kind && element.placement === "own") { + this.defineClassElement(O, element); + } + }, this); + }, this); + }, + initializeClassElements: function (F, elements) { + var proto = F.prototype; + ["method", "field"].forEach(function (kind) { + elements.forEach(function (element) { + var placement = element.placement; + if (element.kind === kind && (placement === "static" || placement === "prototype")) { + var receiver = placement === "static" ? F : proto; + this.defineClassElement(receiver, element); + } + }, this); + }, this); + }, + defineClassElement: function (receiver, element) { + var descriptor = element.descriptor; + if (element.kind === "field") { + var initializer = element.initializer; + descriptor = { + enumerable: descriptor.enumerable, + writable: descriptor.writable, + configurable: descriptor.configurable, + value: initializer === void 0 ? void 0 : initializer.call(receiver) + }; + } + Object.defineProperty(receiver, element.key, descriptor); + }, + decorateClass: function (elements, decorators) { + var newElements = []; + var finishers = []; + var placements = { + static: [], + prototype: [], + own: [] + }; + elements.forEach(function (element) { + this.addElementPlacement(element, placements); + }, this); + elements.forEach(function (element) { + if (!_hasDecorators(element)) return newElements.push(element); + var elementFinishersExtras = this.decorateElement(element, placements); + newElements.push(elementFinishersExtras.element); + newElements.push.apply(newElements, elementFinishersExtras.extras); + finishers.push.apply(finishers, elementFinishersExtras.finishers); + }, this); + if (!decorators) { + return { + elements: newElements, + finishers: finishers + }; + } + var result = this.decorateConstructor(newElements, decorators); + finishers.push.apply(finishers, result.finishers); + result.finishers = finishers; + return result; + }, + addElementPlacement: function (element, placements, silent) { + var keys = placements[element.placement]; + if (!silent && keys.indexOf(element.key) !== -1) { + throw new TypeError("Duplicated element (" + element.key + ")"); + } + keys.push(element.key); + }, + decorateElement: function (element, placements) { + var extras = []; + var finishers = []; + for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) { + var keys = placements[element.placement]; + keys.splice(keys.indexOf(element.key), 1); + var elementObject = this.fromElementDescriptor(element); + var elementFinisherExtras = this.toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject); + element = elementFinisherExtras.element; + this.addElementPlacement(element, placements); + if (elementFinisherExtras.finisher) { + finishers.push(elementFinisherExtras.finisher); + } + var newExtras = elementFinisherExtras.extras; + if (newExtras) { + for (var j = 0; j < newExtras.length; j++) { + this.addElementPlacement(newExtras[j], placements); + } + extras.push.apply(extras, newExtras); + } + } + return { + element: element, + finishers: finishers, + extras: extras + }; + }, + decorateConstructor: function (elements, decorators) { + var finishers = []; + for (var i = decorators.length - 1; i >= 0; i--) { + var obj = this.fromClassDescriptor(elements); + var elementsAndFinisher = this.toClassDescriptor((0, decorators[i])(obj) || obj); + if (elementsAndFinisher.finisher !== undefined) { + finishers.push(elementsAndFinisher.finisher); + } + if (elementsAndFinisher.elements !== undefined) { + elements = elementsAndFinisher.elements; + for (var j = 0; j < elements.length - 1; j++) { + for (var k = j + 1; k < elements.length; k++) { + if (elements[j].key === elements[k].key && elements[j].placement === elements[k].placement) { + throw new TypeError("Duplicated element (" + elements[j].key + ")"); + } + } + } + } + } + return { + elements: elements, + finishers: finishers + }; + }, + fromElementDescriptor: function (element) { + var obj = { + kind: element.kind, + key: element.key, + placement: element.placement, + descriptor: element.descriptor + }; + var desc = { + value: "Descriptor", + configurable: true + }; + Object.defineProperty(obj, Symbol.toStringTag, desc); + if (element.kind === "field") obj.initializer = element.initializer; + return obj; + }, + toElementDescriptors: function (elementObjects) { + if (elementObjects === undefined) return; + return _toArray(elementObjects).map(function (elementObject) { + var element = this.toElementDescriptor(elementObject); + this.disallowProperty(elementObject, "finisher", "An element descriptor"); + this.disallowProperty(elementObject, "extras", "An element descriptor"); + return element; + }, this); + }, + toElementDescriptor: function (elementObject) { + var kind = String(elementObject.kind); + if (kind !== "method" && kind !== "field") { + throw new TypeError('An element descriptor\'s .kind property must be either "method" or' + ' "field", but a decorator created an element descriptor with' + ' .kind "' + kind + '"'); + } + var key = _toPropertyKey(elementObject.key); + var placement = String(elementObject.placement); + if (placement !== "static" && placement !== "prototype" && placement !== "own") { + throw new TypeError('An element descriptor\'s .placement property must be one of "static",' + ' "prototype" or "own", but a decorator created an element descriptor' + ' with .placement "' + placement + '"'); + } + var descriptor = elementObject.descriptor; + this.disallowProperty(elementObject, "elements", "An element descriptor"); + var element = { + kind: kind, + key: key, + placement: placement, + descriptor: Object.assign({}, descriptor) + }; + if (kind !== "field") { + this.disallowProperty(elementObject, "initializer", "A method descriptor"); + } else { + this.disallowProperty(descriptor, "get", "The property descriptor of a field descriptor"); + this.disallowProperty(descriptor, "set", "The property descriptor of a field descriptor"); + this.disallowProperty(descriptor, "value", "The property descriptor of a field descriptor"); + element.initializer = elementObject.initializer; + } + return element; + }, + toElementFinisherExtras: function (elementObject) { + var element = this.toElementDescriptor(elementObject); + var finisher = _optionalCallableProperty(elementObject, "finisher"); + var extras = this.toElementDescriptors(elementObject.extras); + return { + element: element, + finisher: finisher, + extras: extras + }; + }, + fromClassDescriptor: function (elements) { + var obj = { + kind: "class", + elements: elements.map(this.fromElementDescriptor, this) + }; + var desc = { + value: "Descriptor", + configurable: true + }; + Object.defineProperty(obj, Symbol.toStringTag, desc); + return obj; + }, + toClassDescriptor: function (obj) { + var kind = String(obj.kind); + if (kind !== "class") { + throw new TypeError('A class descriptor\'s .kind property must be "class", but a decorator' + ' created a class descriptor with .kind "' + kind + '"'); + } + this.disallowProperty(obj, "key", "A class descriptor"); + this.disallowProperty(obj, "placement", "A class descriptor"); + this.disallowProperty(obj, "descriptor", "A class descriptor"); + this.disallowProperty(obj, "initializer", "A class descriptor"); + this.disallowProperty(obj, "extras", "A class descriptor"); + var finisher = _optionalCallableProperty(obj, "finisher"); + var elements = this.toElementDescriptors(obj.elements); + return { + elements: elements, + finisher: finisher + }; + }, + runClassFinishers: function (constructor, finishers) { + for (var i = 0; i < finishers.length; i++) { + var newConstructor = (0, finishers[i])(constructor); + if (newConstructor !== undefined) { + if (typeof newConstructor !== "function") { + throw new TypeError("Finishers must return a constructor."); + } + constructor = newConstructor; + } + } + return constructor; + }, + disallowProperty: function (obj, name, objectType) { + if (obj[name] !== undefined) { + throw new TypeError(objectType + " can't have a ." + name + " property."); + } + } + }; + return api; + } + function _createElementDescriptor(def) { + var key = _toPropertyKey(def.key); + var descriptor; + if (def.kind === "method") { + descriptor = { + value: def.value, + writable: true, + configurable: true, + enumerable: false + }; + } else if (def.kind === "get") { + descriptor = { + get: def.value, + configurable: true, + enumerable: false + }; + } else if (def.kind === "set") { + descriptor = { + set: def.value, + configurable: true, + enumerable: false + }; + } else if (def.kind === "field") { + descriptor = { + configurable: true, + writable: true, + enumerable: true + }; + } + var element = { + kind: def.kind === "field" ? "field" : "method", + key: key, + placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype", + descriptor: descriptor + }; + if (def.decorators) element.decorators = def.decorators; + if (def.kind === "field") element.initializer = def.value; + return element; + } + function _coalesceGetterSetter(element, other) { + if (element.descriptor.get !== undefined) { + other.descriptor.get = element.descriptor.get; + } else { + other.descriptor.set = element.descriptor.set; + } + } + function _coalesceClassElements(elements) { + var newElements = []; + var isSameElement = function (other) { + return other.kind === "method" && other.key === element.key && other.placement === element.placement; + }; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + var other; + if (element.kind === "method" && (other = newElements.find(isSameElement))) { + if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) { + if (_hasDecorators(element) || _hasDecorators(other)) { + throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated."); + } + other.descriptor = element.descriptor; + } else { + if (_hasDecorators(element)) { + if (_hasDecorators(other)) { + throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ")."); + } + other.decorators = element.decorators; + } + _coalesceGetterSetter(element, other); + } + } else { + newElements.push(element); + } + } + return newElements; + } + function _hasDecorators(element) { + return element.decorators && element.decorators.length; + } + function _isDataDescriptor(desc) { + return desc !== undefined && !(desc.value === undefined && desc.writable === undefined); + } + function _optionalCallableProperty(obj, name) { + var value = obj[name]; + if (value !== undefined && typeof value !== "function") { + throw new TypeError("Expected '" + name + "' to be a function"); + } + return value; + } + function _classPrivateMethodGet(receiver, privateSet, fn) { + if (!privateSet.has(receiver)) { + throw new TypeError("attempted to get private field on non-instance"); + } + return fn; + } + function _checkPrivateRedeclaration(obj, privateCollection) { + if (privateCollection.has(obj)) { + throw new TypeError("Cannot initialize the same private elements twice on an object"); + } + } + function _classPrivateFieldInitSpec(obj, privateMap, value) { + _checkPrivateRedeclaration(obj, privateMap); + privateMap.set(obj, value); + } + function _classPrivateMethodInitSpec(obj, privateSet) { + _checkPrivateRedeclaration(obj, privateSet); + privateSet.add(obj); + } + function _classPrivateMethodSet() { + throw new TypeError("attempted to reassign private method"); + } + function _identity(x) { + return x; + } + function _nullishReceiverError(r) { + throw new TypeError("Cannot set property of null or undefined."); + } + + class Piece extends TrixObject { + static registerType(type, constructor) { + constructor.type = type; + this.types[type] = constructor; + } + static fromJSON(pieceJSON) { + const constructor = this.types[pieceJSON.type]; + if (constructor) { + return constructor.fromJSON(pieceJSON); + } + } + constructor(value) { + let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + super(...arguments); + this.attributes = Hash.box(attributes); + } + copyWithAttributes(attributes) { + return new this.constructor(this.getValue(), attributes); + } + copyWithAdditionalAttributes(attributes) { + return this.copyWithAttributes(this.attributes.merge(attributes)); + } + copyWithoutAttribute(attribute) { + return this.copyWithAttributes(this.attributes.remove(attribute)); + } + copy() { + return this.copyWithAttributes(this.attributes); + } + getAttribute(attribute) { + return this.attributes.get(attribute); + } + getAttributesHash() { + return this.attributes; + } + getAttributes() { + return this.attributes.toObject(); + } + hasAttribute(attribute) { + return this.attributes.has(attribute); + } + hasSameStringValueAsPiece(piece) { + return piece && this.toString() === piece.toString(); + } + hasSameAttributesAsPiece(piece) { + return piece && (this.attributes === piece.attributes || this.attributes.isEqualTo(piece.attributes)); + } + isBlockBreak() { + return false; + } + isEqualTo(piece) { + return super.isEqualTo(...arguments) || this.hasSameConstructorAs(piece) && this.hasSameStringValueAsPiece(piece) && this.hasSameAttributesAsPiece(piece); + } + isEmpty() { + return this.length === 0; + } + isSerializable() { + return true; + } + toJSON() { + return { + type: this.constructor.type, + attributes: this.getAttributes() + }; + } + contentsForInspection() { + return { + type: this.constructor.type, + attributes: this.attributes.inspect() + }; + } + + // Grouping + + canBeGrouped() { + return this.hasAttribute("href"); + } + canBeGroupedWith(piece) { + return this.getAttribute("href") === piece.getAttribute("href"); + } + + // Splittable + + getLength() { + return this.length; + } + canBeConsolidatedWith(piece) { + return false; + } + } + _defineProperty(Piece, "types", {}); + + class ImagePreloadOperation extends Operation { + constructor(url) { + super(...arguments); + this.url = url; + } + perform(callback) { + const image = new Image(); + image.onload = () => { + image.width = this.width = image.naturalWidth; + image.height = this.height = image.naturalHeight; + return callback(true, image); + }; + image.onerror = () => callback(false); + image.src = this.url; + } + } + + class Attachment extends TrixObject { + static attachmentForFile(file) { + const attributes = this.attributesForFile(file); + const attachment = new this(attributes); + attachment.setFile(file); + return attachment; + } + static attributesForFile(file) { + return new Hash({ + filename: file.name, + filesize: file.size, + contentType: file.type + }); + } + static fromJSON(attachmentJSON) { + return new this(attachmentJSON); + } + constructor() { + let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + super(attributes); + this.releaseFile = this.releaseFile.bind(this); + this.attributes = Hash.box(attributes); + this.didChangeAttributes(); + } + getAttribute(attribute) { + return this.attributes.get(attribute); + } + hasAttribute(attribute) { + return this.attributes.has(attribute); + } + getAttributes() { + return this.attributes.toObject(); + } + setAttributes() { + let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + const newAttributes = this.attributes.merge(attributes); + if (!this.attributes.isEqualTo(newAttributes)) { + var _this$previewDelegate, _this$previewDelegate2, _this$delegate, _this$delegate$attach; + this.attributes = newAttributes; + this.didChangeAttributes(); + (_this$previewDelegate = this.previewDelegate) === null || _this$previewDelegate === void 0 || (_this$previewDelegate2 = _this$previewDelegate.attachmentDidChangeAttributes) === null || _this$previewDelegate2 === void 0 || _this$previewDelegate2.call(_this$previewDelegate, this); + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$attach = _this$delegate.attachmentDidChangeAttributes) === null || _this$delegate$attach === void 0 ? void 0 : _this$delegate$attach.call(_this$delegate, this); + } + } + didChangeAttributes() { + if (this.isPreviewable()) { + return this.preloadURL(); + } + } + isPending() { + return this.file != null && !(this.getURL() || this.getHref()); + } + isPreviewable() { + if (this.attributes.has("previewable")) { + return this.attributes.get("previewable"); + } else { + return Attachment.previewablePattern.test(this.getContentType()); + } + } + getType() { + if (this.hasContent()) { + return "content"; + } else if (this.isPreviewable()) { + return "preview"; + } else { + return "file"; + } + } + getURL() { + return this.attributes.get("url"); + } + getHref() { + return this.attributes.get("href"); + } + getFilename() { + return this.attributes.get("filename") || ""; + } + getFilesize() { + return this.attributes.get("filesize"); + } + getFormattedFilesize() { + const filesize = this.attributes.get("filesize"); + if (typeof filesize === "number") { + return file_size_formatting.formatter(filesize); + } else { + return ""; + } + } + getExtension() { + var _this$getFilename$mat; + return (_this$getFilename$mat = this.getFilename().match(/\.(\w+)$/)) === null || _this$getFilename$mat === void 0 ? void 0 : _this$getFilename$mat[1].toLowerCase(); + } + getContentType() { + return this.attributes.get("contentType"); + } + hasContent() { + return this.attributes.has("content"); + } + getContent() { + return this.attributes.get("content"); + } + getWidth() { + return this.attributes.get("width"); + } + getHeight() { + return this.attributes.get("height"); + } + getFile() { + return this.file; + } + setFile(file) { + this.file = file; + if (this.isPreviewable()) { + return this.preloadFile(); + } + } + releaseFile() { + this.releasePreloadedFile(); + this.file = null; + } + getUploadProgress() { + return this.uploadProgress != null ? this.uploadProgress : 0; + } + setUploadProgress(value) { + if (this.uploadProgress !== value) { + var _this$uploadProgressD, _this$uploadProgressD2; + this.uploadProgress = value; + return (_this$uploadProgressD = this.uploadProgressDelegate) === null || _this$uploadProgressD === void 0 || (_this$uploadProgressD2 = _this$uploadProgressD.attachmentDidChangeUploadProgress) === null || _this$uploadProgressD2 === void 0 ? void 0 : _this$uploadProgressD2.call(_this$uploadProgressD, this); + } + } + toJSON() { + return this.getAttributes(); + } + getCacheKey() { + return [super.getCacheKey(...arguments), this.attributes.getCacheKey(), this.getPreviewURL()].join("/"); + } + + // Previewable + + getPreviewURL() { + return this.previewURL || this.preloadingURL; + } + setPreviewURL(url) { + if (url !== this.getPreviewURL()) { + var _this$previewDelegate3, _this$previewDelegate4, _this$delegate2, _this$delegate2$attac; + this.previewURL = url; + (_this$previewDelegate3 = this.previewDelegate) === null || _this$previewDelegate3 === void 0 || (_this$previewDelegate4 = _this$previewDelegate3.attachmentDidChangeAttributes) === null || _this$previewDelegate4 === void 0 || _this$previewDelegate4.call(_this$previewDelegate3, this); + return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$attac = _this$delegate2.attachmentDidChangePreviewURL) === null || _this$delegate2$attac === void 0 ? void 0 : _this$delegate2$attac.call(_this$delegate2, this); + } + } + preloadURL() { + return this.preload(this.getURL(), this.releaseFile); + } + preloadFile() { + if (this.file) { + this.fileObjectURL = URL.createObjectURL(this.file); + return this.preload(this.fileObjectURL); + } + } + releasePreloadedFile() { + if (this.fileObjectURL) { + URL.revokeObjectURL(this.fileObjectURL); + this.fileObjectURL = null; + } + } + preload(url, callback) { + if (url && url !== this.getPreviewURL()) { + this.preloadingURL = url; + const operation = new ImagePreloadOperation(url); + return operation.then(_ref => { + let { + width, + height + } = _ref; + if (!this.getWidth() || !this.getHeight()) { + this.setAttributes({ + width, + height + }); + } + this.preloadingURL = null; + this.setPreviewURL(url); + return callback === null || callback === void 0 ? void 0 : callback(); + }).catch(() => { + this.preloadingURL = null; + return callback === null || callback === void 0 ? void 0 : callback(); + }); + } + } + } + _defineProperty(Attachment, "previewablePattern", /^image(\/(gif|png|webp|jpe?g)|$)/); + + class AttachmentPiece extends Piece { + static fromJSON(pieceJSON) { + return new this(Attachment.fromJSON(pieceJSON.attachment), pieceJSON.attributes); + } + constructor(attachment) { + super(...arguments); + this.attachment = attachment; + this.length = 1; + this.ensureAttachmentExclusivelyHasAttribute("href"); + if (!this.attachment.hasContent()) { + this.removeProhibitedAttributes(); + } + } + ensureAttachmentExclusivelyHasAttribute(attribute) { + if (this.hasAttribute(attribute)) { + if (!this.attachment.hasAttribute(attribute)) { + this.attachment.setAttributes(this.attributes.slice([attribute])); + } + this.attributes = this.attributes.remove(attribute); + } + } + removeProhibitedAttributes() { + const attributes = this.attributes.slice(AttachmentPiece.permittedAttributes); + if (!attributes.isEqualTo(this.attributes)) { + this.attributes = attributes; + } + } + getValue() { + return this.attachment; + } + isSerializable() { + return !this.attachment.isPending(); + } + getCaption() { + return this.attributes.get("caption") || ""; + } + isEqualTo(piece) { + var _piece$attachment; + return super.isEqualTo(piece) && this.attachment.id === (piece === null || piece === void 0 || (_piece$attachment = piece.attachment) === null || _piece$attachment === void 0 ? void 0 : _piece$attachment.id); + } + toString() { + return OBJECT_REPLACEMENT_CHARACTER; + } + toJSON() { + const json = super.toJSON(...arguments); + json.attachment = this.attachment; + return json; + } + getCacheKey() { + return [super.getCacheKey(...arguments), this.attachment.getCacheKey()].join("/"); + } + toConsole() { + return JSON.stringify(this.toString()); + } + } + _defineProperty(AttachmentPiece, "permittedAttributes", ["caption", "presentation"]); + Piece.registerType("attachment", AttachmentPiece); + + class StringPiece extends Piece { + static fromJSON(pieceJSON) { + return new this(pieceJSON.string, pieceJSON.attributes); + } + constructor(string) { + super(...arguments); + this.string = normalizeNewlines(string); + this.length = this.string.length; + } + getValue() { + return this.string; + } + toString() { + return this.string.toString(); + } + isBlockBreak() { + return this.toString() === "\n" && this.getAttribute("blockBreak") === true; + } + toJSON() { + const result = super.toJSON(...arguments); + result.string = this.string; + return result; + } + + // Splittable + + canBeConsolidatedWith(piece) { + return piece && this.hasSameConstructorAs(piece) && this.hasSameAttributesAsPiece(piece); + } + consolidateWith(piece) { + return new this.constructor(this.toString() + piece.toString(), this.attributes); + } + splitAtOffset(offset) { + let left, right; + if (offset === 0) { + left = null; + right = this; + } else if (offset === this.length) { + left = this; + right = null; + } else { + left = new this.constructor(this.string.slice(0, offset), this.attributes); + right = new this.constructor(this.string.slice(offset), this.attributes); + } + return [left, right]; + } + toConsole() { + let { + string + } = this; + if (string.length > 15) { + string = string.slice(0, 14) + "…"; + } + return JSON.stringify(string.toString()); + } + } + Piece.registerType("string", StringPiece); + + /* eslint-disable + prefer-const, + */ + class SplittableList extends TrixObject { + static box(objects) { + if (objects instanceof this) { + return objects; + } else { + return new this(objects); + } + } + constructor() { + let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + this.objects = objects.slice(0); + this.length = this.objects.length; + } + indexOf(object) { + return this.objects.indexOf(object); + } + splice() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + return new this.constructor(spliceArray(this.objects, ...args)); + } + eachObject(callback) { + return this.objects.map((object, index) => callback(object, index)); + } + insertObjectAtIndex(object, index) { + return this.splice(index, 0, object); + } + insertSplittableListAtIndex(splittableList, index) { + return this.splice(index, 0, ...splittableList.objects); + } + insertSplittableListAtPosition(splittableList, position) { + const [objects, index] = this.splitObjectAtPosition(position); + return new this.constructor(objects).insertSplittableListAtIndex(splittableList, index); + } + editObjectAtIndex(index, callback) { + return this.replaceObjectAtIndex(callback(this.objects[index]), index); + } + replaceObjectAtIndex(object, index) { + return this.splice(index, 1, object); + } + removeObjectAtIndex(index) { + return this.splice(index, 1); + } + getObjectAtIndex(index) { + return this.objects[index]; + } + getSplittableListInRange(range) { + const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); + return new this.constructor(objects.slice(leftIndex, rightIndex + 1)); + } + selectSplittableList(test) { + const objects = this.objects.filter(object => test(object)); + return new this.constructor(objects); + } + removeObjectsInRange(range) { + const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); + return new this.constructor(objects).splice(leftIndex, rightIndex - leftIndex + 1); + } + transformObjectsInRange(range, transform) { + const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range); + const transformedObjects = objects.map((object, index) => leftIndex <= index && index <= rightIndex ? transform(object) : object); + return new this.constructor(transformedObjects); + } + splitObjectsAtRange(range) { + let rightOuterIndex; + let [objects, leftInnerIndex, offset] = this.splitObjectAtPosition(startOfRange(range)); + [objects, rightOuterIndex] = new this.constructor(objects).splitObjectAtPosition(endOfRange(range) + offset); + return [objects, leftInnerIndex, rightOuterIndex - 1]; + } + getObjectAtPosition(position) { + const { + index + } = this.findIndexAndOffsetAtPosition(position); + return this.objects[index]; + } + splitObjectAtPosition(position) { + let splitIndex, splitOffset; + const { + index, + offset + } = this.findIndexAndOffsetAtPosition(position); + const objects = this.objects.slice(0); + if (index != null) { + if (offset === 0) { + splitIndex = index; + splitOffset = 0; + } else { + const object = this.getObjectAtIndex(index); + const [leftObject, rightObject] = object.splitAtOffset(offset); + objects.splice(index, 1, leftObject, rightObject); + splitIndex = index + 1; + splitOffset = leftObject.getLength() - offset; + } + } else { + splitIndex = objects.length; + splitOffset = 0; + } + return [objects, splitIndex, splitOffset]; + } + consolidate() { + const objects = []; + let pendingObject = this.objects[0]; + this.objects.slice(1).forEach(object => { + var _pendingObject$canBeC, _pendingObject; + if ((_pendingObject$canBeC = (_pendingObject = pendingObject).canBeConsolidatedWith) !== null && _pendingObject$canBeC !== void 0 && _pendingObject$canBeC.call(_pendingObject, object)) { + pendingObject = pendingObject.consolidateWith(object); + } else { + objects.push(pendingObject); + pendingObject = object; + } + }); + if (pendingObject) { + objects.push(pendingObject); + } + return new this.constructor(objects); + } + consolidateFromIndexToIndex(startIndex, endIndex) { + const objects = this.objects.slice(0); + const objectsInRange = objects.slice(startIndex, endIndex + 1); + const consolidatedInRange = new this.constructor(objectsInRange).consolidate().toArray(); + return this.splice(startIndex, objectsInRange.length, ...consolidatedInRange); + } + findIndexAndOffsetAtPosition(position) { + let index; + let currentPosition = 0; + for (index = 0; index < this.objects.length; index++) { + const object = this.objects[index]; + const nextPosition = currentPosition + object.getLength(); + if (currentPosition <= position && position < nextPosition) { + return { + index, + offset: position - currentPosition + }; + } + currentPosition = nextPosition; + } + return { + index: null, + offset: null + }; + } + findPositionAtIndexAndOffset(index, offset) { + let position = 0; + for (let currentIndex = 0; currentIndex < this.objects.length; currentIndex++) { + const object = this.objects[currentIndex]; + if (currentIndex < index) { + position += object.getLength(); + } else if (currentIndex === index) { + position += offset; + break; + } + } + return position; + } + getEndPosition() { + if (this.endPosition == null) { + this.endPosition = 0; + this.objects.forEach(object => this.endPosition += object.getLength()); + } + return this.endPosition; + } + toString() { + return this.objects.join(""); + } + toArray() { + return this.objects.slice(0); + } + toJSON() { + return this.toArray(); + } + isEqualTo(splittableList) { + return super.isEqualTo(...arguments) || objectArraysAreEqual(this.objects, splittableList === null || splittableList === void 0 ? void 0 : splittableList.objects); + } + contentsForInspection() { + return { + objects: "[".concat(this.objects.map(object => object.inspect()).join(", "), "]") + }; + } + } + const objectArraysAreEqual = function (left) { + let right = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + if (left.length !== right.length) { + return false; + } + let result = true; + for (let index = 0; index < left.length; index++) { + const object = left[index]; + if (result && !object.isEqualTo(right[index])) { + result = false; + } + } + return result; + }; + const startOfRange = range => range[0]; + const endOfRange = range => range[1]; + + class Text extends TrixObject { + static textForAttachmentWithAttributes(attachment, attributes) { + const piece = new AttachmentPiece(attachment, attributes); + return new this([piece]); + } + static textForStringWithAttributes(string, attributes) { + const piece = new StringPiece(string, attributes); + return new this([piece]); + } + static fromJSON(textJSON) { + const pieces = Array.from(textJSON).map(pieceJSON => Piece.fromJSON(pieceJSON)); + return new this(pieces); + } + constructor() { + let pieces = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + const notEmpty = pieces.filter(piece => !piece.isEmpty()); + this.pieceList = new SplittableList(notEmpty); + } + copy() { + return this.copyWithPieceList(this.pieceList); + } + copyWithPieceList(pieceList) { + return new this.constructor(pieceList.consolidate().toArray()); + } + copyUsingObjectMap(objectMap) { + const pieces = this.getPieces().map(piece => objectMap.find(piece) || piece); + return new this.constructor(pieces); + } + appendText(text) { + return this.insertTextAtPosition(text, this.getLength()); + } + insertTextAtPosition(text, position) { + return this.copyWithPieceList(this.pieceList.insertSplittableListAtPosition(text.pieceList, position)); + } + removeTextAtRange(range) { + return this.copyWithPieceList(this.pieceList.removeObjectsInRange(range)); + } + replaceTextAtRange(text, range) { + return this.removeTextAtRange(range).insertTextAtPosition(text, range[0]); + } + moveTextFromRangeToPosition(range, position) { + if (range[0] <= position && position <= range[1]) return; + const text = this.getTextAtRange(range); + const length = text.getLength(); + if (range[0] < position) { + position -= length; + } + return this.removeTextAtRange(range).insertTextAtPosition(text, position); + } + addAttributeAtRange(attribute, value, range) { + const attributes = {}; + attributes[attribute] = value; + return this.addAttributesAtRange(attributes, range); + } + addAttributesAtRange(attributes, range) { + return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithAdditionalAttributes(attributes))); + } + removeAttributeAtRange(attribute, range) { + return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithoutAttribute(attribute))); + } + setAttributesAtRange(attributes, range) { + return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithAttributes(attributes))); + } + getAttributesAtPosition(position) { + var _this$pieceList$getOb; + return ((_this$pieceList$getOb = this.pieceList.getObjectAtPosition(position)) === null || _this$pieceList$getOb === void 0 ? void 0 : _this$pieceList$getOb.getAttributes()) || {}; + } + getCommonAttributes() { + const objects = Array.from(this.pieceList.toArray()).map(piece => piece.getAttributes()); + return Hash.fromCommonAttributesOfObjects(objects).toObject(); + } + getCommonAttributesAtRange(range) { + return this.getTextAtRange(range).getCommonAttributes() || {}; + } + getExpandedRangeForAttributeAtOffset(attributeName, offset) { + let right; + let left = right = offset; + const length = this.getLength(); + while (left > 0 && this.getCommonAttributesAtRange([left - 1, right])[attributeName]) { + left--; + } + while (right < length && this.getCommonAttributesAtRange([offset, right + 1])[attributeName]) { + right++; + } + return [left, right]; + } + getTextAtRange(range) { + return this.copyWithPieceList(this.pieceList.getSplittableListInRange(range)); + } + getStringAtRange(range) { + return this.pieceList.getSplittableListInRange(range).toString(); + } + getStringAtPosition(position) { + return this.getStringAtRange([position, position + 1]); + } + startsWithString(string) { + return this.getStringAtRange([0, string.length]) === string; + } + endsWithString(string) { + const length = this.getLength(); + return this.getStringAtRange([length - string.length, length]) === string; + } + getAttachmentPieces() { + return this.pieceList.toArray().filter(piece => !!piece.attachment); + } + getAttachments() { + return this.getAttachmentPieces().map(piece => piece.attachment); + } + getAttachmentAndPositionById(attachmentId) { + let position = 0; + for (const piece of this.pieceList.toArray()) { + var _piece$attachment; + if (((_piece$attachment = piece.attachment) === null || _piece$attachment === void 0 ? void 0 : _piece$attachment.id) === attachmentId) { + return { + attachment: piece.attachment, + position + }; + } + position += piece.length; + } + return { + attachment: null, + position: null + }; + } + getAttachmentById(attachmentId) { + const { + attachment + } = this.getAttachmentAndPositionById(attachmentId); + return attachment; + } + getRangeOfAttachment(attachment) { + const attachmentAndPosition = this.getAttachmentAndPositionById(attachment.id); + const position = attachmentAndPosition.position; + attachment = attachmentAndPosition.attachment; + if (attachment) { + return [position, position + 1]; + } + } + updateAttributesForAttachment(attributes, attachment) { + const range = this.getRangeOfAttachment(attachment); + if (range) { + return this.addAttributesAtRange(attributes, range); + } else { + return this; + } + } + getLength() { + return this.pieceList.getEndPosition(); + } + isEmpty() { + return this.getLength() === 0; + } + isEqualTo(text) { + var _text$pieceList; + return super.isEqualTo(text) || (text === null || text === void 0 || (_text$pieceList = text.pieceList) === null || _text$pieceList === void 0 ? void 0 : _text$pieceList.isEqualTo(this.pieceList)); + } + isBlockBreak() { + return this.getLength() === 1 && this.pieceList.getObjectAtIndex(0).isBlockBreak(); + } + eachPiece(callback) { + return this.pieceList.eachObject(callback); + } + getPieces() { + return this.pieceList.toArray(); + } + getPieceAtPosition(position) { + return this.pieceList.getObjectAtPosition(position); + } + contentsForInspection() { + return { + pieceList: this.pieceList.inspect() + }; + } + toSerializableText() { + const pieceList = this.pieceList.selectSplittableList(piece => piece.isSerializable()); + return this.copyWithPieceList(pieceList); + } + toString() { + return this.pieceList.toString(); + } + toJSON() { + return this.pieceList.toJSON(); + } + toConsole() { + return JSON.stringify(this.pieceList.toArray().map(piece => JSON.parse(piece.toConsole()))); + } + + // BIDI + + getDirection() { + return getDirection(this.toString()); + } + isRTL() { + return this.getDirection() === "rtl"; + } + } + + class Block extends TrixObject { + static fromJSON(blockJSON) { + const text = Text.fromJSON(blockJSON.text); + return new this(text, blockJSON.attributes, blockJSON.htmlAttributes); + } + constructor(text, attributes, htmlAttributes) { + super(...arguments); + this.text = applyBlockBreakToText(text || new Text()); + this.attributes = attributes || []; + this.htmlAttributes = htmlAttributes || {}; + } + isEmpty() { + return this.text.isBlockBreak(); + } + isEqualTo(block) { + if (super.isEqualTo(block)) return true; + return this.text.isEqualTo(block === null || block === void 0 ? void 0 : block.text) && arraysAreEqual(this.attributes, block === null || block === void 0 ? void 0 : block.attributes) && objectsAreEqual(this.htmlAttributes, block === null || block === void 0 ? void 0 : block.htmlAttributes); + } + copyWithText(text) { + return new Block(text, this.attributes, this.htmlAttributes); + } + copyWithoutText() { + return this.copyWithText(null); + } + copyWithAttributes(attributes) { + return new Block(this.text, attributes, this.htmlAttributes); + } + copyWithoutAttributes() { + return this.copyWithAttributes(null); + } + copyUsingObjectMap(objectMap) { + const mappedText = objectMap.find(this.text); + if (mappedText) { + return this.copyWithText(mappedText); + } else { + return this.copyWithText(this.text.copyUsingObjectMap(objectMap)); + } + } + addAttribute(attribute) { + const attributes = this.attributes.concat(expandAttribute(attribute)); + return this.copyWithAttributes(attributes); + } + addHTMLAttribute(attribute, value) { + const htmlAttributes = Object.assign({}, this.htmlAttributes, { + [attribute]: value + }); + return new Block(this.text, this.attributes, htmlAttributes); + } + removeAttribute(attribute) { + const { + listAttribute + } = getBlockConfig(attribute); + const attributes = removeLastValue(removeLastValue(this.attributes, attribute), listAttribute); + return this.copyWithAttributes(attributes); + } + removeLastAttribute() { + return this.removeAttribute(this.getLastAttribute()); + } + getLastAttribute() { + return getLastElement(this.attributes); + } + getAttributes() { + return this.attributes.slice(0); + } + getAttributeLevel() { + return this.attributes.length; + } + getAttributeAtLevel(level) { + return this.attributes[level - 1]; + } + hasAttribute(attributeName) { + return this.attributes.includes(attributeName); + } + hasAttributes() { + return this.getAttributeLevel() > 0; + } + getLastNestableAttribute() { + return getLastElement(this.getNestableAttributes()); + } + getNestableAttributes() { + return this.attributes.filter(attribute => getBlockConfig(attribute).nestable); + } + getNestingLevel() { + return this.getNestableAttributes().length; + } + decreaseNestingLevel() { + const attribute = this.getLastNestableAttribute(); + if (attribute) { + return this.removeAttribute(attribute); + } else { + return this; + } + } + increaseNestingLevel() { + const attribute = this.getLastNestableAttribute(); + if (attribute) { + const index = this.attributes.lastIndexOf(attribute); + const attributes = spliceArray(this.attributes, index + 1, 0, ...expandAttribute(attribute)); + return this.copyWithAttributes(attributes); + } else { + return this; + } + } + getListItemAttributes() { + return this.attributes.filter(attribute => getBlockConfig(attribute).listAttribute); + } + isListItem() { + var _getBlockConfig; + return (_getBlockConfig = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.listAttribute; + } + isTerminalBlock() { + var _getBlockConfig2; + return (_getBlockConfig2 = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig2 === void 0 ? void 0 : _getBlockConfig2.terminal; + } + breaksOnReturn() { + var _getBlockConfig3; + return (_getBlockConfig3 = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig3 === void 0 ? void 0 : _getBlockConfig3.breakOnReturn; + } + findLineBreakInDirectionFromPosition(direction, position) { + const string = this.toString(); + let result; + switch (direction) { + case "forward": + result = string.indexOf("\n", position); + break; + case "backward": + result = string.slice(0, position).lastIndexOf("\n"); + } + if (result !== -1) { + return result; + } + } + contentsForInspection() { + return { + text: this.text.inspect(), + attributes: this.attributes + }; + } + toString() { + return this.text.toString(); + } + toJSON() { + return { + text: this.text, + attributes: this.attributes, + htmlAttributes: this.htmlAttributes + }; + } + + // BIDI + + getDirection() { + return this.text.getDirection(); + } + isRTL() { + return this.text.isRTL(); + } + + // Splittable + + getLength() { + return this.text.getLength(); + } + canBeConsolidatedWith(block) { + return !this.hasAttributes() && !block.hasAttributes() && this.getDirection() === block.getDirection(); + } + consolidateWith(block) { + const newlineText = Text.textForStringWithAttributes("\n"); + const text = this.getTextWithoutBlockBreak().appendText(newlineText); + return this.copyWithText(text.appendText(block.text)); + } + splitAtOffset(offset) { + let left, right; + if (offset === 0) { + left = null; + right = this; + } else if (offset === this.getLength()) { + left = this; + right = null; + } else { + left = this.copyWithText(this.text.getTextAtRange([0, offset])); + right = this.copyWithText(this.text.getTextAtRange([offset, this.getLength()])); + } + return [left, right]; + } + getBlockBreakPosition() { + return this.text.getLength() - 1; + } + getTextWithoutBlockBreak() { + if (textEndsInBlockBreak(this.text)) { + return this.text.getTextAtRange([0, this.getBlockBreakPosition()]); + } else { + return this.text.copy(); + } + } + + // Grouping + + canBeGrouped(depth) { + return this.attributes[depth]; + } + canBeGroupedWith(otherBlock, depth) { + const otherAttributes = otherBlock.getAttributes(); + const otherAttribute = otherAttributes[depth]; + const attribute = this.attributes[depth]; + return attribute === otherAttribute && !(getBlockConfig(attribute).group === false && !getListAttributeNames().includes(otherAttributes[depth + 1])) && (this.getDirection() === otherBlock.getDirection() || otherBlock.isEmpty()); + } + } + + // Block breaks + + const applyBlockBreakToText = function (text) { + text = unmarkExistingInnerBlockBreaksInText(text); + text = addBlockBreakToText(text); + return text; + }; + const unmarkExistingInnerBlockBreaksInText = function (text) { + let modified = false; + const pieces = text.getPieces(); + let innerPieces = pieces.slice(0, pieces.length - 1); + const lastPiece = pieces[pieces.length - 1]; + if (!lastPiece) return text; + innerPieces = innerPieces.map(piece => { + if (piece.isBlockBreak()) { + modified = true; + return unmarkBlockBreakPiece(piece); + } else { + return piece; + } + }); + if (modified) { + return new Text([...innerPieces, lastPiece]); + } else { + return text; + } + }; + const blockBreakText = Text.textForStringWithAttributes("\n", { + blockBreak: true + }); + const addBlockBreakToText = function (text) { + if (textEndsInBlockBreak(text)) { + return text; + } else { + return text.appendText(blockBreakText); + } + }; + const textEndsInBlockBreak = function (text) { + const length = text.getLength(); + if (length === 0) { + return false; + } + const endText = text.getTextAtRange([length - 1, length]); + return endText.isBlockBreak(); + }; + const unmarkBlockBreakPiece = piece => piece.copyWithoutAttribute("blockBreak"); + + // Attributes + + const expandAttribute = function (attribute) { + const { + listAttribute + } = getBlockConfig(attribute); + if (listAttribute) { + return [listAttribute, attribute]; + } else { + return [attribute]; + } + }; + + // Array helpers + + const getLastElement = array => array.slice(-1)[0]; + const removeLastValue = function (array, value) { + const index = array.lastIndexOf(value); + if (index === -1) { + return array; + } else { + return spliceArray(array, index, 1); + } + }; + + class Document extends TrixObject { + static fromJSON(documentJSON) { + const blocks = Array.from(documentJSON).map(blockJSON => Block.fromJSON(blockJSON)); + return new this(blocks); + } + static fromString(string, textAttributes) { + const text = Text.textForStringWithAttributes(string, textAttributes); + return new this([new Block(text)]); + } + constructor() { + let blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + if (blocks.length === 0) { + blocks = [new Block()]; + } + this.blockList = SplittableList.box(blocks); + } + isEmpty() { + const block = this.getBlockAtIndex(0); + return this.blockList.length === 1 && block.isEmpty() && !block.hasAttributes(); + } + copy() { + let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + const blocks = options.consolidateBlocks ? this.blockList.consolidate().toArray() : this.blockList.toArray(); + return new this.constructor(blocks); + } + copyUsingObjectsFromDocument(sourceDocument) { + const objectMap = new ObjectMap(sourceDocument.getObjects()); + return this.copyUsingObjectMap(objectMap); + } + copyUsingObjectMap(objectMap) { + const blocks = this.getBlocks().map(block => { + const mappedBlock = objectMap.find(block); + return mappedBlock || block.copyUsingObjectMap(objectMap); + }); + return new this.constructor(blocks); + } + copyWithBaseBlockAttributes() { + let blockAttributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + const blocks = this.getBlocks().map(block => { + const attributes = blockAttributes.concat(block.getAttributes()); + return block.copyWithAttributes(attributes); + }); + return new this.constructor(blocks); + } + replaceBlock(oldBlock, newBlock) { + const index = this.blockList.indexOf(oldBlock); + if (index === -1) { + return this; + } + return new this.constructor(this.blockList.replaceObjectAtIndex(newBlock, index)); + } + insertDocumentAtRange(document, range) { + const { + blockList + } = document; + range = normalizeRange(range); + let [position] = range; + const { + index, + offset + } = this.locationFromPosition(position); + let result = this; + const block = this.getBlockAtPosition(position); + if (rangeIsCollapsed(range) && block.isEmpty() && !block.hasAttributes()) { + result = new this.constructor(result.blockList.removeObjectAtIndex(index)); + } else if (block.getBlockBreakPosition() === offset) { + position++; + } + result = result.removeTextAtRange(range); + return new this.constructor(result.blockList.insertSplittableListAtPosition(blockList, position)); + } + mergeDocumentAtRange(document, range) { + let formattedDocument, result; + range = normalizeRange(range); + const [startPosition] = range; + const startLocation = this.locationFromPosition(startPosition); + const blockAttributes = this.getBlockAtIndex(startLocation.index).getAttributes(); + const baseBlockAttributes = document.getBaseBlockAttributes(); + const trailingBlockAttributes = blockAttributes.slice(-baseBlockAttributes.length); + if (arraysAreEqual(baseBlockAttributes, trailingBlockAttributes)) { + const leadingBlockAttributes = blockAttributes.slice(0, -baseBlockAttributes.length); + formattedDocument = document.copyWithBaseBlockAttributes(leadingBlockAttributes); + } else { + formattedDocument = document.copy({ + consolidateBlocks: true + }).copyWithBaseBlockAttributes(blockAttributes); + } + const blockCount = formattedDocument.getBlockCount(); + const firstBlock = formattedDocument.getBlockAtIndex(0); + if (arraysAreEqual(blockAttributes, firstBlock.getAttributes())) { + const firstText = firstBlock.getTextWithoutBlockBreak(); + result = this.insertTextAtRange(firstText, range); + if (blockCount > 1) { + formattedDocument = new this.constructor(formattedDocument.getBlocks().slice(1)); + const position = startPosition + firstText.getLength(); + result = result.insertDocumentAtRange(formattedDocument, position); + } + } else { + result = this.insertDocumentAtRange(formattedDocument, range); + } + return result; + } + insertTextAtRange(text, range) { + range = normalizeRange(range); + const [startPosition] = range; + const { + index, + offset + } = this.locationFromPosition(startPosition); + const document = this.removeTextAtRange(range); + return new this.constructor(document.blockList.editObjectAtIndex(index, block => block.copyWithText(block.text.insertTextAtPosition(text, offset)))); + } + removeTextAtRange(range) { + let blocks; + range = normalizeRange(range); + const [leftPosition, rightPosition] = range; + if (rangeIsCollapsed(range)) { + return this; + } + const [leftLocation, rightLocation] = Array.from(this.locationRangeFromRange(range)); + const leftIndex = leftLocation.index; + const leftOffset = leftLocation.offset; + const leftBlock = this.getBlockAtIndex(leftIndex); + const rightIndex = rightLocation.index; + const rightOffset = rightLocation.offset; + const rightBlock = this.getBlockAtIndex(rightIndex); + const removeRightNewline = rightPosition - leftPosition === 1 && leftBlock.getBlockBreakPosition() === leftOffset && rightBlock.getBlockBreakPosition() !== rightOffset && rightBlock.text.getStringAtPosition(rightOffset) === "\n"; + if (removeRightNewline) { + blocks = this.blockList.editObjectAtIndex(rightIndex, block => block.copyWithText(block.text.removeTextAtRange([rightOffset, rightOffset + 1]))); + } else { + let block; + const leftText = leftBlock.text.getTextAtRange([0, leftOffset]); + const rightText = rightBlock.text.getTextAtRange([rightOffset, rightBlock.getLength()]); + const text = leftText.appendText(rightText); + const removingLeftBlock = leftIndex !== rightIndex && leftOffset === 0; + const useRightBlock = removingLeftBlock && leftBlock.getAttributeLevel() >= rightBlock.getAttributeLevel(); + if (useRightBlock) { + block = rightBlock.copyWithText(text); + } else { + block = leftBlock.copyWithText(text); + } + const affectedBlockCount = rightIndex + 1 - leftIndex; + blocks = this.blockList.splice(leftIndex, affectedBlockCount, block); + } + return new this.constructor(blocks); + } + moveTextFromRangeToPosition(range, position) { + let text; + range = normalizeRange(range); + const [startPosition, endPosition] = range; + if (startPosition <= position && position <= endPosition) { + return this; + } + let document = this.getDocumentAtRange(range); + let result = this.removeTextAtRange(range); + const movingRightward = startPosition < position; + if (movingRightward) { + position -= document.getLength(); + } + const [firstBlock, ...blocks] = document.getBlocks(); + if (blocks.length === 0) { + text = firstBlock.getTextWithoutBlockBreak(); + if (movingRightward) { + position += 1; + } + } else { + text = firstBlock.text; + } + result = result.insertTextAtRange(text, position); + if (blocks.length === 0) { + return result; + } + document = new this.constructor(blocks); + position += text.getLength(); + return result.insertDocumentAtRange(document, position); + } + addAttributeAtRange(attribute, value, range) { + let { + blockList + } = this; + this.eachBlockAtRange(range, (block, textRange, index) => blockList = blockList.editObjectAtIndex(index, function () { + if (getBlockConfig(attribute)) { + return block.addAttribute(attribute, value); + } else { + if (textRange[0] === textRange[1]) { + return block; + } else { + return block.copyWithText(block.text.addAttributeAtRange(attribute, value, textRange)); + } + } + })); + return new this.constructor(blockList); + } + addAttribute(attribute, value) { + let { + blockList + } = this; + this.eachBlock((block, index) => blockList = blockList.editObjectAtIndex(index, () => block.addAttribute(attribute, value))); + return new this.constructor(blockList); + } + removeAttributeAtRange(attribute, range) { + let { + blockList + } = this; + this.eachBlockAtRange(range, function (block, textRange, index) { + if (getBlockConfig(attribute)) { + blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(attribute)); + } else if (textRange[0] !== textRange[1]) { + blockList = blockList.editObjectAtIndex(index, () => block.copyWithText(block.text.removeAttributeAtRange(attribute, textRange))); + } + }); + return new this.constructor(blockList); + } + updateAttributesForAttachment(attributes, attachment) { + const range = this.getRangeOfAttachment(attachment); + const [startPosition] = Array.from(range); + const { + index + } = this.locationFromPosition(startPosition); + const text = this.getTextAtIndex(index); + return new this.constructor(this.blockList.editObjectAtIndex(index, block => block.copyWithText(text.updateAttributesForAttachment(attributes, attachment)))); + } + removeAttributeForAttachment(attribute, attachment) { + const range = this.getRangeOfAttachment(attachment); + return this.removeAttributeAtRange(attribute, range); + } + setHTMLAttributeAtPosition(position, name, value) { + const block = this.getBlockAtPosition(position); + const updatedBlock = block.addHTMLAttribute(name, value); + return this.replaceBlock(block, updatedBlock); + } + insertBlockBreakAtRange(range) { + let blocks; + range = normalizeRange(range); + const [startPosition] = range; + const { + offset + } = this.locationFromPosition(startPosition); + const document = this.removeTextAtRange(range); + if (offset === 0) { + blocks = [new Block()]; + } + return new this.constructor(document.blockList.insertSplittableListAtPosition(new SplittableList(blocks), startPosition)); + } + applyBlockAttributeAtRange(attributeName, value, range) { + const expanded = this.expandRangeToLineBreaksAndSplitBlocks(range); + let document = expanded.document; + range = expanded.range; + const blockConfig = getBlockConfig(attributeName); + if (blockConfig.listAttribute) { + document = document.removeLastListAttributeAtRange(range, { + exceptAttributeName: attributeName + }); + const converted = document.convertLineBreaksToBlockBreaksInRange(range); + document = converted.document; + range = converted.range; + } else if (blockConfig.exclusive) { + document = document.removeBlockAttributesAtRange(range); + } else if (blockConfig.terminal) { + document = document.removeLastTerminalAttributeAtRange(range); + } else { + document = document.consolidateBlocksAtRange(range); + } + return document.addAttributeAtRange(attributeName, value, range); + } + removeLastListAttributeAtRange(range) { + let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let { + blockList + } = this; + this.eachBlockAtRange(range, function (block, textRange, index) { + const lastAttributeName = block.getLastAttribute(); + if (!lastAttributeName) { + return; + } + if (!getBlockConfig(lastAttributeName).listAttribute) { + return; + } + if (lastAttributeName === options.exceptAttributeName) { + return; + } + blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(lastAttributeName)); + }); + return new this.constructor(blockList); + } + removeLastTerminalAttributeAtRange(range) { + let { + blockList + } = this; + this.eachBlockAtRange(range, function (block, textRange, index) { + const lastAttributeName = block.getLastAttribute(); + if (!lastAttributeName) { + return; + } + if (!getBlockConfig(lastAttributeName).terminal) { + return; + } + blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(lastAttributeName)); + }); + return new this.constructor(blockList); + } + removeBlockAttributesAtRange(range) { + let { + blockList + } = this; + this.eachBlockAtRange(range, function (block, textRange, index) { + if (block.hasAttributes()) { + blockList = blockList.editObjectAtIndex(index, () => block.copyWithoutAttributes()); + } + }); + return new this.constructor(blockList); + } + expandRangeToLineBreaksAndSplitBlocks(range) { + let position; + range = normalizeRange(range); + let [startPosition, endPosition] = range; + const startLocation = this.locationFromPosition(startPosition); + const endLocation = this.locationFromPosition(endPosition); + let document = this; + const startBlock = document.getBlockAtIndex(startLocation.index); + startLocation.offset = startBlock.findLineBreakInDirectionFromPosition("backward", startLocation.offset); + if (startLocation.offset != null) { + position = document.positionFromLocation(startLocation); + document = document.insertBlockBreakAtRange([position, position + 1]); + endLocation.index += 1; + endLocation.offset -= document.getBlockAtIndex(startLocation.index).getLength(); + startLocation.index += 1; + } + startLocation.offset = 0; + if (endLocation.offset === 0 && endLocation.index > startLocation.index) { + endLocation.index -= 1; + endLocation.offset = document.getBlockAtIndex(endLocation.index).getBlockBreakPosition(); + } else { + const endBlock = document.getBlockAtIndex(endLocation.index); + if (endBlock.text.getStringAtRange([endLocation.offset - 1, endLocation.offset]) === "\n") { + endLocation.offset -= 1; + } else { + endLocation.offset = endBlock.findLineBreakInDirectionFromPosition("forward", endLocation.offset); + } + if (endLocation.offset !== endBlock.getBlockBreakPosition()) { + position = document.positionFromLocation(endLocation); + document = document.insertBlockBreakAtRange([position, position + 1]); + } + } + startPosition = document.positionFromLocation(startLocation); + endPosition = document.positionFromLocation(endLocation); + range = normalizeRange([startPosition, endPosition]); + return { + document, + range + }; + } + convertLineBreaksToBlockBreaksInRange(range) { + range = normalizeRange(range); + let [position] = range; + const string = this.getStringAtRange(range).slice(0, -1); + let document = this; + string.replace(/.*?\n/g, function (match) { + position += match.length; + document = document.insertBlockBreakAtRange([position - 1, position]); + }); + return { + document, + range + }; + } + consolidateBlocksAtRange(range) { + range = normalizeRange(range); + const [startPosition, endPosition] = range; + const startIndex = this.locationFromPosition(startPosition).index; + const endIndex = this.locationFromPosition(endPosition).index; + return new this.constructor(this.blockList.consolidateFromIndexToIndex(startIndex, endIndex)); + } + getDocumentAtRange(range) { + range = normalizeRange(range); + const blocks = this.blockList.getSplittableListInRange(range).toArray(); + return new this.constructor(blocks); + } + getStringAtRange(range) { + let endIndex; + const array = range = normalizeRange(range), + endPosition = array[array.length - 1]; + if (endPosition !== this.getLength()) { + endIndex = -1; + } + return this.getDocumentAtRange(range).toString().slice(0, endIndex); + } + getBlockAtIndex(index) { + return this.blockList.getObjectAtIndex(index); + } + getBlockAtPosition(position) { + const { + index + } = this.locationFromPosition(position); + return this.getBlockAtIndex(index); + } + getTextAtIndex(index) { + var _this$getBlockAtIndex; + return (_this$getBlockAtIndex = this.getBlockAtIndex(index)) === null || _this$getBlockAtIndex === void 0 ? void 0 : _this$getBlockAtIndex.text; + } + getTextAtPosition(position) { + const { + index + } = this.locationFromPosition(position); + return this.getTextAtIndex(index); + } + getPieceAtPosition(position) { + const { + index, + offset + } = this.locationFromPosition(position); + return this.getTextAtIndex(index).getPieceAtPosition(offset); + } + getCharacterAtPosition(position) { + const { + index, + offset + } = this.locationFromPosition(position); + return this.getTextAtIndex(index).getStringAtRange([offset, offset + 1]); + } + getLength() { + return this.blockList.getEndPosition(); + } + getBlocks() { + return this.blockList.toArray(); + } + getBlockCount() { + return this.blockList.length; + } + getEditCount() { + return this.editCount; + } + eachBlock(callback) { + return this.blockList.eachObject(callback); + } + eachBlockAtRange(range, callback) { + let block, textRange; + range = normalizeRange(range); + const [startPosition, endPosition] = range; + const startLocation = this.locationFromPosition(startPosition); + const endLocation = this.locationFromPosition(endPosition); + if (startLocation.index === endLocation.index) { + block = this.getBlockAtIndex(startLocation.index); + textRange = [startLocation.offset, endLocation.offset]; + return callback(block, textRange, startLocation.index); + } else { + for (let index = startLocation.index; index <= endLocation.index; index++) { + block = this.getBlockAtIndex(index); + if (block) { + switch (index) { + case startLocation.index: + textRange = [startLocation.offset, block.text.getLength()]; + break; + case endLocation.index: + textRange = [0, endLocation.offset]; + break; + default: + textRange = [0, block.text.getLength()]; + } + callback(block, textRange, index); + } + } + } + } + getCommonAttributesAtRange(range) { + range = normalizeRange(range); + const [startPosition] = range; + if (rangeIsCollapsed(range)) { + return this.getCommonAttributesAtPosition(startPosition); + } else { + const textAttributes = []; + const blockAttributes = []; + this.eachBlockAtRange(range, function (block, textRange) { + if (textRange[0] !== textRange[1]) { + textAttributes.push(block.text.getCommonAttributesAtRange(textRange)); + return blockAttributes.push(attributesForBlock(block)); + } + }); + return Hash.fromCommonAttributesOfObjects(textAttributes).merge(Hash.fromCommonAttributesOfObjects(blockAttributes)).toObject(); + } + } + getCommonAttributesAtPosition(position) { + let key, value; + const { + index, + offset + } = this.locationFromPosition(position); + const block = this.getBlockAtIndex(index); + if (!block) { + return {}; + } + const commonAttributes = attributesForBlock(block); + const attributes = block.text.getAttributesAtPosition(offset); + const attributesLeft = block.text.getAttributesAtPosition(offset - 1); + const inheritableAttributes = Object.keys(text_attributes).filter(key => { + return text_attributes[key].inheritable; + }); + for (key in attributesLeft) { + value = attributesLeft[key]; + if (value === attributes[key] || inheritableAttributes.includes(key)) { + commonAttributes[key] = value; + } + } + return commonAttributes; + } + getRangeOfCommonAttributeAtPosition(attributeName, position) { + const { + index, + offset + } = this.locationFromPosition(position); + const text = this.getTextAtIndex(index); + const [startOffset, endOffset] = Array.from(text.getExpandedRangeForAttributeAtOffset(attributeName, offset)); + const start = this.positionFromLocation({ + index, + offset: startOffset + }); + const end = this.positionFromLocation({ + index, + offset: endOffset + }); + return normalizeRange([start, end]); + } + getBaseBlockAttributes() { + let baseBlockAttributes = this.getBlockAtIndex(0).getAttributes(); + for (let blockIndex = 1; blockIndex < this.getBlockCount(); blockIndex++) { + const blockAttributes = this.getBlockAtIndex(blockIndex).getAttributes(); + const lastAttributeIndex = Math.min(baseBlockAttributes.length, blockAttributes.length); + baseBlockAttributes = (() => { + const result = []; + for (let index = 0; index < lastAttributeIndex; index++) { + if (blockAttributes[index] !== baseBlockAttributes[index]) { + break; + } + result.push(blockAttributes[index]); + } + return result; + })(); + } + return baseBlockAttributes; + } + getAttachmentById(attachmentId) { + for (const attachment of this.getAttachments()) { + if (attachment.id === attachmentId) { + return attachment; + } + } + } + getAttachmentPieces() { + let attachmentPieces = []; + this.blockList.eachObject(_ref => { + let { + text + } = _ref; + return attachmentPieces = attachmentPieces.concat(text.getAttachmentPieces()); + }); + return attachmentPieces; + } + getAttachments() { + return this.getAttachmentPieces().map(piece => piece.attachment); + } + getRangeOfAttachment(attachment) { + let position = 0; + const iterable = this.blockList.toArray(); + for (let index = 0; index < iterable.length; index++) { + const { + text + } = iterable[index]; + const textRange = text.getRangeOfAttachment(attachment); + if (textRange) { + return normalizeRange([position + textRange[0], position + textRange[1]]); + } + position += text.getLength(); + } + } + getLocationRangeOfAttachment(attachment) { + const range = this.getRangeOfAttachment(attachment); + return this.locationRangeFromRange(range); + } + getAttachmentPieceForAttachment(attachment) { + for (const piece of this.getAttachmentPieces()) { + if (piece.attachment === attachment) { + return piece; + } + } + } + findRangesForBlockAttribute(attributeName) { + let position = 0; + const ranges = []; + this.getBlocks().forEach(block => { + const length = block.getLength(); + if (block.hasAttribute(attributeName)) { + ranges.push([position, position + length]); + } + position += length; + }); + return ranges; + } + findRangesForTextAttribute(attributeName) { + let { + withValue + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let position = 0; + let range = []; + const ranges = []; + const match = function (piece) { + if (withValue) { + return piece.getAttribute(attributeName) === withValue; + } else { + return piece.hasAttribute(attributeName); + } + }; + this.getPieces().forEach(piece => { + const length = piece.getLength(); + if (match(piece)) { + if (range[1] === position) { + range[1] = position + length; + } else { + ranges.push(range = [position, position + length]); + } + } + position += length; + }); + return ranges; + } + locationFromPosition(position) { + const location = this.blockList.findIndexAndOffsetAtPosition(Math.max(0, position)); + if (location.index != null) { + return location; + } else { + const blocks = this.getBlocks(); + return { + index: blocks.length - 1, + offset: blocks[blocks.length - 1].getLength() + }; + } + } + positionFromLocation(location) { + return this.blockList.findPositionAtIndexAndOffset(location.index, location.offset); + } + locationRangeFromPosition(position) { + return normalizeRange(this.locationFromPosition(position)); + } + locationRangeFromRange(range) { + range = normalizeRange(range); + if (!range) return; + const [startPosition, endPosition] = Array.from(range); + const startLocation = this.locationFromPosition(startPosition); + const endLocation = this.locationFromPosition(endPosition); + return normalizeRange([startLocation, endLocation]); + } + rangeFromLocationRange(locationRange) { + let rightPosition; + locationRange = normalizeRange(locationRange); + const leftPosition = this.positionFromLocation(locationRange[0]); + if (!rangeIsCollapsed(locationRange)) { + rightPosition = this.positionFromLocation(locationRange[1]); + } + return normalizeRange([leftPosition, rightPosition]); + } + isEqualTo(document) { + return this.blockList.isEqualTo(document === null || document === void 0 ? void 0 : document.blockList); + } + getTexts() { + return this.getBlocks().map(block => block.text); + } + getPieces() { + const pieces = []; + Array.from(this.getTexts()).forEach(text => { + pieces.push(...Array.from(text.getPieces() || [])); + }); + return pieces; + } + getObjects() { + return this.getBlocks().concat(this.getTexts()).concat(this.getPieces()); + } + toSerializableDocument() { + const blocks = []; + this.blockList.eachObject(block => blocks.push(block.copyWithText(block.text.toSerializableText()))); + return new this.constructor(blocks); + } + toString() { + return this.blockList.toString(); + } + toJSON() { + return this.blockList.toJSON(); + } + toConsole() { + return JSON.stringify(this.blockList.toArray().map(block => JSON.parse(block.text.toConsole()))); + } + } + const attributesForBlock = function (block) { + const attributes = {}; + const attributeName = block.getLastAttribute(); + if (attributeName) { + attributes[attributeName] = true; + } + return attributes; + }; + + /* eslint-disable + no-case-declarations, + no-irregular-whitespace, + */ + const pieceForString = function (string) { + let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const type = "string"; + string = normalizeSpaces(string); + return { + string, + attributes, + type + }; + }; + const pieceForAttachment = function (attachment) { + let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const type = "attachment"; + return { + attachment, + attributes, + type + }; + }; + const blockForAttributes = function () { + let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + let htmlAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const text = []; + return { + text, + attributes, + htmlAttributes + }; + }; + const parseTrixDataAttribute = (element, name) => { + try { + return JSON.parse(element.getAttribute("data-trix-".concat(name))); + } catch (error) { + return {}; + } + }; + const getImageDimensions = element => { + const width = element.getAttribute("width"); + const height = element.getAttribute("height"); + const dimensions = {}; + if (width) { + dimensions.width = parseInt(width, 10); + } + if (height) { + dimensions.height = parseInt(height, 10); + } + return dimensions; + }; + class HTMLParser extends BasicObject { + static parse(html, options) { + const parser = new this(html, options); + parser.parse(); + return parser; + } + constructor(html) { + let { + referenceElement + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + super(...arguments); + this.html = html; + this.referenceElement = referenceElement; + this.blocks = []; + this.blockElements = []; + this.processedElements = []; + } + getDocument() { + return Document.fromJSON(this.blocks); + } + + // HTML parsing + + parse() { + try { + this.createHiddenContainer(); + HTMLSanitizer.setHTML(this.containerElement, this.html); + const walker = walkTree(this.containerElement, { + usingFilter: nodeFilter + }); + while (walker.nextNode()) { + this.processNode(walker.currentNode); + } + return this.translateBlockElementMarginsToNewlines(); + } finally { + this.removeHiddenContainer(); + } + } + createHiddenContainer() { + if (this.referenceElement) { + this.containerElement = this.referenceElement.cloneNode(false); + this.containerElement.removeAttribute("id"); + this.containerElement.setAttribute("data-trix-internal", ""); + this.containerElement.style.display = "none"; + return this.referenceElement.parentNode.insertBefore(this.containerElement, this.referenceElement.nextSibling); + } else { + this.containerElement = makeElement({ + tagName: "div", + style: { + display: "none" + } + }); + return document.body.appendChild(this.containerElement); + } + } + removeHiddenContainer() { + return removeNode(this.containerElement); + } + processNode(node) { + switch (node.nodeType) { + case Node.TEXT_NODE: + if (!this.isInsignificantTextNode(node)) { + this.appendBlockForTextNode(node); + return this.processTextNode(node); + } + break; + case Node.ELEMENT_NODE: + this.appendBlockForElement(node); + return this.processElement(node); + } + } + appendBlockForTextNode(node) { + const element = node.parentNode; + if (element === this.currentBlockElement && this.isBlockElement(node.previousSibling)) { + return this.appendStringWithAttributes("\n"); + } else if (element === this.containerElement || this.isBlockElement(element)) { + var _this$currentBlock; + const attributes = this.getBlockAttributes(element); + const htmlAttributes = this.getBlockHTMLAttributes(element); + if (!arraysAreEqual(attributes, (_this$currentBlock = this.currentBlock) === null || _this$currentBlock === void 0 ? void 0 : _this$currentBlock.attributes)) { + this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes); + this.currentBlockElement = element; + } + } + } + appendBlockForElement(element) { + const elementIsBlockElement = this.isBlockElement(element); + const currentBlockContainsElement = elementContainsNode(this.currentBlockElement, element); + if (elementIsBlockElement && !this.isBlockElement(element.firstChild)) { + if (!this.isInsignificantTextNode(element.firstChild) || !this.isBlockElement(element.firstElementChild)) { + const attributes = this.getBlockAttributes(element); + const htmlAttributes = this.getBlockHTMLAttributes(element); + if (element.firstChild) { + if (!(currentBlockContainsElement && arraysAreEqual(attributes, this.currentBlock.attributes))) { + this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes); + this.currentBlockElement = element; + } else { + return this.appendStringWithAttributes("\n"); + } + } + } + } else if (this.currentBlockElement && !currentBlockContainsElement && !elementIsBlockElement) { + const parentBlockElement = this.findParentBlockElement(element); + if (parentBlockElement) { + return this.appendBlockForElement(parentBlockElement); + } else { + this.currentBlock = this.appendEmptyBlock(); + this.currentBlockElement = null; + } + } + } + findParentBlockElement(element) { + let { + parentElement + } = element; + while (parentElement && parentElement !== this.containerElement) { + if (this.isBlockElement(parentElement) && this.blockElements.includes(parentElement)) { + return parentElement; + } else { + parentElement = parentElement.parentElement; + } + } + return null; + } + processTextNode(node) { + let string = node.data; + if (!elementCanDisplayPreformattedText(node.parentNode)) { + var _node$previousSibling; + string = squishBreakableWhitespace(string); + if (stringEndsWithWhitespace((_node$previousSibling = node.previousSibling) === null || _node$previousSibling === void 0 ? void 0 : _node$previousSibling.textContent)) { + string = leftTrimBreakableWhitespace(string); + } + } + return this.appendStringWithAttributes(string, this.getTextAttributes(node.parentNode)); + } + processElement(element) { + let attributes; + if (nodeIsAttachmentElement(element)) { + attributes = parseTrixDataAttribute(element, "attachment"); + if (Object.keys(attributes).length) { + const textAttributes = this.getTextAttributes(element); + this.appendAttachmentWithAttributes(attributes, textAttributes); + // We have everything we need so avoid processing inner nodes + element.innerHTML = ""; + } + return this.processedElements.push(element); + } else { + switch (tagName(element)) { + case "br": + if (!this.isExtraBR(element) && !this.isBlockElement(element.nextSibling)) { + this.appendStringWithAttributes("\n", this.getTextAttributes(element)); + } + return this.processedElements.push(element); + case "img": + attributes = { + url: element.getAttribute("src"), + contentType: "image" + }; + const object = getImageDimensions(element); + for (const key in object) { + const value = object[key]; + attributes[key] = value; + } + this.appendAttachmentWithAttributes(attributes, this.getTextAttributes(element)); + return this.processedElements.push(element); + case "tr": + if (this.needsTableSeparator(element)) { + return this.appendStringWithAttributes(parser.tableRowSeparator); + } + break; + case "td": + if (this.needsTableSeparator(element)) { + return this.appendStringWithAttributes(parser.tableCellSeparator); + } + break; + } + } + } + + // Document construction + + appendBlockForAttributesWithElement(attributes, element) { + let htmlAttributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + this.blockElements.push(element); + const block = blockForAttributes(attributes, htmlAttributes); + this.blocks.push(block); + return block; + } + appendEmptyBlock() { + return this.appendBlockForAttributesWithElement([], null); + } + appendStringWithAttributes(string, attributes) { + return this.appendPiece(pieceForString(string, attributes)); + } + appendAttachmentWithAttributes(attachment, attributes) { + return this.appendPiece(pieceForAttachment(attachment, attributes)); + } + appendPiece(piece) { + if (this.blocks.length === 0) { + this.appendEmptyBlock(); + } + return this.blocks[this.blocks.length - 1].text.push(piece); + } + appendStringToTextAtIndex(string, index) { + const { + text + } = this.blocks[index]; + const piece = text[text.length - 1]; + if ((piece === null || piece === void 0 ? void 0 : piece.type) === "string") { + piece.string += string; + } else { + return text.push(pieceForString(string)); + } + } + prependStringToTextAtIndex(string, index) { + const { + text + } = this.blocks[index]; + const piece = text[0]; + if ((piece === null || piece === void 0 ? void 0 : piece.type) === "string") { + piece.string = string + piece.string; + } else { + return text.unshift(pieceForString(string)); + } + } + + // Attribute parsing + + getTextAttributes(element) { + let value; + const attributes = {}; + for (const attribute in text_attributes) { + const configAttr = text_attributes[attribute]; + if (configAttr.tagName && findClosestElementFromNode(element, { + matchingSelector: configAttr.tagName, + untilNode: this.containerElement + })) { + attributes[attribute] = true; + } else if (configAttr.parser) { + value = configAttr.parser(element); + if (value) { + let attributeInheritedFromBlock = false; + for (const blockElement of this.findBlockElementAncestors(element)) { + if (configAttr.parser(blockElement) === value) { + attributeInheritedFromBlock = true; + break; + } + } + if (!attributeInheritedFromBlock) { + attributes[attribute] = value; + } + } + } else if (configAttr.styleProperty) { + value = element.style[configAttr.styleProperty]; + if (value) { + attributes[attribute] = value; + } + } + } + if (nodeIsAttachmentElement(element)) { + const object = parseTrixDataAttribute(element, "attributes"); + for (const key in object) { + value = object[key]; + attributes[key] = value; + } + } + return attributes; + } + getBlockAttributes(element) { + const attributes$1 = []; + while (element && element !== this.containerElement) { + for (const attribute in attributes) { + const attrConfig = attributes[attribute]; + if (attrConfig.parse !== false) { + if (tagName(element) === attrConfig.tagName) { + var _attrConfig$test; + if ((_attrConfig$test = attrConfig.test) !== null && _attrConfig$test !== void 0 && _attrConfig$test.call(attrConfig, element) || !attrConfig.test) { + attributes$1.push(attribute); + if (attrConfig.listAttribute) { + attributes$1.push(attrConfig.listAttribute); + } + } + } + } + } + element = element.parentNode; + } + return attributes$1.reverse(); + } + getBlockHTMLAttributes(element) { + const attributes$1 = {}; + const blockConfig = Object.values(attributes).find(settings => settings.tagName === tagName(element)); + const allowedAttributes = (blockConfig === null || blockConfig === void 0 ? void 0 : blockConfig.htmlAttributes) || []; + allowedAttributes.forEach(attribute => { + if (element.hasAttribute(attribute)) { + attributes$1[attribute] = element.getAttribute(attribute); + } + }); + return attributes$1; + } + findBlockElementAncestors(element) { + const ancestors = []; + while (element && element !== this.containerElement) { + const tag = tagName(element); + if (getBlockTagNames().includes(tag)) { + ancestors.push(element); + } + element = element.parentNode; + } + return ancestors; + } + + // Element inspection + + isBlockElement(element) { + if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) return; + if (nodeIsAttachmentElement(element)) return; + if (findClosestElementFromNode(element, { + matchingSelector: "td", + untilNode: this.containerElement + })) return; + return getBlockTagNames().includes(tagName(element)) || window.getComputedStyle(element).display === "block"; + } + isInsignificantTextNode(node) { + if ((node === null || node === void 0 ? void 0 : node.nodeType) !== Node.TEXT_NODE) return; + if (!stringIsAllBreakableWhitespace(node.data)) return; + const { + parentNode, + previousSibling, + nextSibling + } = node; + if (nodeEndsWithNonWhitespace(parentNode.previousSibling) && !this.isBlockElement(parentNode.previousSibling)) return; + if (elementCanDisplayPreformattedText(parentNode)) return; + return !previousSibling || this.isBlockElement(previousSibling) || !nextSibling || this.isBlockElement(nextSibling); + } + isExtraBR(element) { + return tagName(element) === "br" && this.isBlockElement(element.parentNode) && element.parentNode.lastChild === element; + } + needsTableSeparator(element) { + if (parser.removeBlankTableCells) { + var _element$previousSibl; + const content = (_element$previousSibl = element.previousSibling) === null || _element$previousSibl === void 0 ? void 0 : _element$previousSibl.textContent; + return content && /\S/.test(content); + } else { + return element.previousSibling; + } + } + + // Margin translation + + translateBlockElementMarginsToNewlines() { + const defaultMargin = this.getMarginOfDefaultBlockElement(); + for (let index = 0; index < this.blocks.length; index++) { + const margin = this.getMarginOfBlockElementAtIndex(index); + if (margin) { + if (margin.top > defaultMargin.top * 2) { + this.prependStringToTextAtIndex("\n", index); + } + if (margin.bottom > defaultMargin.bottom * 2) { + this.appendStringToTextAtIndex("\n", index); + } + } + } + } + getMarginOfBlockElementAtIndex(index) { + const element = this.blockElements[index]; + if (element) { + if (element.textContent) { + if (!getBlockTagNames().includes(tagName(element)) && !this.processedElements.includes(element)) { + return getBlockElementMargin(element); + } + } + } + } + getMarginOfDefaultBlockElement() { + const element = makeElement(attributes.default.tagName); + this.containerElement.appendChild(element); + return getBlockElementMargin(element); + } + } + + // Helpers + + const elementCanDisplayPreformattedText = function (element) { + const { + whiteSpace + } = window.getComputedStyle(element); + return ["pre", "pre-wrap", "pre-line"].includes(whiteSpace); + }; + const nodeEndsWithNonWhitespace = node => node && !stringEndsWithWhitespace(node.textContent); + const getBlockElementMargin = function (element) { + const style = window.getComputedStyle(element); + if (style.display === "block") { + return { + top: parseInt(style.marginTop), + bottom: parseInt(style.marginBottom) + }; + } + }; + const nodeFilter = function (node) { + if (tagName(node) === "style") { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }; + + // Whitespace + + const leftTrimBreakableWhitespace = string => string.replace(new RegExp("^".concat(breakableWhitespacePattern.source, "+")), ""); + const stringIsAllBreakableWhitespace = string => new RegExp("^".concat(breakableWhitespacePattern.source, "*$")).test(string); + const stringEndsWithWhitespace = string => /\s$/.test(string); + + /* eslint-disable + no-empty, + */ + const unserializableElementSelector = "[data-trix-serialize=false]"; + const unserializableAttributeNames = ["contenteditable", "data-trix-id", "data-trix-store-key", "data-trix-mutable", "data-trix-placeholder", "tabindex"]; + const serializedAttributesAttribute = "data-trix-serialized-attributes"; + const serializedAttributesSelector = "[".concat(serializedAttributesAttribute, "]"); + const blockCommentPattern = new RegExp("", "g"); + const serializers = { + "application/json": function (serializable) { + let document; + if (serializable instanceof Document) { + document = serializable; + } else if (serializable instanceof HTMLElement) { + document = HTMLParser.parse(serializable.innerHTML).getDocument(); + } else { + throw new Error("unserializable object"); + } + return document.toSerializableDocument().toJSONString(); + }, + "text/html": function (serializable) { + let element; + if (serializable instanceof Document) { + element = DocumentView.render(serializable); + } else if (serializable instanceof HTMLElement) { + element = serializable.cloneNode(true); + } else { + throw new Error("unserializable object"); + } + + // Remove unserializable elements + Array.from(element.querySelectorAll(unserializableElementSelector)).forEach(el => { + removeNode(el); + }); + + // Remove unserializable attributes + unserializableAttributeNames.forEach(attribute => { + Array.from(element.querySelectorAll("[".concat(attribute, "]"))).forEach(el => { + el.removeAttribute(attribute); + }); + }); + + // Rewrite elements with serialized attribute overrides + Array.from(element.querySelectorAll(serializedAttributesSelector)).forEach(el => { + try { + const attributes = JSON.parse(el.getAttribute(serializedAttributesAttribute)); + el.removeAttribute(serializedAttributesAttribute); + for (const name in attributes) { + const value = attributes[name]; + el.setAttribute(name, value); + } + } catch (error) {} + }); + return element.innerHTML.replace(blockCommentPattern, ""); + } + }; + const deserializers = { + "application/json": function (string) { + return Document.fromJSONString(string); + }, + "text/html": function (string) { + return HTMLParser.parse(string).getDocument(); + } + }; + const serializeToContentType = function (serializable, contentType) { + const serializer = serializers[contentType]; + if (serializer) { + return serializer(serializable); + } else { + throw new Error("unknown content type: ".concat(contentType)); + } + }; + const deserializeFromContentType = function (string, contentType) { + const deserializer = deserializers[contentType]; + if (deserializer) { + return deserializer(string); + } else { + throw new Error("unknown content type: ".concat(contentType)); + } + }; + + var core = /*#__PURE__*/Object.freeze({ + __proto__: null + }); + + class ManagedAttachment extends BasicObject { + constructor(attachmentManager, attachment) { + super(...arguments); + this.attachmentManager = attachmentManager; + this.attachment = attachment; + this.id = this.attachment.id; + this.file = this.attachment.file; + } + remove() { + return this.attachmentManager.requestRemovalOfAttachment(this.attachment); + } + } + ManagedAttachment.proxyMethod("attachment.getAttribute"); + ManagedAttachment.proxyMethod("attachment.hasAttribute"); + ManagedAttachment.proxyMethod("attachment.setAttribute"); + ManagedAttachment.proxyMethod("attachment.getAttributes"); + ManagedAttachment.proxyMethod("attachment.setAttributes"); + ManagedAttachment.proxyMethod("attachment.isPending"); + ManagedAttachment.proxyMethod("attachment.isPreviewable"); + ManagedAttachment.proxyMethod("attachment.getURL"); + ManagedAttachment.proxyMethod("attachment.getHref"); + ManagedAttachment.proxyMethod("attachment.getFilename"); + ManagedAttachment.proxyMethod("attachment.getFilesize"); + ManagedAttachment.proxyMethod("attachment.getFormattedFilesize"); + ManagedAttachment.proxyMethod("attachment.getExtension"); + ManagedAttachment.proxyMethod("attachment.getContentType"); + ManagedAttachment.proxyMethod("attachment.getFile"); + ManagedAttachment.proxyMethod("attachment.setFile"); + ManagedAttachment.proxyMethod("attachment.releaseFile"); + ManagedAttachment.proxyMethod("attachment.getUploadProgress"); + ManagedAttachment.proxyMethod("attachment.setUploadProgress"); + + class AttachmentManager extends BasicObject { + constructor() { + let attachments = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + super(...arguments); + this.managedAttachments = {}; + Array.from(attachments).forEach(attachment => { + this.manageAttachment(attachment); + }); + } + getAttachments() { + const result = []; + for (const id in this.managedAttachments) { + const attachment = this.managedAttachments[id]; + result.push(attachment); + } + return result; + } + manageAttachment(attachment) { + if (!this.managedAttachments[attachment.id]) { + this.managedAttachments[attachment.id] = new ManagedAttachment(this, attachment); + } + return this.managedAttachments[attachment.id]; + } + attachmentIsManaged(attachment) { + return attachment.id in this.managedAttachments; + } + requestRemovalOfAttachment(attachment) { + if (this.attachmentIsManaged(attachment)) { + var _this$delegate, _this$delegate$attach; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$attach = _this$delegate.attachmentManagerDidRequestRemovalOfAttachment) === null || _this$delegate$attach === void 0 ? void 0 : _this$delegate$attach.call(_this$delegate, attachment); + } + } + unmanageAttachment(attachment) { + const managedAttachment = this.managedAttachments[attachment.id]; + delete this.managedAttachments[attachment.id]; + return managedAttachment; + } + } + + class LineBreakInsertion { + constructor(composition) { + this.composition = composition; + this.document = this.composition.document; + const selectedRange = this.composition.getSelectedRange(); + this.startPosition = selectedRange[0]; + this.endPosition = selectedRange[1]; + this.startLocation = this.document.locationFromPosition(this.startPosition); + this.endLocation = this.document.locationFromPosition(this.endPosition); + this.block = this.document.getBlockAtIndex(this.endLocation.index); + this.breaksOnReturn = this.block.breaksOnReturn(); + this.previousCharacter = this.block.text.getStringAtPosition(this.endLocation.offset - 1); + this.nextCharacter = this.block.text.getStringAtPosition(this.endLocation.offset); + } + shouldInsertBlockBreak() { + if (this.block.hasAttributes() && this.block.isListItem() && !this.block.isEmpty()) { + return this.startLocation.offset !== 0; + } else { + return this.breaksOnReturn && this.nextCharacter !== "\n"; + } + } + shouldBreakFormattedBlock() { + return this.block.hasAttributes() && !this.block.isListItem() && (this.breaksOnReturn && this.nextCharacter === "\n" || this.previousCharacter === "\n"); + } + shouldDecreaseListLevel() { + return this.block.hasAttributes() && this.block.isListItem() && this.block.isEmpty(); + } + shouldPrependListItem() { + return this.block.isListItem() && this.startLocation.offset === 0 && !this.block.isEmpty(); + } + shouldRemoveLastBlockAttribute() { + return this.block.hasAttributes() && !this.block.isListItem() && this.block.isEmpty(); + } + } + + const PLACEHOLDER = " "; + class Composition extends BasicObject { + constructor() { + super(...arguments); + this.document = new Document(); + this.attachments = []; + this.currentAttributes = {}; + this.revision = 0; + } + setDocument(document) { + if (!document.isEqualTo(this.document)) { + var _this$delegate, _this$delegate$compos; + this.document = document; + this.refreshAttachments(); + this.revision++; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$compos = _this$delegate.compositionDidChangeDocument) === null || _this$delegate$compos === void 0 ? void 0 : _this$delegate$compos.call(_this$delegate, document); + } + } + + // Snapshots + + getSnapshot() { + return { + document: this.document, + selectedRange: this.getSelectedRange() + }; + } + loadSnapshot(_ref) { + var _this$delegate2, _this$delegate2$compo, _this$delegate3, _this$delegate3$compo; + let { + document, + selectedRange + } = _ref; + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$compo = _this$delegate2.compositionWillLoadSnapshot) === null || _this$delegate2$compo === void 0 || _this$delegate2$compo.call(_this$delegate2); + this.setDocument(document != null ? document : new Document()); + this.setSelection(selectedRange != null ? selectedRange : [0, 0]); + return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$compo = _this$delegate3.compositionDidLoadSnapshot) === null || _this$delegate3$compo === void 0 ? void 0 : _this$delegate3$compo.call(_this$delegate3); + } + + // Responder protocol + + insertText(text) { + let { + updatePosition + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + updatePosition: true + }; + const selectedRange = this.getSelectedRange(); + this.setDocument(this.document.insertTextAtRange(text, selectedRange)); + const startPosition = selectedRange[0]; + const endPosition = startPosition + text.getLength(); + if (updatePosition) { + this.setSelection(endPosition); + } + return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); + } + insertBlock() { + let block = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Block(); + const document = new Document([block]); + return this.insertDocument(document); + } + insertDocument() { + let document = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Document(); + const selectedRange = this.getSelectedRange(); + this.setDocument(this.document.insertDocumentAtRange(document, selectedRange)); + const startPosition = selectedRange[0]; + const endPosition = startPosition + document.getLength(); + this.setSelection(endPosition); + return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); + } + insertString(string, options) { + const attributes = this.getCurrentTextAttributes(); + const text = Text.textForStringWithAttributes(string, attributes); + return this.insertText(text, options); + } + insertBlockBreak() { + const selectedRange = this.getSelectedRange(); + this.setDocument(this.document.insertBlockBreakAtRange(selectedRange)); + const startPosition = selectedRange[0]; + const endPosition = startPosition + 1; + this.setSelection(endPosition); + return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); + } + insertLineBreak() { + const insertion = new LineBreakInsertion(this); + if (insertion.shouldDecreaseListLevel()) { + this.decreaseListLevel(); + return this.setSelection(insertion.startPosition); + } else if (insertion.shouldPrependListItem()) { + const document = new Document([insertion.block.copyWithoutText()]); + return this.insertDocument(document); + } else if (insertion.shouldInsertBlockBreak()) { + return this.insertBlockBreak(); + } else if (insertion.shouldRemoveLastBlockAttribute()) { + return this.removeLastBlockAttribute(); + } else if (insertion.shouldBreakFormattedBlock()) { + return this.breakFormattedBlock(insertion); + } else { + return this.insertString("\n"); + } + } + insertHTML(html) { + const document = HTMLParser.parse(html).getDocument(); + const selectedRange = this.getSelectedRange(); + this.setDocument(this.document.mergeDocumentAtRange(document, selectedRange)); + const startPosition = selectedRange[0]; + const endPosition = startPosition + document.getLength() - 1; + this.setSelection(endPosition); + return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]); + } + replaceHTML(html) { + const document = HTMLParser.parse(html).getDocument().copyUsingObjectsFromDocument(this.document); + const locationRange = this.getLocationRange({ + strict: false + }); + const selectedRange = this.document.rangeFromLocationRange(locationRange); + this.setDocument(document); + return this.setSelection(selectedRange); + } + insertFile(file) { + return this.insertFiles([file]); + } + insertFiles(files) { + const attachments = []; + Array.from(files).forEach(file => { + var _this$delegate4; + if ((_this$delegate4 = this.delegate) !== null && _this$delegate4 !== void 0 && _this$delegate4.compositionShouldAcceptFile(file)) { + const attachment = Attachment.attachmentForFile(file); + attachments.push(attachment); + } + }); + return this.insertAttachments(attachments); + } + insertAttachment(attachment) { + return this.insertAttachments([attachment]); + } + insertAttachments(attachments$1) { + let text = new Text(); + Array.from(attachments$1).forEach(attachment => { + var _config$attachments$t; + const type = attachment.getType(); + const presentation = (_config$attachments$t = attachments[type]) === null || _config$attachments$t === void 0 ? void 0 : _config$attachments$t.presentation; + const attributes = this.getCurrentTextAttributes(); + if (presentation) { + attributes.presentation = presentation; + } + const attachmentText = Text.textForAttachmentWithAttributes(attachment, attributes); + text = text.appendText(attachmentText); + }); + return this.insertText(text); + } + shouldManageDeletingInDirection(direction) { + const locationRange = this.getLocationRange(); + if (rangeIsCollapsed(locationRange)) { + if (direction === "backward" && locationRange[0].offset === 0) { + return true; + } + if (this.shouldManageMovingCursorInDirection(direction)) { + return true; + } + } else { + if (locationRange[0].index !== locationRange[1].index) { + return true; + } + } + return false; + } + deleteInDirection(direction) { + let { + length + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let attachment, deletingIntoPreviousBlock, selectionSpansBlocks; + const locationRange = this.getLocationRange(); + let range = this.getSelectedRange(); + const selectionIsCollapsed = rangeIsCollapsed(range); + if (selectionIsCollapsed) { + deletingIntoPreviousBlock = direction === "backward" && locationRange[0].offset === 0; + } else { + selectionSpansBlocks = locationRange[0].index !== locationRange[1].index; + } + if (deletingIntoPreviousBlock) { + if (this.canDecreaseBlockAttributeLevel()) { + const block = this.getBlock(); + if (block.isListItem()) { + this.decreaseListLevel(); + } else { + this.decreaseBlockAttributeLevel(); + } + this.setSelection(range[0]); + if (block.isEmpty()) { + return false; + } + } + } + if (selectionIsCollapsed) { + range = this.getExpandedRangeInDirection(direction, { + length + }); + if (direction === "backward") { + attachment = this.getAttachmentAtRange(range); + } + } + if (attachment) { + this.editAttachment(attachment); + return false; + } else { + this.setDocument(this.document.removeTextAtRange(range)); + this.setSelection(range[0]); + if (deletingIntoPreviousBlock || selectionSpansBlocks) { + return false; + } + } + } + moveTextFromRange(range) { + const [position] = Array.from(this.getSelectedRange()); + this.setDocument(this.document.moveTextFromRangeToPosition(range, position)); + return this.setSelection(position); + } + removeAttachment(attachment) { + const range = this.document.getRangeOfAttachment(attachment); + if (range) { + this.stopEditingAttachment(); + this.setDocument(this.document.removeTextAtRange(range)); + return this.setSelection(range[0]); + } + } + removeLastBlockAttribute() { + const [startPosition, endPosition] = Array.from(this.getSelectedRange()); + const block = this.document.getBlockAtPosition(endPosition); + this.removeCurrentAttribute(block.getLastAttribute()); + return this.setSelection(startPosition); + } + insertPlaceholder() { + this.placeholderPosition = this.getPosition(); + return this.insertString(PLACEHOLDER); + } + selectPlaceholder() { + if (this.placeholderPosition != null) { + this.setSelectedRange([this.placeholderPosition, this.placeholderPosition + PLACEHOLDER.length]); + return this.getSelectedRange(); + } + } + forgetPlaceholder() { + this.placeholderPosition = null; + } + + // Current attributes + + hasCurrentAttribute(attributeName) { + const value = this.currentAttributes[attributeName]; + return value != null && value !== false; + } + toggleCurrentAttribute(attributeName) { + const value = !this.currentAttributes[attributeName]; + if (value) { + return this.setCurrentAttribute(attributeName, value); + } else { + return this.removeCurrentAttribute(attributeName); + } + } + canSetCurrentAttribute(attributeName) { + if (getBlockConfig(attributeName)) { + return this.canSetCurrentBlockAttribute(attributeName); + } else { + return this.canSetCurrentTextAttribute(attributeName); + } + } + canSetCurrentTextAttribute(attributeName) { + const document = this.getSelectedDocument(); + if (!document) return; + for (const attachment of Array.from(document.getAttachments())) { + if (!attachment.hasContent()) { + return false; + } + } + return true; + } + canSetCurrentBlockAttribute(attributeName) { + const block = this.getBlock(); + if (!block) return; + return !block.isTerminalBlock(); + } + setCurrentAttribute(attributeName, value) { + if (getBlockConfig(attributeName)) { + return this.setBlockAttribute(attributeName, value); + } else { + this.setTextAttribute(attributeName, value); + this.currentAttributes[attributeName] = value; + return this.notifyDelegateOfCurrentAttributesChange(); + } + } + setHTMLAtributeAtPosition(position, attributeName, value) { + var _getBlockConfig; + const block = this.document.getBlockAtPosition(position); + const allowedHTMLAttributes = (_getBlockConfig = getBlockConfig(block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.htmlAttributes; + if (block && allowedHTMLAttributes !== null && allowedHTMLAttributes !== void 0 && allowedHTMLAttributes.includes(attributeName)) { + const newDocument = this.document.setHTMLAttributeAtPosition(position, attributeName, value); + this.setDocument(newDocument); + } + } + setTextAttribute(attributeName, value) { + const selectedRange = this.getSelectedRange(); + if (!selectedRange) return; + const [startPosition, endPosition] = Array.from(selectedRange); + if (startPosition === endPosition) { + if (attributeName === "href") { + const text = Text.textForStringWithAttributes(value, { + href: value + }); + return this.insertText(text); + } + } else { + return this.setDocument(this.document.addAttributeAtRange(attributeName, value, selectedRange)); + } + } + setBlockAttribute(attributeName, value) { + const selectedRange = this.getSelectedRange(); + if (this.canSetCurrentAttribute(attributeName)) { + this.setDocument(this.document.applyBlockAttributeAtRange(attributeName, value, selectedRange)); + return this.setSelection(selectedRange); + } + } + removeCurrentAttribute(attributeName) { + if (getBlockConfig(attributeName)) { + this.removeBlockAttribute(attributeName); + return this.updateCurrentAttributes(); + } else { + this.removeTextAttribute(attributeName); + delete this.currentAttributes[attributeName]; + return this.notifyDelegateOfCurrentAttributesChange(); + } + } + removeTextAttribute(attributeName) { + const selectedRange = this.getSelectedRange(); + if (!selectedRange) return; + return this.setDocument(this.document.removeAttributeAtRange(attributeName, selectedRange)); + } + removeBlockAttribute(attributeName) { + const selectedRange = this.getSelectedRange(); + if (!selectedRange) return; + return this.setDocument(this.document.removeAttributeAtRange(attributeName, selectedRange)); + } + canDecreaseNestingLevel() { + var _this$getBlock; + return ((_this$getBlock = this.getBlock()) === null || _this$getBlock === void 0 ? void 0 : _this$getBlock.getNestingLevel()) > 0; + } + canIncreaseNestingLevel() { + var _getBlockConfig2; + const block = this.getBlock(); + if (!block) return; + if ((_getBlockConfig2 = getBlockConfig(block.getLastNestableAttribute())) !== null && _getBlockConfig2 !== void 0 && _getBlockConfig2.listAttribute) { + const previousBlock = this.getPreviousBlock(); + if (previousBlock) { + return arrayStartsWith(previousBlock.getListItemAttributes(), block.getListItemAttributes()); + } + } else { + return block.getNestingLevel() > 0; + } + } + decreaseNestingLevel() { + const block = this.getBlock(); + if (!block) return; + return this.setDocument(this.document.replaceBlock(block, block.decreaseNestingLevel())); + } + increaseNestingLevel() { + const block = this.getBlock(); + if (!block) return; + return this.setDocument(this.document.replaceBlock(block, block.increaseNestingLevel())); + } + canDecreaseBlockAttributeLevel() { + var _this$getBlock2; + return ((_this$getBlock2 = this.getBlock()) === null || _this$getBlock2 === void 0 ? void 0 : _this$getBlock2.getAttributeLevel()) > 0; + } + decreaseBlockAttributeLevel() { + var _this$getBlock3; + const attribute = (_this$getBlock3 = this.getBlock()) === null || _this$getBlock3 === void 0 ? void 0 : _this$getBlock3.getLastAttribute(); + if (attribute) { + return this.removeCurrentAttribute(attribute); + } + } + decreaseListLevel() { + let [startPosition] = Array.from(this.getSelectedRange()); + const { + index + } = this.document.locationFromPosition(startPosition); + let endIndex = index; + const attributeLevel = this.getBlock().getAttributeLevel(); + let block = this.document.getBlockAtIndex(endIndex + 1); + while (block) { + if (!block.isListItem() || block.getAttributeLevel() <= attributeLevel) { + break; + } + endIndex++; + block = this.document.getBlockAtIndex(endIndex + 1); + } + startPosition = this.document.positionFromLocation({ + index, + offset: 0 + }); + const endPosition = this.document.positionFromLocation({ + index: endIndex, + offset: 0 + }); + return this.setDocument(this.document.removeLastListAttributeAtRange([startPosition, endPosition])); + } + updateCurrentAttributes() { + const selectedRange = this.getSelectedRange({ + ignoreLock: true + }); + if (selectedRange) { + const currentAttributes = this.document.getCommonAttributesAtRange(selectedRange); + Array.from(getAllAttributeNames()).forEach(attributeName => { + if (!currentAttributes[attributeName]) { + if (!this.canSetCurrentAttribute(attributeName)) { + currentAttributes[attributeName] = false; + } + } + }); + if (!objectsAreEqual(currentAttributes, this.currentAttributes)) { + this.currentAttributes = currentAttributes; + return this.notifyDelegateOfCurrentAttributesChange(); + } + } + } + getCurrentAttributes() { + return extend.call({}, this.currentAttributes); + } + getCurrentTextAttributes() { + const attributes = {}; + for (const key in this.currentAttributes) { + const value = this.currentAttributes[key]; + if (value !== false) { + if (getTextConfig(key)) { + attributes[key] = value; + } + } + } + return attributes; + } + + // Selection freezing + + freezeSelection() { + return this.setCurrentAttribute("frozen", true); + } + thawSelection() { + return this.removeCurrentAttribute("frozen"); + } + hasFrozenSelection() { + return this.hasCurrentAttribute("frozen"); + } + setSelection(selectedRange) { + var _this$delegate5; + const locationRange = this.document.locationRangeFromRange(selectedRange); + return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : _this$delegate5.compositionDidRequestChangingSelectionToLocationRange(locationRange); + } + getSelectedRange() { + const locationRange = this.getLocationRange(); + if (locationRange) { + return this.document.rangeFromLocationRange(locationRange); + } + } + setSelectedRange(selectedRange) { + const locationRange = this.document.locationRangeFromRange(selectedRange); + return this.getSelectionManager().setLocationRange(locationRange); + } + getPosition() { + const locationRange = this.getLocationRange(); + if (locationRange) { + return this.document.positionFromLocation(locationRange[0]); + } + } + getLocationRange(options) { + if (this.targetLocationRange) { + return this.targetLocationRange; + } else { + return this.getSelectionManager().getLocationRange(options) || normalizeRange({ + index: 0, + offset: 0 + }); + } + } + withTargetLocationRange(locationRange, fn) { + let result; + this.targetLocationRange = locationRange; + try { + result = fn(); + } finally { + this.targetLocationRange = null; + } + return result; + } + withTargetRange(range, fn) { + const locationRange = this.document.locationRangeFromRange(range); + return this.withTargetLocationRange(locationRange, fn); + } + withTargetDOMRange(domRange, fn) { + const locationRange = this.createLocationRangeFromDOMRange(domRange, { + strict: false + }); + return this.withTargetLocationRange(locationRange, fn); + } + getExpandedRangeInDirection(direction) { + let { + length + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + let [startPosition, endPosition] = Array.from(this.getSelectedRange()); + if (direction === "backward") { + if (length) { + startPosition -= length; + } else { + startPosition = this.translateUTF16PositionFromOffset(startPosition, -1); + } + } else { + if (length) { + endPosition += length; + } else { + endPosition = this.translateUTF16PositionFromOffset(endPosition, 1); + } + } + return normalizeRange([startPosition, endPosition]); + } + shouldManageMovingCursorInDirection(direction) { + if (this.editingAttachment) { + return true; + } + const range = this.getExpandedRangeInDirection(direction); + return this.getAttachmentAtRange(range) != null; + } + moveCursorInDirection(direction) { + let canEditAttachment, range; + if (this.editingAttachment) { + range = this.document.getRangeOfAttachment(this.editingAttachment); + } else { + const selectedRange = this.getSelectedRange(); + range = this.getExpandedRangeInDirection(direction); + canEditAttachment = !rangesAreEqual(selectedRange, range); + } + if (direction === "backward") { + this.setSelectedRange(range[0]); + } else { + this.setSelectedRange(range[1]); + } + if (canEditAttachment) { + const attachment = this.getAttachmentAtRange(range); + if (attachment) { + return this.editAttachment(attachment); + } + } + } + expandSelectionInDirection(direction) { + let { + length + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const range = this.getExpandedRangeInDirection(direction, { + length + }); + return this.setSelectedRange(range); + } + expandSelectionForEditing() { + if (this.hasCurrentAttribute("href")) { + return this.expandSelectionAroundCommonAttribute("href"); + } + } + expandSelectionAroundCommonAttribute(attributeName) { + const position = this.getPosition(); + const range = this.document.getRangeOfCommonAttributeAtPosition(attributeName, position); + return this.setSelectedRange(range); + } + selectionContainsAttachments() { + var _this$getSelectedAtta; + return ((_this$getSelectedAtta = this.getSelectedAttachments()) === null || _this$getSelectedAtta === void 0 ? void 0 : _this$getSelectedAtta.length) > 0; + } + selectionIsInCursorTarget() { + return this.editingAttachment || this.positionIsCursorTarget(this.getPosition()); + } + positionIsCursorTarget(position) { + const location = this.document.locationFromPosition(position); + if (location) { + return this.locationIsCursorTarget(location); + } + } + positionIsBlockBreak(position) { + var _this$document$getPie; + return (_this$document$getPie = this.document.getPieceAtPosition(position)) === null || _this$document$getPie === void 0 ? void 0 : _this$document$getPie.isBlockBreak(); + } + getSelectedDocument() { + const selectedRange = this.getSelectedRange(); + if (selectedRange) { + return this.document.getDocumentAtRange(selectedRange); + } + } + getSelectedAttachments() { + var _this$getSelectedDocu; + return (_this$getSelectedDocu = this.getSelectedDocument()) === null || _this$getSelectedDocu === void 0 ? void 0 : _this$getSelectedDocu.getAttachments(); + } + + // Attachments + + getAttachments() { + return this.attachments.slice(0); + } + refreshAttachments() { + const attachments = this.document.getAttachments(); + const { + added, + removed + } = summarizeArrayChange(this.attachments, attachments); + this.attachments = attachments; + Array.from(removed).forEach(attachment => { + var _this$delegate6, _this$delegate6$compo; + attachment.delegate = null; + (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$compo = _this$delegate6.compositionDidRemoveAttachment) === null || _this$delegate6$compo === void 0 || _this$delegate6$compo.call(_this$delegate6, attachment); + }); + return (() => { + const result = []; + Array.from(added).forEach(attachment => { + var _this$delegate7, _this$delegate7$compo; + attachment.delegate = this; + result.push((_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$compo = _this$delegate7.compositionDidAddAttachment) === null || _this$delegate7$compo === void 0 ? void 0 : _this$delegate7$compo.call(_this$delegate7, attachment)); + }); + return result; + })(); + } + + // Attachment delegate + + attachmentDidChangeAttributes(attachment) { + var _this$delegate8, _this$delegate8$compo; + this.revision++; + return (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || (_this$delegate8$compo = _this$delegate8.compositionDidEditAttachment) === null || _this$delegate8$compo === void 0 ? void 0 : _this$delegate8$compo.call(_this$delegate8, attachment); + } + attachmentDidChangePreviewURL(attachment) { + var _this$delegate9, _this$delegate9$compo; + this.revision++; + return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || (_this$delegate9$compo = _this$delegate9.compositionDidChangeAttachmentPreviewURL) === null || _this$delegate9$compo === void 0 ? void 0 : _this$delegate9$compo.call(_this$delegate9, attachment); + } + + // Attachment editing + + editAttachment(attachment, options) { + var _this$delegate10, _this$delegate10$comp; + if (attachment === this.editingAttachment) return; + this.stopEditingAttachment(); + this.editingAttachment = attachment; + return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || (_this$delegate10$comp = _this$delegate10.compositionDidStartEditingAttachment) === null || _this$delegate10$comp === void 0 ? void 0 : _this$delegate10$comp.call(_this$delegate10, this.editingAttachment, options); + } + stopEditingAttachment() { + var _this$delegate11, _this$delegate11$comp; + if (!this.editingAttachment) return; + (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 || (_this$delegate11$comp = _this$delegate11.compositionDidStopEditingAttachment) === null || _this$delegate11$comp === void 0 || _this$delegate11$comp.call(_this$delegate11, this.editingAttachment); + this.editingAttachment = null; + } + updateAttributesForAttachment(attributes, attachment) { + return this.setDocument(this.document.updateAttributesForAttachment(attributes, attachment)); + } + removeAttributeForAttachment(attribute, attachment) { + return this.setDocument(this.document.removeAttributeForAttachment(attribute, attachment)); + } + + // Private + + breakFormattedBlock(insertion) { + let { + document + } = insertion; + const { + block + } = insertion; + let position = insertion.startPosition; + let range = [position - 1, position]; + if (block.getBlockBreakPosition() === insertion.startLocation.offset) { + if (block.breaksOnReturn() && insertion.nextCharacter === "\n") { + position += 1; + } else { + document = document.removeTextAtRange(range); + } + range = [position, position]; + } else if (insertion.nextCharacter === "\n") { + if (insertion.previousCharacter === "\n") { + range = [position - 1, position + 1]; + } else { + range = [position, position + 1]; + position += 1; + } + } else if (insertion.startLocation.offset - 1 !== 0) { + position += 1; + } + const newDocument = new Document([block.removeLastAttribute().copyWithoutText()]); + this.setDocument(document.insertDocumentAtRange(newDocument, range)); + return this.setSelection(position); + } + getPreviousBlock() { + const locationRange = this.getLocationRange(); + if (locationRange) { + const { + index + } = locationRange[0]; + if (index > 0) { + return this.document.getBlockAtIndex(index - 1); + } + } + } + getBlock() { + const locationRange = this.getLocationRange(); + if (locationRange) { + return this.document.getBlockAtIndex(locationRange[0].index); + } + } + getAttachmentAtRange(range) { + const document = this.document.getDocumentAtRange(range); + if (document.toString() === "".concat(OBJECT_REPLACEMENT_CHARACTER, "\n")) { + return document.getAttachments()[0]; + } + } + notifyDelegateOfCurrentAttributesChange() { + var _this$delegate12, _this$delegate12$comp; + return (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 || (_this$delegate12$comp = _this$delegate12.compositionDidChangeCurrentAttributes) === null || _this$delegate12$comp === void 0 ? void 0 : _this$delegate12$comp.call(_this$delegate12, this.currentAttributes); + } + notifyDelegateOfInsertionAtRange(range) { + var _this$delegate13, _this$delegate13$comp; + return (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || (_this$delegate13$comp = _this$delegate13.compositionDidPerformInsertionAtRange) === null || _this$delegate13$comp === void 0 ? void 0 : _this$delegate13$comp.call(_this$delegate13, range); + } + translateUTF16PositionFromOffset(position, offset) { + const utf16string = this.document.toUTF16String(); + const utf16position = utf16string.offsetFromUCS2Offset(position); + return utf16string.offsetToUCS2Offset(utf16position + offset); + } + } + Composition.proxyMethod("getSelectionManager().getPointRange"); + Composition.proxyMethod("getSelectionManager().setLocationRangeFromPointRange"); + Composition.proxyMethod("getSelectionManager().createLocationRangeFromDOMRange"); + Composition.proxyMethod("getSelectionManager().locationIsCursorTarget"); + Composition.proxyMethod("getSelectionManager().selectionIsExpanded"); + Composition.proxyMethod("delegate?.getSelectionManager"); + + class UndoManager extends BasicObject { + constructor(composition) { + super(...arguments); + this.composition = composition; + this.undoEntries = []; + this.redoEntries = []; + } + recordUndoEntry(description) { + let { + context, + consolidatable + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + const previousEntry = this.undoEntries.slice(-1)[0]; + if (!consolidatable || !entryHasDescriptionAndContext(previousEntry, description, context)) { + const undoEntry = this.createEntry({ + description, + context + }); + this.undoEntries.push(undoEntry); + this.redoEntries = []; + } + } + undo() { + const undoEntry = this.undoEntries.pop(); + if (undoEntry) { + const redoEntry = this.createEntry(undoEntry); + this.redoEntries.push(redoEntry); + return this.composition.loadSnapshot(undoEntry.snapshot); + } + } + redo() { + const redoEntry = this.redoEntries.pop(); + if (redoEntry) { + const undoEntry = this.createEntry(redoEntry); + this.undoEntries.push(undoEntry); + return this.composition.loadSnapshot(redoEntry.snapshot); + } + } + canUndo() { + return this.undoEntries.length > 0; + } + canRedo() { + return this.redoEntries.length > 0; + } + + // Private + + createEntry() { + let { + description, + context + } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return { + description: description === null || description === void 0 ? void 0 : description.toString(), + context: JSON.stringify(context), + snapshot: this.composition.getSnapshot() + }; + } + } + const entryHasDescriptionAndContext = (entry, description, context) => (entry === null || entry === void 0 ? void 0 : entry.description) === (description === null || description === void 0 ? void 0 : description.toString()) && (entry === null || entry === void 0 ? void 0 : entry.context) === JSON.stringify(context); + + const BLOCK_ATTRIBUTE_NAME = "attachmentGallery"; + const TEXT_ATTRIBUTE_NAME = "presentation"; + const TEXT_ATTRIBUTE_VALUE = "gallery"; + class Filter { + constructor(snapshot) { + this.document = snapshot.document; + this.selectedRange = snapshot.selectedRange; + } + perform() { + this.removeBlockAttribute(); + return this.applyBlockAttribute(); + } + getSnapshot() { + return { + document: this.document, + selectedRange: this.selectedRange + }; + } + + // Private + + removeBlockAttribute() { + return this.findRangesOfBlocks().map(range => this.document = this.document.removeAttributeAtRange(BLOCK_ATTRIBUTE_NAME, range)); + } + applyBlockAttribute() { + let offset = 0; + this.findRangesOfPieces().forEach(range => { + if (range[1] - range[0] > 1) { + range[0] += offset; + range[1] += offset; + if (this.document.getCharacterAtPosition(range[1]) !== "\n") { + this.document = this.document.insertBlockBreakAtRange(range[1]); + if (range[1] < this.selectedRange[1]) { + this.moveSelectedRangeForward(); + } + range[1]++; + offset++; + } + if (range[0] !== 0) { + if (this.document.getCharacterAtPosition(range[0] - 1) !== "\n") { + this.document = this.document.insertBlockBreakAtRange(range[0]); + if (range[0] < this.selectedRange[0]) { + this.moveSelectedRangeForward(); + } + range[0]++; + offset++; + } + } + this.document = this.document.applyBlockAttributeAtRange(BLOCK_ATTRIBUTE_NAME, true, range); + } + }); + } + findRangesOfBlocks() { + return this.document.findRangesForBlockAttribute(BLOCK_ATTRIBUTE_NAME); + } + findRangesOfPieces() { + return this.document.findRangesForTextAttribute(TEXT_ATTRIBUTE_NAME, { + withValue: TEXT_ATTRIBUTE_VALUE + }); + } + moveSelectedRangeForward() { + this.selectedRange[0] += 1; + this.selectedRange[1] += 1; + } + } + + const attachmentGalleryFilter = function (snapshot) { + const filter = new Filter(snapshot); + filter.perform(); + return filter.getSnapshot(); + }; + + const DEFAULT_FILTERS = [attachmentGalleryFilter]; + class Editor { + constructor(composition, selectionManager, element) { + this.insertFiles = this.insertFiles.bind(this); + this.composition = composition; + this.selectionManager = selectionManager; + this.element = element; + this.undoManager = new UndoManager(this.composition); + this.filters = DEFAULT_FILTERS.slice(0); + } + loadDocument(document) { + return this.loadSnapshot({ + document, + selectedRange: [0, 0] + }); + } + loadHTML() { + let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + const document = HTMLParser.parse(html, { + referenceElement: this.element + }).getDocument(); + return this.loadDocument(document); + } + loadJSON(_ref) { + let { + document, + selectedRange + } = _ref; + document = Document.fromJSON(document); + return this.loadSnapshot({ + document, + selectedRange + }); + } + loadSnapshot(snapshot) { + this.undoManager = new UndoManager(this.composition); + return this.composition.loadSnapshot(snapshot); + } + getDocument() { + return this.composition.document; + } + getSelectedDocument() { + return this.composition.getSelectedDocument(); + } + getSnapshot() { + return this.composition.getSnapshot(); + } + toJSON() { + return this.getSnapshot(); + } + + // Document manipulation + + deleteInDirection(direction) { + return this.composition.deleteInDirection(direction); + } + insertAttachment(attachment) { + return this.composition.insertAttachment(attachment); + } + insertAttachments(attachments) { + return this.composition.insertAttachments(attachments); + } + insertDocument(document) { + return this.composition.insertDocument(document); + } + insertFile(file) { + return this.composition.insertFile(file); + } + insertFiles(files) { + return this.composition.insertFiles(files); + } + insertHTML(html) { + return this.composition.insertHTML(html); + } + insertString(string) { + return this.composition.insertString(string); + } + insertText(text) { + return this.composition.insertText(text); + } + insertLineBreak() { + return this.composition.insertLineBreak(); + } + + // Selection + + getSelectedRange() { + return this.composition.getSelectedRange(); + } + getPosition() { + return this.composition.getPosition(); + } + getClientRectAtPosition(position) { + const locationRange = this.getDocument().locationRangeFromRange([position, position + 1]); + return this.selectionManager.getClientRectAtLocationRange(locationRange); + } + expandSelectionInDirection(direction) { + return this.composition.expandSelectionInDirection(direction); + } + moveCursorInDirection(direction) { + return this.composition.moveCursorInDirection(direction); + } + setSelectedRange(selectedRange) { + return this.composition.setSelectedRange(selectedRange); + } + + // Attributes + + activateAttribute(name) { + let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + return this.composition.setCurrentAttribute(name, value); + } + attributeIsActive(name) { + return this.composition.hasCurrentAttribute(name); + } + canActivateAttribute(name) { + return this.composition.canSetCurrentAttribute(name); + } + deactivateAttribute(name) { + return this.composition.removeCurrentAttribute(name); + } + + // HTML attributes + setHTMLAtributeAtPosition(position, name, value) { + this.composition.setHTMLAtributeAtPosition(position, name, value); + } + + // Nesting level + + canDecreaseNestingLevel() { + return this.composition.canDecreaseNestingLevel(); + } + canIncreaseNestingLevel() { + return this.composition.canIncreaseNestingLevel(); + } + decreaseNestingLevel() { + if (this.canDecreaseNestingLevel()) { + return this.composition.decreaseNestingLevel(); + } + } + increaseNestingLevel() { + if (this.canIncreaseNestingLevel()) { + return this.composition.increaseNestingLevel(); + } + } + + // Undo/redo + + canRedo() { + return this.undoManager.canRedo(); + } + canUndo() { + return this.undoManager.canUndo(); + } + recordUndoEntry(description) { + let { + context, + consolidatable + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.undoManager.recordUndoEntry(description, { + context, + consolidatable + }); + } + redo() { + if (this.canRedo()) { + return this.undoManager.redo(); + } + } + undo() { + if (this.canUndo()) { + return this.undoManager.undo(); + } + } + } + + /* eslint-disable + no-var, + prefer-const, + */ + class LocationMapper { + constructor(element) { + this.element = element; + } + findLocationFromContainerAndOffset(container, offset) { + let { + strict + } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { + strict: true + }; + let childIndex = 0; + let foundBlock = false; + const location = { + index: 0, + offset: 0 + }; + const attachmentElement = this.findAttachmentElementParentForNode(container); + if (attachmentElement) { + container = attachmentElement.parentNode; + offset = findChildIndexOfNode(attachmentElement); + } + const walker = walkTree(this.element, { + usingFilter: rejectAttachmentContents + }); + while (walker.nextNode()) { + const node = walker.currentNode; + if (node === container && nodeIsTextNode(container)) { + if (!nodeIsCursorTarget(node)) { + location.offset += offset; + } + break; + } else { + if (node.parentNode === container) { + if (childIndex++ === offset) { + break; + } + } else if (!elementContainsNode(container, node)) { + if (childIndex > 0) { + break; + } + } + if (nodeIsBlockStart(node, { + strict + })) { + if (foundBlock) { + location.index++; + } + location.offset = 0; + foundBlock = true; + } else { + location.offset += nodeLength(node); + } + } + } + return location; + } + findContainerAndOffsetFromLocation(location) { + let container, offset; + if (location.index === 0 && location.offset === 0) { + container = this.element; + offset = 0; + while (container.firstChild) { + container = container.firstChild; + if (nodeIsBlockContainer(container)) { + offset = 1; + break; + } + } + return [container, offset]; + } + let [node, nodeOffset] = this.findNodeAndOffsetFromLocation(location); + if (!node) return; + if (nodeIsTextNode(node)) { + if (nodeLength(node) === 0) { + container = node.parentNode.parentNode; + offset = findChildIndexOfNode(node.parentNode); + if (nodeIsCursorTarget(node, { + name: "right" + })) { + offset++; + } + } else { + container = node; + offset = location.offset - nodeOffset; + } + } else { + container = node.parentNode; + if (!nodeIsBlockStart(node.previousSibling)) { + if (!nodeIsBlockContainer(container)) { + while (node === container.lastChild) { + node = container; + container = container.parentNode; + if (nodeIsBlockContainer(container)) { + break; + } + } + } + } + offset = findChildIndexOfNode(node); + if (location.offset !== 0) { + offset++; + } + } + return [container, offset]; + } + findNodeAndOffsetFromLocation(location) { + let node, nodeOffset; + let offset = 0; + for (const currentNode of this.getSignificantNodesForIndex(location.index)) { + const length = nodeLength(currentNode); + if (location.offset <= offset + length) { + if (nodeIsTextNode(currentNode)) { + node = currentNode; + nodeOffset = offset; + if (location.offset === nodeOffset && nodeIsCursorTarget(node)) { + break; + } + } else if (!node) { + node = currentNode; + nodeOffset = offset; + } + } + offset += length; + if (offset > location.offset) { + break; + } + } + return [node, nodeOffset]; + } + + // Private + + findAttachmentElementParentForNode(node) { + while (node && node !== this.element) { + if (nodeIsAttachmentElement(node)) { + return node; + } + node = node.parentNode; + } + } + getSignificantNodesForIndex(index) { + const nodes = []; + const walker = walkTree(this.element, { + usingFilter: acceptSignificantNodes + }); + let recordingNodes = false; + while (walker.nextNode()) { + const node = walker.currentNode; + if (nodeIsBlockStartComment(node)) { + var blockIndex; + if (blockIndex != null) { + blockIndex++; + } else { + blockIndex = 0; + } + if (blockIndex === index) { + recordingNodes = true; + } else if (recordingNodes) { + break; + } + } else if (recordingNodes) { + nodes.push(node); + } + } + return nodes; + } + } + const nodeLength = function (node) { + if (node.nodeType === Node.TEXT_NODE) { + if (nodeIsCursorTarget(node)) { + return 0; + } else { + const string = node.textContent; + return string.length; + } + } else if (tagName(node) === "br" || nodeIsAttachmentElement(node)) { + return 1; + } else { + return 0; + } + }; + const acceptSignificantNodes = function (node) { + if (rejectEmptyTextNodes(node) === NodeFilter.FILTER_ACCEPT) { + return rejectAttachmentContents(node); + } else { + return NodeFilter.FILTER_REJECT; + } + }; + const rejectEmptyTextNodes = function (node) { + if (nodeIsEmptyTextNode(node)) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }; + const rejectAttachmentContents = function (node) { + if (nodeIsAttachmentElement(node.parentNode)) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }; + + /* eslint-disable + id-length, + no-empty, + */ + class PointMapper { + createDOMRangeFromPoint(_ref) { + let { + x, + y + } = _ref; + let domRange; + if (document.caretPositionFromPoint) { + const { + offsetNode, + offset + } = document.caretPositionFromPoint(x, y); + domRange = document.createRange(); + domRange.setStart(offsetNode, offset); + return domRange; + } else if (document.caretRangeFromPoint) { + return document.caretRangeFromPoint(x, y); + } else if (document.body.createTextRange) { + const originalDOMRange = getDOMRange(); + try { + // IE 11 throws "Unspecified error" when using moveToPoint + // during a drag-and-drop operation. + const textRange = document.body.createTextRange(); + textRange.moveToPoint(x, y); + textRange.select(); + } catch (error) {} + domRange = getDOMRange(); + setDOMRange(originalDOMRange); + return domRange; + } + } + getClientRectsForDOMRange(domRange) { + const array = Array.from(domRange.getClientRects()); + const start = array[0]; + const end = array[array.length - 1]; + return [start, end]; + } + } + + /* eslint-disable + */ + class SelectionManager extends BasicObject { + constructor(element) { + super(...arguments); + this.didMouseDown = this.didMouseDown.bind(this); + this.selectionDidChange = this.selectionDidChange.bind(this); + this.element = element; + this.locationMapper = new LocationMapper(this.element); + this.pointMapper = new PointMapper(); + this.lockCount = 0; + handleEvent("mousedown", { + onElement: this.element, + withCallback: this.didMouseDown + }); + } + getLocationRange() { + let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + if (options.strict === false) { + return this.createLocationRangeFromDOMRange(getDOMRange()); + } else if (options.ignoreLock) { + return this.currentLocationRange; + } else if (this.lockedLocationRange) { + return this.lockedLocationRange; + } else { + return this.currentLocationRange; + } + } + setLocationRange(locationRange) { + if (this.lockedLocationRange) return; + locationRange = normalizeRange(locationRange); + const domRange = this.createDOMRangeFromLocationRange(locationRange); + if (domRange) { + setDOMRange(domRange); + this.updateCurrentLocationRange(locationRange); + } + } + setLocationRangeFromPointRange(pointRange) { + pointRange = normalizeRange(pointRange); + const startLocation = this.getLocationAtPoint(pointRange[0]); + const endLocation = this.getLocationAtPoint(pointRange[1]); + this.setLocationRange([startLocation, endLocation]); + } + getClientRectAtLocationRange(locationRange) { + const domRange = this.createDOMRangeFromLocationRange(locationRange); + if (domRange) { + return this.getClientRectsForDOMRange(domRange)[1]; + } + } + locationIsCursorTarget(location) { + const node = Array.from(this.findNodeAndOffsetFromLocation(location))[0]; + return nodeIsCursorTarget(node); + } + lock() { + if (this.lockCount++ === 0) { + this.updateCurrentLocationRange(); + this.lockedLocationRange = this.getLocationRange(); + } + } + unlock() { + if (--this.lockCount === 0) { + const { + lockedLocationRange + } = this; + this.lockedLocationRange = null; + if (lockedLocationRange != null) { + return this.setLocationRange(lockedLocationRange); + } + } + } + clearSelection() { + var _getDOMSelection; + return (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.removeAllRanges(); + } + selectionIsCollapsed() { + var _getDOMRange; + return ((_getDOMRange = getDOMRange()) === null || _getDOMRange === void 0 ? void 0 : _getDOMRange.collapsed) === true; + } + selectionIsExpanded() { + return !this.selectionIsCollapsed(); + } + createLocationRangeFromDOMRange(domRange, options) { + if (domRange == null || !this.domRangeWithinElement(domRange)) return; + const start = this.findLocationFromContainerAndOffset(domRange.startContainer, domRange.startOffset, options); + if (!start) return; + const end = domRange.collapsed ? undefined : this.findLocationFromContainerAndOffset(domRange.endContainer, domRange.endOffset, options); + return normalizeRange([start, end]); + } + didMouseDown() { + return this.pauseTemporarily(); + } + pauseTemporarily() { + let resumeHandlers; + this.paused = true; + const resume = () => { + this.paused = false; + clearTimeout(resumeTimeout); + Array.from(resumeHandlers).forEach(handler => { + handler.destroy(); + }); + if (elementContainsNode(document, this.element)) { + return this.selectionDidChange(); + } + }; + const resumeTimeout = setTimeout(resume, 200); + resumeHandlers = ["mousemove", "keydown"].map(eventName => handleEvent(eventName, { + onElement: document, + withCallback: resume + })); + } + selectionDidChange() { + if (!this.paused && !innerElementIsActive(this.element)) { + return this.updateCurrentLocationRange(); + } + } + updateCurrentLocationRange(locationRange) { + if (locationRange != null ? locationRange : locationRange = this.createLocationRangeFromDOMRange(getDOMRange())) { + if (!rangesAreEqual(locationRange, this.currentLocationRange)) { + var _this$delegate, _this$delegate$locati; + this.currentLocationRange = locationRange; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$locati = _this$delegate.locationRangeDidChange) === null || _this$delegate$locati === void 0 ? void 0 : _this$delegate$locati.call(_this$delegate, this.currentLocationRange.slice(0)); + } + } + } + createDOMRangeFromLocationRange(locationRange) { + const rangeStart = this.findContainerAndOffsetFromLocation(locationRange[0]); + const rangeEnd = rangeIsCollapsed(locationRange) ? rangeStart : this.findContainerAndOffsetFromLocation(locationRange[1]) || rangeStart; + if (rangeStart != null && rangeEnd != null) { + const domRange = document.createRange(); + domRange.setStart(...Array.from(rangeStart || [])); + domRange.setEnd(...Array.from(rangeEnd || [])); + return domRange; + } + } + getLocationAtPoint(point) { + const domRange = this.createDOMRangeFromPoint(point); + if (domRange) { + var _this$createLocationR; + return (_this$createLocationR = this.createLocationRangeFromDOMRange(domRange)) === null || _this$createLocationR === void 0 ? void 0 : _this$createLocationR[0]; + } + } + domRangeWithinElement(domRange) { + if (domRange.collapsed) { + return elementContainsNode(this.element, domRange.startContainer); + } else { + return elementContainsNode(this.element, domRange.startContainer) && elementContainsNode(this.element, domRange.endContainer); + } + } + } + SelectionManager.proxyMethod("locationMapper.findLocationFromContainerAndOffset"); + SelectionManager.proxyMethod("locationMapper.findContainerAndOffsetFromLocation"); + SelectionManager.proxyMethod("locationMapper.findNodeAndOffsetFromLocation"); + SelectionManager.proxyMethod("pointMapper.createDOMRangeFromPoint"); + SelectionManager.proxyMethod("pointMapper.getClientRectsForDOMRange"); + + var models = /*#__PURE__*/Object.freeze({ + __proto__: null, + Attachment: Attachment, + AttachmentManager: AttachmentManager, + AttachmentPiece: AttachmentPiece, + Block: Block, + Composition: Composition, + Document: Document, + Editor: Editor, + HTMLParser: HTMLParser, + HTMLSanitizer: HTMLSanitizer, + LineBreakInsertion: LineBreakInsertion, + LocationMapper: LocationMapper, + ManagedAttachment: ManagedAttachment, + Piece: Piece, + PointMapper: PointMapper, + SelectionManager: SelectionManager, + SplittableList: SplittableList, + StringPiece: StringPiece, + Text: Text, + UndoManager: UndoManager + }); + + var views = /*#__PURE__*/Object.freeze({ + __proto__: null, + ObjectView: ObjectView, + AttachmentView: AttachmentView, + BlockView: BlockView, + DocumentView: DocumentView, + PieceView: PieceView, + PreviewableAttachmentView: PreviewableAttachmentView, + TextView: TextView + }); + + const { + lang, + css, + keyNames: keyNames$1 + } = config; + const undoable = function (fn) { + return function () { + const commands = fn.apply(this, arguments); + commands.do(); + if (!this.undos) { + this.undos = []; + } + this.undos.push(commands.undo); + }; + }; + class AttachmentEditorController extends BasicObject { + constructor(attachmentPiece, _element, container) { + let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + super(...arguments); + // Installing and uninstalling + _defineProperty(this, "makeElementMutable", undoable(() => { + return { + do: () => { + this.element.dataset.trixMutable = true; + }, + undo: () => delete this.element.dataset.trixMutable + }; + })); + _defineProperty(this, "addToolbar", undoable(() => { + //
+ //
+ // + // + // + //
+ //
+ const element = makeElement({ + tagName: "div", + className: css.attachmentToolbar, + data: { + trixMutable: true + }, + childNodes: makeElement({ + tagName: "div", + className: "trix-button-row", + childNodes: makeElement({ + tagName: "span", + className: "trix-button-group trix-button-group--actions", + childNodes: makeElement({ + tagName: "button", + className: "trix-button trix-button--remove", + textContent: lang.remove, + attributes: { + title: lang.remove + }, + data: { + trixAction: "remove" + } + }) + }) + }) + }); + if (this.attachment.isPreviewable()) { + //
+ // + // #{name} + // #{size} + // + //
+ element.appendChild(makeElement({ + tagName: "div", + className: css.attachmentMetadataContainer, + childNodes: makeElement({ + tagName: "span", + className: css.attachmentMetadata, + childNodes: [makeElement({ + tagName: "span", + className: css.attachmentName, + textContent: this.attachment.getFilename(), + attributes: { + title: this.attachment.getFilename() + } + }), makeElement({ + tagName: "span", + className: css.attachmentSize, + textContent: this.attachment.getFormattedFilesize() + })] + }) + })); + } + handleEvent("click", { + onElement: element, + withCallback: this.didClickToolbar + }); + handleEvent("click", { + onElement: element, + matchingSelector: "[data-trix-action]", + withCallback: this.didClickActionButton + }); + triggerEvent("trix-attachment-before-toolbar", { + onElement: this.element, + attributes: { + toolbar: element, + attachment: this.attachment + } + }); + return { + do: () => this.element.appendChild(element), + undo: () => removeNode(element) + }; + })); + _defineProperty(this, "installCaptionEditor", undoable(() => { + const textarea = makeElement({ + tagName: "textarea", + className: css.attachmentCaptionEditor, + attributes: { + placeholder: lang.captionPlaceholder + }, + data: { + trixMutable: true + } + }); + textarea.value = this.attachmentPiece.getCaption(); + const textareaClone = textarea.cloneNode(); + textareaClone.classList.add("trix-autoresize-clone"); + textareaClone.tabIndex = -1; + const autoresize = function () { + textareaClone.value = textarea.value; + textarea.style.height = textareaClone.scrollHeight + "px"; + }; + handleEvent("input", { + onElement: textarea, + withCallback: autoresize + }); + handleEvent("input", { + onElement: textarea, + withCallback: this.didInputCaption + }); + handleEvent("keydown", { + onElement: textarea, + withCallback: this.didKeyDownCaption + }); + handleEvent("change", { + onElement: textarea, + withCallback: this.didChangeCaption + }); + handleEvent("blur", { + onElement: textarea, + withCallback: this.didBlurCaption + }); + const figcaption = this.element.querySelector("figcaption"); + const editingFigcaption = figcaption.cloneNode(); + return { + do: () => { + figcaption.style.display = "none"; + editingFigcaption.appendChild(textarea); + editingFigcaption.appendChild(textareaClone); + editingFigcaption.classList.add("".concat(css.attachmentCaption, "--editing")); + figcaption.parentElement.insertBefore(editingFigcaption, figcaption); + autoresize(); + if (this.options.editCaption) { + return defer(() => textarea.focus()); + } + }, + undo() { + removeNode(editingFigcaption); + figcaption.style.display = null; + } + }; + })); + this.didClickToolbar = this.didClickToolbar.bind(this); + this.didClickActionButton = this.didClickActionButton.bind(this); + this.didKeyDownCaption = this.didKeyDownCaption.bind(this); + this.didInputCaption = this.didInputCaption.bind(this); + this.didChangeCaption = this.didChangeCaption.bind(this); + this.didBlurCaption = this.didBlurCaption.bind(this); + this.attachmentPiece = attachmentPiece; + this.element = _element; + this.container = container; + this.options = options; + this.attachment = this.attachmentPiece.attachment; + if (tagName(this.element) === "a") { + this.element = this.element.firstChild; + } + this.install(); + } + install() { + this.makeElementMutable(); + this.addToolbar(); + if (this.attachment.isPreviewable()) { + this.installCaptionEditor(); + } + } + uninstall() { + var _this$delegate; + let undo = this.undos.pop(); + this.savePendingCaption(); + while (undo) { + undo(); + undo = this.undos.pop(); + } + (_this$delegate = this.delegate) === null || _this$delegate === void 0 || _this$delegate.didUninstallAttachmentEditor(this); + } + + // Private + + savePendingCaption() { + if (this.pendingCaption != null) { + const caption = this.pendingCaption; + this.pendingCaption = null; + if (caption) { + var _this$delegate2, _this$delegate2$attac; + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$attac = _this$delegate2.attachmentEditorDidRequestUpdatingAttributesForAttachment) === null || _this$delegate2$attac === void 0 || _this$delegate2$attac.call(_this$delegate2, { + caption + }, this.attachment); + } else { + var _this$delegate3, _this$delegate3$attac; + (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$attac = _this$delegate3.attachmentEditorDidRequestRemovingAttributeForAttachment) === null || _this$delegate3$attac === void 0 || _this$delegate3$attac.call(_this$delegate3, "caption", this.attachment); + } + } + } + // Event handlers + + didClickToolbar(event) { + event.preventDefault(); + return event.stopPropagation(); + } + didClickActionButton(event) { + var _this$delegate4; + const action = event.target.getAttribute("data-trix-action"); + switch (action) { + case "remove": + return (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : _this$delegate4.attachmentEditorDidRequestRemovalOfAttachment(this.attachment); + } + } + didKeyDownCaption(event) { + if (keyNames$1[event.keyCode] === "return") { + var _this$delegate5, _this$delegate5$attac; + event.preventDefault(); + this.savePendingCaption(); + return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$attac = _this$delegate5.attachmentEditorDidRequestDeselectingAttachment) === null || _this$delegate5$attac === void 0 ? void 0 : _this$delegate5$attac.call(_this$delegate5, this.attachment); + } + } + didInputCaption(event) { + this.pendingCaption = event.target.value.replace(/\s/g, " ").trim(); + } + didChangeCaption(event) { + return this.savePendingCaption(); + } + didBlurCaption(event) { + return this.savePendingCaption(); + } + } + + class CompositionController extends BasicObject { + constructor(element, composition) { + super(...arguments); + this.didFocus = this.didFocus.bind(this); + this.didBlur = this.didBlur.bind(this); + this.didClickAttachment = this.didClickAttachment.bind(this); + this.element = element; + this.composition = composition; + this.documentView = new DocumentView(this.composition.document, { + element: this.element + }); + handleEvent("focus", { + onElement: this.element, + withCallback: this.didFocus + }); + handleEvent("blur", { + onElement: this.element, + withCallback: this.didBlur + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: "a[contenteditable=false]", + preventDefault: true + }); + handleEvent("mousedown", { + onElement: this.element, + matchingSelector: attachmentSelector, + withCallback: this.didClickAttachment + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: "a".concat(attachmentSelector), + preventDefault: true + }); + } + didFocus(event) { + var _this$blurPromise; + const perform = () => { + if (!this.focused) { + var _this$delegate, _this$delegate$compos; + this.focused = true; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$compos = _this$delegate.compositionControllerDidFocus) === null || _this$delegate$compos === void 0 ? void 0 : _this$delegate$compos.call(_this$delegate); + } + }; + return ((_this$blurPromise = this.blurPromise) === null || _this$blurPromise === void 0 ? void 0 : _this$blurPromise.then(perform)) || perform(); + } + didBlur(event) { + this.blurPromise = new Promise(resolve => { + return defer(() => { + if (!innerElementIsActive(this.element)) { + var _this$delegate2, _this$delegate2$compo; + this.focused = null; + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$compo = _this$delegate2.compositionControllerDidBlur) === null || _this$delegate2$compo === void 0 || _this$delegate2$compo.call(_this$delegate2); + } + this.blurPromise = null; + return resolve(); + }); + }); + } + didClickAttachment(event, target) { + var _this$delegate3, _this$delegate3$compo; + const attachment = this.findAttachmentForElement(target); + const editCaption = !!findClosestElementFromNode(event.target, { + matchingSelector: "figcaption" + }); + return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$compo = _this$delegate3.compositionControllerDidSelectAttachment) === null || _this$delegate3$compo === void 0 ? void 0 : _this$delegate3$compo.call(_this$delegate3, attachment, { + editCaption + }); + } + getSerializableElement() { + if (this.isEditingAttachment()) { + return this.documentView.shadowElement; + } else { + return this.element; + } + } + render() { + var _this$delegate6, _this$delegate6$compo; + if (this.revision !== this.composition.revision) { + this.documentView.setDocument(this.composition.document); + this.documentView.render(); + this.revision = this.composition.revision; + } + if (this.canSyncDocumentView() && !this.documentView.isSynced()) { + var _this$delegate4, _this$delegate4$compo, _this$delegate5, _this$delegate5$compo; + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || (_this$delegate4$compo = _this$delegate4.compositionControllerWillSyncDocumentView) === null || _this$delegate4$compo === void 0 || _this$delegate4$compo.call(_this$delegate4); + this.documentView.sync(); + (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$compo = _this$delegate5.compositionControllerDidSyncDocumentView) === null || _this$delegate5$compo === void 0 || _this$delegate5$compo.call(_this$delegate5); + } + return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$compo = _this$delegate6.compositionControllerDidRender) === null || _this$delegate6$compo === void 0 ? void 0 : _this$delegate6$compo.call(_this$delegate6); + } + rerenderViewForObject(object) { + this.invalidateViewForObject(object); + return this.render(); + } + invalidateViewForObject(object) { + return this.documentView.invalidateViewForObject(object); + } + isViewCachingEnabled() { + return this.documentView.isViewCachingEnabled(); + } + enableViewCaching() { + return this.documentView.enableViewCaching(); + } + disableViewCaching() { + return this.documentView.disableViewCaching(); + } + refreshViewCache() { + return this.documentView.garbageCollectCachedViews(); + } + + // Attachment editor management + + isEditingAttachment() { + return !!this.attachmentEditor; + } + installAttachmentEditorForAttachment(attachment, options) { + var _this$attachmentEdito; + if (((_this$attachmentEdito = this.attachmentEditor) === null || _this$attachmentEdito === void 0 ? void 0 : _this$attachmentEdito.attachment) === attachment) return; + const element = this.documentView.findElementForObject(attachment); + if (!element) return; + this.uninstallAttachmentEditor(); + const attachmentPiece = this.composition.document.getAttachmentPieceForAttachment(attachment); + this.attachmentEditor = new AttachmentEditorController(attachmentPiece, element, this.element, options); + this.attachmentEditor.delegate = this; + } + uninstallAttachmentEditor() { + var _this$attachmentEdito2; + return (_this$attachmentEdito2 = this.attachmentEditor) === null || _this$attachmentEdito2 === void 0 ? void 0 : _this$attachmentEdito2.uninstall(); + } + + // Attachment controller delegate + + didUninstallAttachmentEditor() { + this.attachmentEditor = null; + return this.render(); + } + attachmentEditorDidRequestUpdatingAttributesForAttachment(attributes, attachment) { + var _this$delegate7, _this$delegate7$compo; + (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$compo = _this$delegate7.compositionControllerWillUpdateAttachment) === null || _this$delegate7$compo === void 0 || _this$delegate7$compo.call(_this$delegate7, attachment); + return this.composition.updateAttributesForAttachment(attributes, attachment); + } + attachmentEditorDidRequestRemovingAttributeForAttachment(attribute, attachment) { + var _this$delegate8, _this$delegate8$compo; + (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || (_this$delegate8$compo = _this$delegate8.compositionControllerWillUpdateAttachment) === null || _this$delegate8$compo === void 0 || _this$delegate8$compo.call(_this$delegate8, attachment); + return this.composition.removeAttributeForAttachment(attribute, attachment); + } + attachmentEditorDidRequestRemovalOfAttachment(attachment) { + var _this$delegate9, _this$delegate9$compo; + return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || (_this$delegate9$compo = _this$delegate9.compositionControllerDidRequestRemovalOfAttachment) === null || _this$delegate9$compo === void 0 ? void 0 : _this$delegate9$compo.call(_this$delegate9, attachment); + } + attachmentEditorDidRequestDeselectingAttachment(attachment) { + var _this$delegate10, _this$delegate10$comp; + return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || (_this$delegate10$comp = _this$delegate10.compositionControllerDidRequestDeselectingAttachment) === null || _this$delegate10$comp === void 0 ? void 0 : _this$delegate10$comp.call(_this$delegate10, attachment); + } + + // Private + + canSyncDocumentView() { + return !this.isEditingAttachment(); + } + findAttachmentForElement(element) { + return this.composition.document.getAttachmentById(parseInt(element.dataset.trixId, 10)); + } + } + + class Controller extends BasicObject {} + + const mutableAttributeName = "data-trix-mutable"; + const mutableSelector = "[".concat(mutableAttributeName, "]"); + const options = { + attributes: true, + childList: true, + characterData: true, + characterDataOldValue: true, + subtree: true + }; + class MutationObserver extends BasicObject { + constructor(element) { + super(element); + this.didMutate = this.didMutate.bind(this); + this.element = element; + this.observer = new window.MutationObserver(this.didMutate); + this.start(); + } + start() { + this.reset(); + return this.observer.observe(this.element, options); + } + stop() { + return this.observer.disconnect(); + } + didMutate(mutations) { + this.mutations.push(...Array.from(this.findSignificantMutations(mutations) || [])); + if (this.mutations.length) { + var _this$delegate, _this$delegate$elemen; + (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$elemen = _this$delegate.elementDidMutate) === null || _this$delegate$elemen === void 0 || _this$delegate$elemen.call(_this$delegate, this.getMutationSummary()); + return this.reset(); + } + } + + // Private + + reset() { + this.mutations = []; + } + findSignificantMutations(mutations) { + return mutations.filter(mutation => { + return this.mutationIsSignificant(mutation); + }); + } + mutationIsSignificant(mutation) { + if (this.nodeIsMutable(mutation.target)) { + return false; + } + for (const node of Array.from(this.nodesModifiedByMutation(mutation))) { + if (this.nodeIsSignificant(node)) return true; + } + return false; + } + nodeIsSignificant(node) { + return node !== this.element && !this.nodeIsMutable(node) && !nodeIsEmptyTextNode(node); + } + nodeIsMutable(node) { + return findClosestElementFromNode(node, { + matchingSelector: mutableSelector + }); + } + nodesModifiedByMutation(mutation) { + const nodes = []; + switch (mutation.type) { + case "attributes": + if (mutation.attributeName !== mutableAttributeName) { + nodes.push(mutation.target); + } + break; + case "characterData": + // Changes to text nodes should consider the parent element + nodes.push(mutation.target.parentNode); + nodes.push(mutation.target); + break; + case "childList": + // Consider each added or removed node + nodes.push(...Array.from(mutation.addedNodes || [])); + nodes.push(...Array.from(mutation.removedNodes || [])); + break; + } + return nodes; + } + getMutationSummary() { + return this.getTextMutationSummary(); + } + getTextMutationSummary() { + const { + additions, + deletions + } = this.getTextChangesFromCharacterData(); + const textChanges = this.getTextChangesFromChildList(); + Array.from(textChanges.additions).forEach(addition => { + if (!Array.from(additions).includes(addition)) { + additions.push(addition); + } + }); + deletions.push(...Array.from(textChanges.deletions || [])); + const summary = {}; + const added = additions.join(""); + if (added) { + summary.textAdded = added; + } + const deleted = deletions.join(""); + if (deleted) { + summary.textDeleted = deleted; + } + return summary; + } + getMutationsByType(type) { + return Array.from(this.mutations).filter(mutation => mutation.type === type); + } + getTextChangesFromChildList() { + let textAdded, textRemoved; + const addedNodes = []; + const removedNodes = []; + Array.from(this.getMutationsByType("childList")).forEach(mutation => { + addedNodes.push(...Array.from(mutation.addedNodes || [])); + removedNodes.push(...Array.from(mutation.removedNodes || [])); + }); + const singleBlockCommentRemoved = addedNodes.length === 0 && removedNodes.length === 1 && nodeIsBlockStartComment(removedNodes[0]); + if (singleBlockCommentRemoved) { + textAdded = []; + textRemoved = ["\n"]; + } else { + textAdded = getTextForNodes(addedNodes); + textRemoved = getTextForNodes(removedNodes); + } + const additions = textAdded.filter((text, index) => text !== textRemoved[index]).map(normalizeSpaces); + const deletions = textRemoved.filter((text, index) => text !== textAdded[index]).map(normalizeSpaces); + return { + additions, + deletions + }; + } + getTextChangesFromCharacterData() { + let added, removed; + const characterMutations = this.getMutationsByType("characterData"); + if (characterMutations.length) { + const startMutation = characterMutations[0], + endMutation = characterMutations[characterMutations.length - 1]; + const oldString = normalizeSpaces(startMutation.oldValue); + const newString = normalizeSpaces(endMutation.target.data); + const summarized = summarizeStringChange(oldString, newString); + added = summarized.added; + removed = summarized.removed; + } + return { + additions: added ? [added] : [], + deletions: removed ? [removed] : [] + }; + } + } + const getTextForNodes = function () { + let nodes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + const text = []; + for (const node of Array.from(nodes)) { + switch (node.nodeType) { + case Node.TEXT_NODE: + text.push(node.data); + break; + case Node.ELEMENT_NODE: + if (tagName(node) === "br") { + text.push("\n"); + } else { + text.push(...Array.from(getTextForNodes(node.childNodes) || [])); + } + break; + } + } + return text; + }; + + /* eslint-disable + no-empty, + */ + class FileVerificationOperation extends Operation { + constructor(file) { + super(...arguments); + this.file = file; + } + perform(callback) { + const reader = new FileReader(); + reader.onerror = () => callback(false); + reader.onload = () => { + reader.onerror = null; + try { + reader.abort(); + } catch (error) {} + return callback(true, this.file); + }; + return reader.readAsArrayBuffer(this.file); + } + } + + // Each software keyboard on Android emits its own set of events and some of them can be buggy. + // This class detects when some buggy events are being emitted and lets know the input controller + // that they should be ignored. + class FlakyAndroidKeyboardDetector { + constructor(element) { + this.element = element; + } + shouldIgnore(event) { + if (!browser$1.samsungAndroid) return false; + this.previousEvent = this.event; + this.event = event; + this.checkSamsungKeyboardBuggyModeStart(); + this.checkSamsungKeyboardBuggyModeEnd(); + return this.buggyMode; + } + + // private + + // The Samsung keyboard on Android can enter a buggy state in which it emits a flurry of confused events that, + // if processed, corrupts the editor. The buggy mode always starts with an insertText event, right after a + // keydown event with for an "Unidentified" key, with the same text as the editor element, except for a few + // extra whitespace, or exotic utf8, characters. + checkSamsungKeyboardBuggyModeStart() { + if (this.insertingLongTextAfterUnidentifiedChar() && differsInWhitespace(this.element.innerText, this.event.data)) { + this.buggyMode = true; + this.event.preventDefault(); + } + } + + // The flurry of buggy events are always insertText. If we see any other type, it means it's over. + checkSamsungKeyboardBuggyModeEnd() { + if (this.buggyMode && this.event.inputType !== "insertText") { + this.buggyMode = false; + } + } + insertingLongTextAfterUnidentifiedChar() { + var _this$event$data; + return this.isBeforeInputInsertText() && this.previousEventWasUnidentifiedKeydown() && ((_this$event$data = this.event.data) === null || _this$event$data === void 0 ? void 0 : _this$event$data.length) > 50; + } + isBeforeInputInsertText() { + return this.event.type === "beforeinput" && this.event.inputType === "insertText"; + } + previousEventWasUnidentifiedKeydown() { + var _this$previousEvent, _this$previousEvent2; + return ((_this$previousEvent = this.previousEvent) === null || _this$previousEvent === void 0 ? void 0 : _this$previousEvent.type) === "keydown" && ((_this$previousEvent2 = this.previousEvent) === null || _this$previousEvent2 === void 0 ? void 0 : _this$previousEvent2.key) === "Unidentified"; + } + } + const differsInWhitespace = (text1, text2) => { + return normalize(text1) === normalize(text2); + }; + const whiteSpaceNormalizerRegexp = new RegExp("(".concat(OBJECT_REPLACEMENT_CHARACTER, "|").concat(ZERO_WIDTH_SPACE, "|").concat(NON_BREAKING_SPACE, "|\\s)+"), "g"); + const normalize = text => text.replace(whiteSpaceNormalizerRegexp, " ").trim(); + + class InputController extends BasicObject { + constructor(element) { + super(...arguments); + this.element = element; + this.mutationObserver = new MutationObserver(this.element); + this.mutationObserver.delegate = this; + this.flakyKeyboardDetector = new FlakyAndroidKeyboardDetector(this.element); + for (const eventName in this.constructor.events) { + handleEvent(eventName, { + onElement: this.element, + withCallback: this.handlerFor(eventName) + }); + } + } + elementDidMutate(mutationSummary) {} + editorWillSyncDocumentView() { + return this.mutationObserver.stop(); + } + editorDidSyncDocumentView() { + return this.mutationObserver.start(); + } + requestRender() { + var _this$delegate, _this$delegate$inputC; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidRequestRender) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); + } + requestReparse() { + var _this$delegate2, _this$delegate2$input; + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$input = _this$delegate2.inputControllerDidRequestReparse) === null || _this$delegate2$input === void 0 || _this$delegate2$input.call(_this$delegate2); + return this.requestRender(); + } + attachFiles(files) { + const operations = Array.from(files).map(file => new FileVerificationOperation(file)); + return Promise.all(operations).then(files => { + this.handleInput(function () { + var _this$delegate3, _this$responder; + (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || _this$delegate3.inputControllerWillAttachFiles(); + (_this$responder = this.responder) === null || _this$responder === void 0 || _this$responder.insertFiles(files); + return this.requestRender(); + }); + }); + } + + // Private + + handlerFor(eventName) { + return event => { + if (!event.defaultPrevented) { + this.handleInput(() => { + if (!innerElementIsActive(this.element)) { + if (this.flakyKeyboardDetector.shouldIgnore(event)) return; + this.eventName = eventName; + this.constructor.events[eventName].call(this, event); + } + }); + } + }; + } + handleInput(callback) { + try { + var _this$delegate4; + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillHandleInput(); + callback.call(this); + } finally { + var _this$delegate5; + (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.inputControllerDidHandleInput(); + } + } + createLinkHTML(href, text) { + const link = document.createElement("a"); + link.href = href; + link.textContent = text ? text : href; + return link.outerHTML; + } + } + _defineProperty(InputController, "events", {}); + + var _$codePointAt, _; + const { + browser, + keyNames + } = config; + let pastedFileCount = 0; + class Level0InputController extends InputController { + constructor() { + super(...arguments); + this.resetInputSummary(); + } + setInputSummary() { + let summary = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + this.inputSummary.eventName = this.eventName; + for (const key in summary) { + const value = summary[key]; + this.inputSummary[key] = value; + } + return this.inputSummary; + } + resetInputSummary() { + this.inputSummary = {}; + } + reset() { + this.resetInputSummary(); + return selectionChangeObserver.reset(); + } + + // Mutation observer delegate + + elementDidMutate(mutationSummary) { + if (this.isComposing()) { + var _this$delegate, _this$delegate$inputC; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidAllowUnhandledInput) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); + } else { + return this.handleInput(function () { + if (this.mutationIsSignificant(mutationSummary)) { + if (this.mutationIsExpected(mutationSummary)) { + this.requestRender(); + } else { + this.requestReparse(); + } + } + return this.reset(); + }); + } + } + mutationIsExpected(_ref) { + let { + textAdded, + textDeleted + } = _ref; + if (this.inputSummary.preferDocument) { + return true; + } + const mutationAdditionMatchesSummary = textAdded != null ? textAdded === this.inputSummary.textAdded : !this.inputSummary.textAdded; + const mutationDeletionMatchesSummary = textDeleted != null ? this.inputSummary.didDelete : !this.inputSummary.didDelete; + const unexpectedNewlineAddition = ["\n", " \n"].includes(textAdded) && !mutationAdditionMatchesSummary; + const unexpectedNewlineDeletion = textDeleted === "\n" && !mutationDeletionMatchesSummary; + const singleUnexpectedNewline = unexpectedNewlineAddition && !unexpectedNewlineDeletion || unexpectedNewlineDeletion && !unexpectedNewlineAddition; + if (singleUnexpectedNewline) { + const range = this.getSelectedRange(); + if (range) { + var _this$responder; + const offset = unexpectedNewlineAddition ? textAdded.replace(/\n$/, "").length || -1 : (textAdded === null || textAdded === void 0 ? void 0 : textAdded.length) || 1; + if ((_this$responder = this.responder) !== null && _this$responder !== void 0 && _this$responder.positionIsBlockBreak(range[1] + offset)) { + return true; + } + } + } + return mutationAdditionMatchesSummary && mutationDeletionMatchesSummary; + } + mutationIsSignificant(mutationSummary) { + var _this$compositionInpu; + const textChanged = Object.keys(mutationSummary).length > 0; + const composedEmptyString = ((_this$compositionInpu = this.compositionInput) === null || _this$compositionInpu === void 0 ? void 0 : _this$compositionInpu.getEndData()) === ""; + return textChanged || !composedEmptyString; + } + + // Private + + getCompositionInput() { + if (this.isComposing()) { + return this.compositionInput; + } else { + this.compositionInput = new CompositionInput(this); + } + } + isComposing() { + return this.compositionInput && !this.compositionInput.isEnded(); + } + deleteInDirection(direction, event) { + var _this$responder2; + if (((_this$responder2 = this.responder) === null || _this$responder2 === void 0 ? void 0 : _this$responder2.deleteInDirection(direction)) === false) { + if (event) { + event.preventDefault(); + return this.requestRender(); + } + } else { + return this.setInputSummary({ + didDelete: true + }); + } + } + serializeSelectionToDataTransfer(dataTransfer) { + var _this$responder3; + if (!dataTransferIsWritable(dataTransfer)) return; + const document = (_this$responder3 = this.responder) === null || _this$responder3 === void 0 ? void 0 : _this$responder3.getSelectedDocument().toSerializableDocument(); + dataTransfer.setData("application/x-trix-document", JSON.stringify(document)); + dataTransfer.setData("text/html", DocumentView.render(document).innerHTML); + dataTransfer.setData("text/plain", document.toString().replace(/\n$/, "")); + return true; + } + canAcceptDataTransfer(dataTransfer) { + const types = {}; + Array.from((dataTransfer === null || dataTransfer === void 0 ? void 0 : dataTransfer.types) || []).forEach(type => { + types[type] = true; + }); + return types.Files || types["application/x-trix-document"] || types["text/html"] || types["text/plain"]; + } + getPastedHTMLUsingHiddenElement(callback) { + const selectedRange = this.getSelectedRange(); + const style = { + position: "absolute", + left: "".concat(window.pageXOffset, "px"), + top: "".concat(window.pageYOffset, "px"), + opacity: 0 + }; + const element = makeElement({ + style, + tagName: "div", + editable: true + }); + document.body.appendChild(element); + element.focus(); + return requestAnimationFrame(() => { + const html = element.innerHTML; + removeNode(element); + this.setSelectedRange(selectedRange); + return callback(html); + }); + } + } + _defineProperty(Level0InputController, "events", { + keydown(event) { + if (!this.isComposing()) { + this.resetInputSummary(); + } + this.inputSummary.didInput = true; + const keyName = keyNames[event.keyCode]; + if (keyName) { + var _context2; + let context = this.keys; + ["ctrl", "alt", "shift", "meta"].forEach(modifier => { + if (event["".concat(modifier, "Key")]) { + var _context; + if (modifier === "ctrl") { + modifier = "control"; + } + context = (_context = context) === null || _context === void 0 ? void 0 : _context[modifier]; + } + }); + if (((_context2 = context) === null || _context2 === void 0 ? void 0 : _context2[keyName]) != null) { + this.setInputSummary({ + keyName + }); + selectionChangeObserver.reset(); + context[keyName].call(this, event); + } + } + if (keyEventIsKeyboardCommand(event)) { + const character = String.fromCharCode(event.keyCode).toLowerCase(); + if (character) { + var _this$delegate3; + const keys = ["alt", "shift"].map(modifier => { + if (event["".concat(modifier, "Key")]) { + return modifier; + } + }).filter(key => key); + keys.push(character); + if ((_this$delegate3 = this.delegate) !== null && _this$delegate3 !== void 0 && _this$delegate3.inputControllerDidReceiveKeyboardCommand(keys)) { + event.preventDefault(); + } + } + } + }, + keypress(event) { + if (this.inputSummary.eventName != null) return; + if (event.metaKey) return; + if (event.ctrlKey && !event.altKey) return; + const string = stringFromKeyEvent(event); + if (string) { + var _this$delegate4, _this$responder9; + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillPerformTyping(); + (_this$responder9 = this.responder) === null || _this$responder9 === void 0 || _this$responder9.insertString(string); + return this.setInputSummary({ + textAdded: string, + didDelete: this.selectionIsExpanded() + }); + } + }, + textInput(event) { + // Handle autocapitalization + const { + data + } = event; + const { + textAdded + } = this.inputSummary; + if (textAdded && textAdded !== data && textAdded.toUpperCase() === data) { + var _this$responder10; + const range = this.getSelectedRange(); + this.setSelectedRange([range[0], range[1] + textAdded.length]); + (_this$responder10 = this.responder) === null || _this$responder10 === void 0 || _this$responder10.insertString(data); + this.setInputSummary({ + textAdded: data + }); + return this.setSelectedRange(range); + } + }, + dragenter(event) { + event.preventDefault(); + }, + dragstart(event) { + var _this$delegate5, _this$delegate5$input; + this.serializeSelectionToDataTransfer(event.dataTransfer); + this.draggedRange = this.getSelectedRange(); + return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$input = _this$delegate5.inputControllerDidStartDrag) === null || _this$delegate5$input === void 0 ? void 0 : _this$delegate5$input.call(_this$delegate5); + }, + dragover(event) { + if (this.draggedRange || this.canAcceptDataTransfer(event.dataTransfer)) { + event.preventDefault(); + const draggingPoint = { + x: event.clientX, + y: event.clientY + }; + if (!objectsAreEqual(draggingPoint, this.draggingPoint)) { + var _this$delegate6, _this$delegate6$input; + this.draggingPoint = draggingPoint; + return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$input = _this$delegate6.inputControllerDidReceiveDragOverPoint) === null || _this$delegate6$input === void 0 ? void 0 : _this$delegate6$input.call(_this$delegate6, this.draggingPoint); + } + } + }, + dragend(event) { + var _this$delegate7, _this$delegate7$input; + (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$input = _this$delegate7.inputControllerDidCancelDrag) === null || _this$delegate7$input === void 0 || _this$delegate7$input.call(_this$delegate7); + this.draggedRange = null; + this.draggingPoint = null; + }, + drop(event) { + var _event$dataTransfer, _this$responder11; + event.preventDefault(); + const files = (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.files; + const documentJSON = event.dataTransfer.getData("application/x-trix-document"); + const point = { + x: event.clientX, + y: event.clientY + }; + (_this$responder11 = this.responder) === null || _this$responder11 === void 0 || _this$responder11.setLocationRangeFromPointRange(point); + if (files !== null && files !== void 0 && files.length) { + this.attachFiles(files); + } else if (this.draggedRange) { + var _this$delegate8, _this$responder12; + (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || _this$delegate8.inputControllerWillMoveText(); + (_this$responder12 = this.responder) === null || _this$responder12 === void 0 || _this$responder12.moveTextFromRange(this.draggedRange); + this.draggedRange = null; + this.requestRender(); + } else if (documentJSON) { + var _this$responder13; + const document = Document.fromJSONString(documentJSON); + (_this$responder13 = this.responder) === null || _this$responder13 === void 0 || _this$responder13.insertDocument(document); + this.requestRender(); + } + this.draggedRange = null; + this.draggingPoint = null; + }, + cut(event) { + var _this$responder14; + if ((_this$responder14 = this.responder) !== null && _this$responder14 !== void 0 && _this$responder14.selectionIsExpanded()) { + var _this$delegate9; + if (this.serializeSelectionToDataTransfer(event.clipboardData)) { + event.preventDefault(); + } + (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || _this$delegate9.inputControllerWillCutText(); + this.deleteInDirection("backward"); + if (event.defaultPrevented) { + return this.requestRender(); + } + } + }, + copy(event) { + var _this$responder15; + if ((_this$responder15 = this.responder) !== null && _this$responder15 !== void 0 && _this$responder15.selectionIsExpanded()) { + if (this.serializeSelectionToDataTransfer(event.clipboardData)) { + event.preventDefault(); + } + } + }, + paste(event) { + const clipboard = event.clipboardData || event.testClipboardData; + const paste = { + clipboard + }; + if (!clipboard || pasteEventIsCrippledSafariHTMLPaste(event)) { + this.getPastedHTMLUsingHiddenElement(html => { + var _this$delegate10, _this$responder16, _this$delegate11; + paste.type = "text/html"; + paste.html = html; + (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || _this$delegate10.inputControllerWillPaste(paste); + (_this$responder16 = this.responder) === null || _this$responder16 === void 0 || _this$responder16.insertHTML(paste.html); + this.requestRender(); + return (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 ? void 0 : _this$delegate11.inputControllerDidPaste(paste); + }); + return; + } + const href = clipboard.getData("URL"); + const html = clipboard.getData("text/html"); + const name = clipboard.getData("public.url-name"); + if (href) { + var _this$delegate12, _this$responder17, _this$delegate13; + let string; + paste.type = "text/html"; + if (name) { + string = squishBreakableWhitespace(name).trim(); + } else { + string = href; + } + paste.html = this.createLinkHTML(href, string); + (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 || _this$delegate12.inputControllerWillPaste(paste); + this.setInputSummary({ + textAdded: string, + didDelete: this.selectionIsExpanded() + }); + (_this$responder17 = this.responder) === null || _this$responder17 === void 0 || _this$responder17.insertHTML(paste.html); + this.requestRender(); + (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || _this$delegate13.inputControllerDidPaste(paste); + } else if (dataTransferIsPlainText(clipboard)) { + var _this$delegate14, _this$responder18, _this$delegate15; + paste.type = "text/plain"; + paste.string = clipboard.getData("text/plain"); + (_this$delegate14 = this.delegate) === null || _this$delegate14 === void 0 || _this$delegate14.inputControllerWillPaste(paste); + this.setInputSummary({ + textAdded: paste.string, + didDelete: this.selectionIsExpanded() + }); + (_this$responder18 = this.responder) === null || _this$responder18 === void 0 || _this$responder18.insertString(paste.string); + this.requestRender(); + (_this$delegate15 = this.delegate) === null || _this$delegate15 === void 0 || _this$delegate15.inputControllerDidPaste(paste); + } else if (html) { + var _this$delegate16, _this$responder19, _this$delegate17; + paste.type = "text/html"; + paste.html = html; + (_this$delegate16 = this.delegate) === null || _this$delegate16 === void 0 || _this$delegate16.inputControllerWillPaste(paste); + (_this$responder19 = this.responder) === null || _this$responder19 === void 0 || _this$responder19.insertHTML(paste.html); + this.requestRender(); + (_this$delegate17 = this.delegate) === null || _this$delegate17 === void 0 || _this$delegate17.inputControllerDidPaste(paste); + } else if (Array.from(clipboard.types).includes("Files")) { + var _clipboard$items, _clipboard$items$getA; + const file = (_clipboard$items = clipboard.items) === null || _clipboard$items === void 0 || (_clipboard$items = _clipboard$items[0]) === null || _clipboard$items === void 0 || (_clipboard$items$getA = _clipboard$items.getAsFile) === null || _clipboard$items$getA === void 0 ? void 0 : _clipboard$items$getA.call(_clipboard$items); + if (file) { + var _this$delegate18, _this$responder20, _this$delegate19; + const extension = extensionForFile(file); + if (!file.name && extension) { + file.name = "pasted-file-".concat(++pastedFileCount, ".").concat(extension); + } + paste.type = "File"; + paste.file = file; + (_this$delegate18 = this.delegate) === null || _this$delegate18 === void 0 || _this$delegate18.inputControllerWillAttachFiles(); + (_this$responder20 = this.responder) === null || _this$responder20 === void 0 || _this$responder20.insertFile(paste.file); + this.requestRender(); + (_this$delegate19 = this.delegate) === null || _this$delegate19 === void 0 || _this$delegate19.inputControllerDidPaste(paste); + } + } + event.preventDefault(); + }, + compositionstart(event) { + return this.getCompositionInput().start(event.data); + }, + compositionupdate(event) { + return this.getCompositionInput().update(event.data); + }, + compositionend(event) { + return this.getCompositionInput().end(event.data); + }, + beforeinput(event) { + this.inputSummary.didInput = true; + }, + input(event) { + this.inputSummary.didInput = true; + return event.stopPropagation(); + } + }); + _defineProperty(Level0InputController, "keys", { + backspace(event) { + var _this$delegate20; + (_this$delegate20 = this.delegate) === null || _this$delegate20 === void 0 || _this$delegate20.inputControllerWillPerformTyping(); + return this.deleteInDirection("backward", event); + }, + delete(event) { + var _this$delegate21; + (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 || _this$delegate21.inputControllerWillPerformTyping(); + return this.deleteInDirection("forward", event); + }, + return(event) { + var _this$delegate22, _this$responder21; + this.setInputSummary({ + preferDocument: true + }); + (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 || _this$delegate22.inputControllerWillPerformTyping(); + return (_this$responder21 = this.responder) === null || _this$responder21 === void 0 ? void 0 : _this$responder21.insertLineBreak(); + }, + tab(event) { + var _this$responder22; + if ((_this$responder22 = this.responder) !== null && _this$responder22 !== void 0 && _this$responder22.canIncreaseNestingLevel()) { + var _this$responder23; + (_this$responder23 = this.responder) === null || _this$responder23 === void 0 || _this$responder23.increaseNestingLevel(); + this.requestRender(); + event.preventDefault(); + } + }, + left(event) { + if (this.selectionIsInCursorTarget()) { + var _this$responder24; + event.preventDefault(); + return (_this$responder24 = this.responder) === null || _this$responder24 === void 0 ? void 0 : _this$responder24.moveCursorInDirection("backward"); + } + }, + right(event) { + if (this.selectionIsInCursorTarget()) { + var _this$responder25; + event.preventDefault(); + return (_this$responder25 = this.responder) === null || _this$responder25 === void 0 ? void 0 : _this$responder25.moveCursorInDirection("forward"); + } + }, + control: { + d(event) { + var _this$delegate23; + (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 || _this$delegate23.inputControllerWillPerformTyping(); + return this.deleteInDirection("forward", event); + }, + h(event) { + var _this$delegate24; + (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 || _this$delegate24.inputControllerWillPerformTyping(); + return this.deleteInDirection("backward", event); + }, + o(event) { + var _this$delegate25, _this$responder26; + event.preventDefault(); + (_this$delegate25 = this.delegate) === null || _this$delegate25 === void 0 || _this$delegate25.inputControllerWillPerformTyping(); + (_this$responder26 = this.responder) === null || _this$responder26 === void 0 || _this$responder26.insertString("\n", { + updatePosition: false + }); + return this.requestRender(); + } + }, + shift: { + return(event) { + var _this$delegate26, _this$responder27; + (_this$delegate26 = this.delegate) === null || _this$delegate26 === void 0 || _this$delegate26.inputControllerWillPerformTyping(); + (_this$responder27 = this.responder) === null || _this$responder27 === void 0 || _this$responder27.insertString("\n"); + this.requestRender(); + event.preventDefault(); + }, + tab(event) { + var _this$responder28; + if ((_this$responder28 = this.responder) !== null && _this$responder28 !== void 0 && _this$responder28.canDecreaseNestingLevel()) { + var _this$responder29; + (_this$responder29 = this.responder) === null || _this$responder29 === void 0 || _this$responder29.decreaseNestingLevel(); + this.requestRender(); + event.preventDefault(); + } + }, + left(event) { + if (this.selectionIsInCursorTarget()) { + event.preventDefault(); + return this.expandSelectionInDirection("backward"); + } + }, + right(event) { + if (this.selectionIsInCursorTarget()) { + event.preventDefault(); + return this.expandSelectionInDirection("forward"); + } + } + }, + alt: { + backspace(event) { + var _this$delegate27; + this.setInputSummary({ + preferDocument: false + }); + return (_this$delegate27 = this.delegate) === null || _this$delegate27 === void 0 ? void 0 : _this$delegate27.inputControllerWillPerformTyping(); + } + }, + meta: { + backspace(event) { + var _this$delegate28; + this.setInputSummary({ + preferDocument: false + }); + return (_this$delegate28 = this.delegate) === null || _this$delegate28 === void 0 ? void 0 : _this$delegate28.inputControllerWillPerformTyping(); + } + } + }); + Level0InputController.proxyMethod("responder?.getSelectedRange"); + Level0InputController.proxyMethod("responder?.setSelectedRange"); + Level0InputController.proxyMethod("responder?.expandSelectionInDirection"); + Level0InputController.proxyMethod("responder?.selectionIsInCursorTarget"); + Level0InputController.proxyMethod("responder?.selectionIsExpanded"); + const extensionForFile = file => { + var _file$type; + return (_file$type = file.type) === null || _file$type === void 0 || (_file$type = _file$type.match(/\/(\w+)$/)) === null || _file$type === void 0 ? void 0 : _file$type[1]; + }; + const hasStringCodePointAt = !!((_$codePointAt = (_ = " ").codePointAt) !== null && _$codePointAt !== void 0 && _$codePointAt.call(_, 0)); + const stringFromKeyEvent = function (event) { + if (event.key && hasStringCodePointAt && event.key.codePointAt(0) === event.keyCode) { + return event.key; + } else { + let code; + if (event.which === null) { + code = event.keyCode; + } else if (event.which !== 0 && event.charCode !== 0) { + code = event.charCode; + } + if (code != null && keyNames[code] !== "escape") { + return UTF16String.fromCodepoints([code]).toString(); + } + } + }; + const pasteEventIsCrippledSafariHTMLPaste = function (event) { + const paste = event.clipboardData; + if (paste) { + if (paste.types.includes("text/html")) { + // Answer is yes if there's any possibility of Paste and Match Style in Safari, + // which is nearly impossible to detect confidently: https://bugs.webkit.org/show_bug.cgi?id=174165 + for (const type of paste.types) { + const hasPasteboardFlavor = /^CorePasteboardFlavorType/.test(type); + const hasReadableDynamicData = /^dyn\./.test(type) && paste.getData(type); + const mightBePasteAndMatchStyle = hasPasteboardFlavor || hasReadableDynamicData; + if (mightBePasteAndMatchStyle) { + return true; + } + } + return false; + } else { + const isExternalHTMLPaste = paste.types.includes("com.apple.webarchive"); + const isExternalRichTextPaste = paste.types.includes("com.apple.flat-rtfd"); + return isExternalHTMLPaste || isExternalRichTextPaste; + } + } + }; + class CompositionInput extends BasicObject { + constructor(inputController) { + super(...arguments); + this.inputController = inputController; + this.responder = this.inputController.responder; + this.delegate = this.inputController.delegate; + this.inputSummary = this.inputController.inputSummary; + this.data = {}; + } + start(data) { + this.data.start = data; + if (this.isSignificant()) { + var _this$responder5; + if (this.inputSummary.eventName === "keypress" && this.inputSummary.textAdded) { + var _this$responder4; + (_this$responder4 = this.responder) === null || _this$responder4 === void 0 || _this$responder4.deleteInDirection("left"); + } + if (!this.selectionIsExpanded()) { + this.insertPlaceholder(); + this.requestRender(); + } + this.range = (_this$responder5 = this.responder) === null || _this$responder5 === void 0 ? void 0 : _this$responder5.getSelectedRange(); + } + } + update(data) { + this.data.update = data; + if (this.isSignificant()) { + const range = this.selectPlaceholder(); + if (range) { + this.forgetPlaceholder(); + this.range = range; + } + } + } + end(data) { + this.data.end = data; + if (this.isSignificant()) { + this.forgetPlaceholder(); + if (this.canApplyToDocument()) { + var _this$delegate2, _this$responder6, _this$responder7, _this$responder8; + this.setInputSummary({ + preferDocument: true, + didInput: false + }); + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || _this$delegate2.inputControllerWillPerformTyping(); + (_this$responder6 = this.responder) === null || _this$responder6 === void 0 || _this$responder6.setSelectedRange(this.range); + (_this$responder7 = this.responder) === null || _this$responder7 === void 0 || _this$responder7.insertString(this.data.end); + return (_this$responder8 = this.responder) === null || _this$responder8 === void 0 ? void 0 : _this$responder8.setSelectedRange(this.range[0] + this.data.end.length); + } else if (this.data.start != null || this.data.update != null) { + this.requestReparse(); + return this.inputController.reset(); + } + } else { + return this.inputController.reset(); + } + } + getEndData() { + return this.data.end; + } + isEnded() { + return this.getEndData() != null; + } + isSignificant() { + if (browser.composesExistingText) { + return this.inputSummary.didInput; + } else { + return true; + } + } + + // Private + + canApplyToDocument() { + var _this$data$start, _this$data$end; + return ((_this$data$start = this.data.start) === null || _this$data$start === void 0 ? void 0 : _this$data$start.length) === 0 && ((_this$data$end = this.data.end) === null || _this$data$end === void 0 ? void 0 : _this$data$end.length) > 0 && this.range; + } + } + CompositionInput.proxyMethod("inputController.setInputSummary"); + CompositionInput.proxyMethod("inputController.requestRender"); + CompositionInput.proxyMethod("inputController.requestReparse"); + CompositionInput.proxyMethod("responder?.selectionIsExpanded"); + CompositionInput.proxyMethod("responder?.insertPlaceholder"); + CompositionInput.proxyMethod("responder?.selectPlaceholder"); + CompositionInput.proxyMethod("responder?.forgetPlaceholder"); + + class Level2InputController extends InputController { + constructor() { + super(...arguments); + this.render = this.render.bind(this); + } + elementDidMutate() { + if (this.scheduledRender) { + if (this.composing) { + var _this$delegate, _this$delegate$inputC; + return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidAllowUnhandledInput) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate); + } + } else { + return this.reparse(); + } + } + scheduleRender() { + return this.scheduledRender ? this.scheduledRender : this.scheduledRender = requestAnimationFrame(this.render); + } + render() { + var _this$afterRender; + cancelAnimationFrame(this.scheduledRender); + this.scheduledRender = null; + if (!this.composing) { + var _this$delegate2; + (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || _this$delegate2.render(); + } + (_this$afterRender = this.afterRender) === null || _this$afterRender === void 0 || _this$afterRender.call(this); + this.afterRender = null; + } + reparse() { + var _this$delegate3; + return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : _this$delegate3.reparse(); + } + + // Responder helpers + + insertString() { + var _this$delegate4; + let string = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + let options = arguments.length > 1 ? arguments[1] : undefined; + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillPerformTyping(); + return this.withTargetDOMRange(function () { + var _this$responder; + return (_this$responder = this.responder) === null || _this$responder === void 0 ? void 0 : _this$responder.insertString(string, options); + }); + } + toggleAttributeIfSupported(attributeName) { + if (getAllAttributeNames().includes(attributeName)) { + var _this$delegate5; + (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.inputControllerWillPerformFormatting(attributeName); + return this.withTargetDOMRange(function () { + var _this$responder2; + return (_this$responder2 = this.responder) === null || _this$responder2 === void 0 ? void 0 : _this$responder2.toggleCurrentAttribute(attributeName); + }); + } + } + activateAttributeIfSupported(attributeName, value) { + if (getAllAttributeNames().includes(attributeName)) { + var _this$delegate6; + (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || _this$delegate6.inputControllerWillPerformFormatting(attributeName); + return this.withTargetDOMRange(function () { + var _this$responder3; + return (_this$responder3 = this.responder) === null || _this$responder3 === void 0 ? void 0 : _this$responder3.setCurrentAttribute(attributeName, value); + }); + } + } + deleteInDirection(direction) { + let { + recordUndoEntry + } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + recordUndoEntry: true + }; + if (recordUndoEntry) { + var _this$delegate7; + (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || _this$delegate7.inputControllerWillPerformTyping(); + } + const perform = () => { + var _this$responder4; + return (_this$responder4 = this.responder) === null || _this$responder4 === void 0 ? void 0 : _this$responder4.deleteInDirection(direction); + }; + const domRange = this.getTargetDOMRange({ + minLength: this.composing ? 1 : 2 + }); + if (domRange) { + return this.withTargetDOMRange(domRange, perform); + } else { + return perform(); + } + } + + // Selection helpers + + withTargetDOMRange(domRange, fn) { + if (typeof domRange === "function") { + fn = domRange; + domRange = this.getTargetDOMRange(); + } + if (domRange) { + var _this$responder5; + return (_this$responder5 = this.responder) === null || _this$responder5 === void 0 ? void 0 : _this$responder5.withTargetDOMRange(domRange, fn.bind(this)); + } else { + selectionChangeObserver.reset(); + return fn.call(this); + } + } + getTargetDOMRange() { + var _this$event$getTarget, _this$event; + let { + minLength + } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { + minLength: 0 + }; + const targetRanges = (_this$event$getTarget = (_this$event = this.event).getTargetRanges) === null || _this$event$getTarget === void 0 ? void 0 : _this$event$getTarget.call(_this$event); + if (targetRanges) { + if (targetRanges.length) { + const domRange = staticRangeToRange(targetRanges[0]); + if (minLength === 0 || domRange.toString().length >= minLength) { + return domRange; + } + } + } + } + withEvent(event, fn) { + let result; + this.event = event; + try { + result = fn.call(this); + } finally { + this.event = null; + } + return result; + } + } + _defineProperty(Level2InputController, "events", { + keydown(event) { + if (keyEventIsKeyboardCommand(event)) { + var _this$delegate8; + const command = keyboardCommandFromKeyEvent(event); + if ((_this$delegate8 = this.delegate) !== null && _this$delegate8 !== void 0 && _this$delegate8.inputControllerDidReceiveKeyboardCommand(command)) { + event.preventDefault(); + } + } else { + let name = event.key; + if (event.altKey) { + name += "+Alt"; + } + if (event.shiftKey) { + name += "+Shift"; + } + const handler = this.constructor.keys[name]; + if (handler) { + return this.withEvent(event, handler); + } + } + }, + // Handle paste event to work around beforeinput.insertFromPaste browser bugs. + // Safe to remove each condition once fixed upstream. + paste(event) { + var _event$clipboardData; + // https://bugs.webkit.org/show_bug.cgi?id=194921 + let paste; + const href = (_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.getData("URL"); + if (pasteEventHasFilesOnly(event)) { + event.preventDefault(); + return this.attachFiles(event.clipboardData.files); + + // https://bugs.chromium.org/p/chromium/issues/detail?id=934448 + } else if (pasteEventHasPlainTextOnly(event)) { + var _this$delegate9, _this$responder6, _this$delegate10; + event.preventDefault(); + paste = { + type: "text/plain", + string: event.clipboardData.getData("text/plain") + }; + (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || _this$delegate9.inputControllerWillPaste(paste); + (_this$responder6 = this.responder) === null || _this$responder6 === void 0 || _this$responder6.insertString(paste.string); + this.render(); + return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 ? void 0 : _this$delegate10.inputControllerDidPaste(paste); + + // https://bugs.webkit.org/show_bug.cgi?id=196702 + } else if (href) { + var _this$delegate11, _this$responder7, _this$delegate12; + event.preventDefault(); + paste = { + type: "text/html", + html: this.createLinkHTML(href) + }; + (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 || _this$delegate11.inputControllerWillPaste(paste); + (_this$responder7 = this.responder) === null || _this$responder7 === void 0 || _this$responder7.insertHTML(paste.html); + this.render(); + return (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 ? void 0 : _this$delegate12.inputControllerDidPaste(paste); + } + }, + beforeinput(event) { + const handler = this.constructor.inputTypes[event.inputType]; + const immmediateRender = shouldRenderInmmediatelyToDealWithIOSDictation(event); + if (handler) { + this.withEvent(event, handler); + if (!immmediateRender) { + this.scheduleRender(); + } + } + if (immmediateRender) { + this.render(); + } + }, + input(event) { + selectionChangeObserver.reset(); + }, + dragstart(event) { + var _this$responder8; + if ((_this$responder8 = this.responder) !== null && _this$responder8 !== void 0 && _this$responder8.selectionContainsAttachments()) { + var _this$responder9; + event.dataTransfer.setData("application/x-trix-dragging", true); + this.dragging = { + range: (_this$responder9 = this.responder) === null || _this$responder9 === void 0 ? void 0 : _this$responder9.getSelectedRange(), + point: pointFromEvent(event) + }; + } + }, + dragenter(event) { + if (dragEventHasFiles(event)) { + event.preventDefault(); + } + }, + dragover(event) { + if (this.dragging) { + event.preventDefault(); + const point = pointFromEvent(event); + if (!objectsAreEqual(point, this.dragging.point)) { + var _this$responder10; + this.dragging.point = point; + return (_this$responder10 = this.responder) === null || _this$responder10 === void 0 ? void 0 : _this$responder10.setLocationRangeFromPointRange(point); + } + } else if (dragEventHasFiles(event)) { + event.preventDefault(); + } + }, + drop(event) { + if (this.dragging) { + var _this$delegate13, _this$responder11; + event.preventDefault(); + (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || _this$delegate13.inputControllerWillMoveText(); + (_this$responder11 = this.responder) === null || _this$responder11 === void 0 || _this$responder11.moveTextFromRange(this.dragging.range); + this.dragging = null; + return this.scheduleRender(); + } else if (dragEventHasFiles(event)) { + var _this$responder12; + event.preventDefault(); + const point = pointFromEvent(event); + (_this$responder12 = this.responder) === null || _this$responder12 === void 0 || _this$responder12.setLocationRangeFromPointRange(point); + return this.attachFiles(event.dataTransfer.files); + } + }, + dragend() { + if (this.dragging) { + var _this$responder13; + (_this$responder13 = this.responder) === null || _this$responder13 === void 0 || _this$responder13.setSelectedRange(this.dragging.range); + this.dragging = null; + } + }, + compositionend(event) { + if (this.composing) { + this.composing = false; + if (!browser$1.recentAndroid) this.scheduleRender(); + } + } + }); + _defineProperty(Level2InputController, "keys", { + ArrowLeft() { + var _this$responder14; + if ((_this$responder14 = this.responder) !== null && _this$responder14 !== void 0 && _this$responder14.shouldManageMovingCursorInDirection("backward")) { + var _this$responder15; + this.event.preventDefault(); + return (_this$responder15 = this.responder) === null || _this$responder15 === void 0 ? void 0 : _this$responder15.moveCursorInDirection("backward"); + } + }, + ArrowRight() { + var _this$responder16; + if ((_this$responder16 = this.responder) !== null && _this$responder16 !== void 0 && _this$responder16.shouldManageMovingCursorInDirection("forward")) { + var _this$responder17; + this.event.preventDefault(); + return (_this$responder17 = this.responder) === null || _this$responder17 === void 0 ? void 0 : _this$responder17.moveCursorInDirection("forward"); + } + }, + Backspace() { + var _this$responder18; + if ((_this$responder18 = this.responder) !== null && _this$responder18 !== void 0 && _this$responder18.shouldManageDeletingInDirection("backward")) { + var _this$delegate14, _this$responder19; + this.event.preventDefault(); + (_this$delegate14 = this.delegate) === null || _this$delegate14 === void 0 || _this$delegate14.inputControllerWillPerformTyping(); + (_this$responder19 = this.responder) === null || _this$responder19 === void 0 || _this$responder19.deleteInDirection("backward"); + return this.render(); + } + }, + Tab() { + var _this$responder20; + if ((_this$responder20 = this.responder) !== null && _this$responder20 !== void 0 && _this$responder20.canIncreaseNestingLevel()) { + var _this$responder21; + this.event.preventDefault(); + (_this$responder21 = this.responder) === null || _this$responder21 === void 0 || _this$responder21.increaseNestingLevel(); + return this.render(); + } + }, + "Tab+Shift"() { + var _this$responder22; + if ((_this$responder22 = this.responder) !== null && _this$responder22 !== void 0 && _this$responder22.canDecreaseNestingLevel()) { + var _this$responder23; + this.event.preventDefault(); + (_this$responder23 = this.responder) === null || _this$responder23 === void 0 || _this$responder23.decreaseNestingLevel(); + return this.render(); + } + } + }); + _defineProperty(Level2InputController, "inputTypes", { + deleteByComposition() { + return this.deleteInDirection("backward", { + recordUndoEntry: false + }); + }, + deleteByCut() { + return this.deleteInDirection("backward"); + }, + deleteByDrag() { + this.event.preventDefault(); + return this.withTargetDOMRange(function () { + var _this$responder24; + this.deleteByDragRange = (_this$responder24 = this.responder) === null || _this$responder24 === void 0 ? void 0 : _this$responder24.getSelectedRange(); + }); + }, + deleteCompositionText() { + return this.deleteInDirection("backward", { + recordUndoEntry: false + }); + }, + deleteContent() { + return this.deleteInDirection("backward"); + }, + deleteContentBackward() { + return this.deleteInDirection("backward"); + }, + deleteContentForward() { + return this.deleteInDirection("forward"); + }, + deleteEntireSoftLine() { + return this.deleteInDirection("forward"); + }, + deleteHardLineBackward() { + return this.deleteInDirection("backward"); + }, + deleteHardLineForward() { + return this.deleteInDirection("forward"); + }, + deleteSoftLineBackward() { + return this.deleteInDirection("backward"); + }, + deleteSoftLineForward() { + return this.deleteInDirection("forward"); + }, + deleteWordBackward() { + return this.deleteInDirection("backward"); + }, + deleteWordForward() { + return this.deleteInDirection("forward"); + }, + formatBackColor() { + return this.activateAttributeIfSupported("backgroundColor", this.event.data); + }, + formatBold() { + return this.toggleAttributeIfSupported("bold"); + }, + formatFontColor() { + return this.activateAttributeIfSupported("color", this.event.data); + }, + formatFontName() { + return this.activateAttributeIfSupported("font", this.event.data); + }, + formatIndent() { + var _this$responder25; + if ((_this$responder25 = this.responder) !== null && _this$responder25 !== void 0 && _this$responder25.canIncreaseNestingLevel()) { + return this.withTargetDOMRange(function () { + var _this$responder26; + return (_this$responder26 = this.responder) === null || _this$responder26 === void 0 ? void 0 : _this$responder26.increaseNestingLevel(); + }); + } + }, + formatItalic() { + return this.toggleAttributeIfSupported("italic"); + }, + formatJustifyCenter() { + return this.toggleAttributeIfSupported("justifyCenter"); + }, + formatJustifyFull() { + return this.toggleAttributeIfSupported("justifyFull"); + }, + formatJustifyLeft() { + return this.toggleAttributeIfSupported("justifyLeft"); + }, + formatJustifyRight() { + return this.toggleAttributeIfSupported("justifyRight"); + }, + formatOutdent() { + var _this$responder27; + if ((_this$responder27 = this.responder) !== null && _this$responder27 !== void 0 && _this$responder27.canDecreaseNestingLevel()) { + return this.withTargetDOMRange(function () { + var _this$responder28; + return (_this$responder28 = this.responder) === null || _this$responder28 === void 0 ? void 0 : _this$responder28.decreaseNestingLevel(); + }); + } + }, + formatRemove() { + this.withTargetDOMRange(function () { + for (const attributeName in (_this$responder29 = this.responder) === null || _this$responder29 === void 0 ? void 0 : _this$responder29.getCurrentAttributes()) { + var _this$responder29, _this$responder30; + (_this$responder30 = this.responder) === null || _this$responder30 === void 0 || _this$responder30.removeCurrentAttribute(attributeName); + } + }); + }, + formatSetBlockTextDirection() { + return this.activateAttributeIfSupported("blockDir", this.event.data); + }, + formatSetInlineTextDirection() { + return this.activateAttributeIfSupported("textDir", this.event.data); + }, + formatStrikeThrough() { + return this.toggleAttributeIfSupported("strike"); + }, + formatSubscript() { + return this.toggleAttributeIfSupported("sub"); + }, + formatSuperscript() { + return this.toggleAttributeIfSupported("sup"); + }, + formatUnderline() { + return this.toggleAttributeIfSupported("underline"); + }, + historyRedo() { + var _this$delegate15; + return (_this$delegate15 = this.delegate) === null || _this$delegate15 === void 0 ? void 0 : _this$delegate15.inputControllerWillPerformRedo(); + }, + historyUndo() { + var _this$delegate16; + return (_this$delegate16 = this.delegate) === null || _this$delegate16 === void 0 ? void 0 : _this$delegate16.inputControllerWillPerformUndo(); + }, + insertCompositionText() { + this.composing = true; + return this.insertString(this.event.data); + }, + insertFromComposition() { + this.composing = false; + return this.insertString(this.event.data); + }, + insertFromDrop() { + const range = this.deleteByDragRange; + if (range) { + var _this$delegate17; + this.deleteByDragRange = null; + (_this$delegate17 = this.delegate) === null || _this$delegate17 === void 0 || _this$delegate17.inputControllerWillMoveText(); + return this.withTargetDOMRange(function () { + var _this$responder31; + return (_this$responder31 = this.responder) === null || _this$responder31 === void 0 ? void 0 : _this$responder31.moveTextFromRange(range); + }); + } + }, + insertFromPaste() { + const { + dataTransfer + } = this.event; + const paste = { + dataTransfer + }; + const href = dataTransfer.getData("URL"); + const html = dataTransfer.getData("text/html"); + if (href) { + var _this$delegate18; + let string; + this.event.preventDefault(); + paste.type = "text/html"; + const name = dataTransfer.getData("public.url-name"); + if (name) { + string = squishBreakableWhitespace(name).trim(); + } else { + string = href; + } + paste.html = this.createLinkHTML(href, string); + (_this$delegate18 = this.delegate) === null || _this$delegate18 === void 0 || _this$delegate18.inputControllerWillPaste(paste); + this.withTargetDOMRange(function () { + var _this$responder32; + return (_this$responder32 = this.responder) === null || _this$responder32 === void 0 ? void 0 : _this$responder32.insertHTML(paste.html); + }); + this.afterRender = () => { + var _this$delegate19; + return (_this$delegate19 = this.delegate) === null || _this$delegate19 === void 0 ? void 0 : _this$delegate19.inputControllerDidPaste(paste); + }; + } else if (dataTransferIsPlainText(dataTransfer)) { + var _this$delegate20; + paste.type = "text/plain"; + paste.string = dataTransfer.getData("text/plain"); + (_this$delegate20 = this.delegate) === null || _this$delegate20 === void 0 || _this$delegate20.inputControllerWillPaste(paste); + this.withTargetDOMRange(function () { + var _this$responder33; + return (_this$responder33 = this.responder) === null || _this$responder33 === void 0 ? void 0 : _this$responder33.insertString(paste.string); + }); + this.afterRender = () => { + var _this$delegate21; + return (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 ? void 0 : _this$delegate21.inputControllerDidPaste(paste); + }; + } else if (processableFilePaste(this.event)) { + var _this$delegate22; + paste.type = "File"; + paste.file = dataTransfer.files[0]; + (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 || _this$delegate22.inputControllerWillPaste(paste); + this.withTargetDOMRange(function () { + var _this$responder34; + return (_this$responder34 = this.responder) === null || _this$responder34 === void 0 ? void 0 : _this$responder34.insertFile(paste.file); + }); + this.afterRender = () => { + var _this$delegate23; + return (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 ? void 0 : _this$delegate23.inputControllerDidPaste(paste); + }; + } else if (html) { + var _this$delegate24; + this.event.preventDefault(); + paste.type = "text/html"; + paste.html = html; + (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 || _this$delegate24.inputControllerWillPaste(paste); + this.withTargetDOMRange(function () { + var _this$responder35; + return (_this$responder35 = this.responder) === null || _this$responder35 === void 0 ? void 0 : _this$responder35.insertHTML(paste.html); + }); + this.afterRender = () => { + var _this$delegate25; + return (_this$delegate25 = this.delegate) === null || _this$delegate25 === void 0 ? void 0 : _this$delegate25.inputControllerDidPaste(paste); + }; + } + }, + insertFromYank() { + return this.insertString(this.event.data); + }, + insertLineBreak() { + return this.insertString("\n"); + }, + insertLink() { + return this.activateAttributeIfSupported("href", this.event.data); + }, + insertOrderedList() { + return this.toggleAttributeIfSupported("number"); + }, + insertParagraph() { + var _this$delegate26; + (_this$delegate26 = this.delegate) === null || _this$delegate26 === void 0 || _this$delegate26.inputControllerWillPerformTyping(); + return this.withTargetDOMRange(function () { + var _this$responder36; + return (_this$responder36 = this.responder) === null || _this$responder36 === void 0 ? void 0 : _this$responder36.insertLineBreak(); + }); + }, + insertReplacementText() { + const replacement = this.event.dataTransfer.getData("text/plain"); + const domRange = this.event.getTargetRanges()[0]; + this.withTargetDOMRange(domRange, () => { + this.insertString(replacement, { + updatePosition: false + }); + }); + }, + insertText() { + var _this$event$dataTrans; + return this.insertString(this.event.data || ((_this$event$dataTrans = this.event.dataTransfer) === null || _this$event$dataTrans === void 0 ? void 0 : _this$event$dataTrans.getData("text/plain"))); + }, + insertTranspose() { + return this.insertString(this.event.data); + }, + insertUnorderedList() { + return this.toggleAttributeIfSupported("bullet"); + } + }); + const staticRangeToRange = function (staticRange) { + const range = document.createRange(); + range.setStart(staticRange.startContainer, staticRange.startOffset); + range.setEnd(staticRange.endContainer, staticRange.endOffset); + return range; + }; + + // Event helpers + + const dragEventHasFiles = event => { + var _event$dataTransfer; + return Array.from(((_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.types) || []).includes("Files"); + }; + const processableFilePaste = event => { + var _event$dataTransfer$f; + // Paste events that only have files are handled by the paste event handler, + // to work around Safari not supporting beforeinput.insertFromPaste for files. + + // MS Office text pastes include a file with a screenshot of the text, but we should + // handle them as text pastes. + return ((_event$dataTransfer$f = event.dataTransfer.files) === null || _event$dataTransfer$f === void 0 ? void 0 : _event$dataTransfer$f[0]) && !pasteEventHasFilesOnly(event) && !dataTransferIsMsOfficePaste(event); + }; + const pasteEventHasFilesOnly = function (event) { + const clipboard = event.clipboardData; + if (clipboard) { + const fileTypes = Array.from(clipboard.types).filter(type => type.match(/file/i)); // "Files", "application/x-moz-file" + return fileTypes.length === clipboard.types.length && clipboard.files.length >= 1; + } + }; + const pasteEventHasPlainTextOnly = function (event) { + const clipboard = event.clipboardData; + if (clipboard) { + return clipboard.types.includes("text/plain") && clipboard.types.length === 1; + } + }; + const keyboardCommandFromKeyEvent = function (event) { + const command = []; + if (event.altKey) { + command.push("alt"); + } + if (event.shiftKey) { + command.push("shift"); + } + command.push(event.key); + return command; + }; + const pointFromEvent = event => ({ + x: event.clientX, + y: event.clientY + }); + + const attributeButtonSelector = "[data-trix-attribute]"; + const actionButtonSelector = "[data-trix-action]"; + const toolbarButtonSelector = "".concat(attributeButtonSelector, ", ").concat(actionButtonSelector); + const dialogSelector = "[data-trix-dialog]"; + const activeDialogSelector = "".concat(dialogSelector, "[data-trix-active]"); + const dialogButtonSelector = "".concat(dialogSelector, " [data-trix-method]"); + const dialogInputSelector = "".concat(dialogSelector, " [data-trix-input]"); + const getInputForDialog = (element, attributeName) => { + if (!attributeName) { + attributeName = getAttributeName(element); + } + return element.querySelector("[data-trix-input][name='".concat(attributeName, "']")); + }; + const getActionName = element => element.getAttribute("data-trix-action"); + const getAttributeName = element => { + return element.getAttribute("data-trix-attribute") || element.getAttribute("data-trix-dialog-attribute"); + }; + const getDialogName = element => element.getAttribute("data-trix-dialog"); + class ToolbarController extends BasicObject { + constructor(element) { + super(element); + this.didClickActionButton = this.didClickActionButton.bind(this); + this.didClickAttributeButton = this.didClickAttributeButton.bind(this); + this.didClickDialogButton = this.didClickDialogButton.bind(this); + this.didKeyDownDialogInput = this.didKeyDownDialogInput.bind(this); + this.element = element; + this.attributes = {}; + this.actions = {}; + this.resetDialogInputs(); + handleEvent("mousedown", { + onElement: this.element, + matchingSelector: actionButtonSelector, + withCallback: this.didClickActionButton + }); + handleEvent("mousedown", { + onElement: this.element, + matchingSelector: attributeButtonSelector, + withCallback: this.didClickAttributeButton + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: toolbarButtonSelector, + preventDefault: true + }); + handleEvent("click", { + onElement: this.element, + matchingSelector: dialogButtonSelector, + withCallback: this.didClickDialogButton + }); + handleEvent("keydown", { + onElement: this.element, + matchingSelector: dialogInputSelector, + withCallback: this.didKeyDownDialogInput + }); + } + + // Event handlers + + didClickActionButton(event, element) { + var _this$delegate; + (_this$delegate = this.delegate) === null || _this$delegate === void 0 || _this$delegate.toolbarDidClickButton(); + event.preventDefault(); + const actionName = getActionName(element); + if (this.getDialog(actionName)) { + return this.toggleDialog(actionName); + } else { + var _this$delegate2; + return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.toolbarDidInvokeAction(actionName, element); + } + } + didClickAttributeButton(event, element) { + var _this$delegate3; + (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || _this$delegate3.toolbarDidClickButton(); + event.preventDefault(); + const attributeName = getAttributeName(element); + if (this.getDialog(attributeName)) { + this.toggleDialog(attributeName); + } else { + var _this$delegate4; + (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.toolbarDidToggleAttribute(attributeName); + } + return this.refreshAttributeButtons(); + } + didClickDialogButton(event, element) { + const dialogElement = findClosestElementFromNode(element, { + matchingSelector: dialogSelector + }); + const method = element.getAttribute("data-trix-method"); + return this[method].call(this, dialogElement); + } + didKeyDownDialogInput(event, element) { + if (event.keyCode === 13) { + // Enter key + event.preventDefault(); + const attribute = element.getAttribute("name"); + const dialog = this.getDialog(attribute); + this.setAttribute(dialog); + } + if (event.keyCode === 27) { + // Escape key + event.preventDefault(); + return this.hideDialog(); + } + } + + // Action buttons + + updateActions(actions) { + this.actions = actions; + return this.refreshActionButtons(); + } + refreshActionButtons() { + return this.eachActionButton((element, actionName) => { + element.disabled = this.actions[actionName] === false; + }); + } + eachActionButton(callback) { + return Array.from(this.element.querySelectorAll(actionButtonSelector)).map(element => callback(element, getActionName(element))); + } + + // Attribute buttons + + updateAttributes(attributes) { + this.attributes = attributes; + return this.refreshAttributeButtons(); + } + refreshAttributeButtons() { + return this.eachAttributeButton((element, attributeName) => { + element.disabled = this.attributes[attributeName] === false; + if (this.attributes[attributeName] || this.dialogIsVisible(attributeName)) { + element.setAttribute("data-trix-active", ""); + return element.classList.add("trix-active"); + } else { + element.removeAttribute("data-trix-active"); + return element.classList.remove("trix-active"); + } + }); + } + eachAttributeButton(callback) { + return Array.from(this.element.querySelectorAll(attributeButtonSelector)).map(element => callback(element, getAttributeName(element))); + } + applyKeyboardCommand(keys) { + const keyString = JSON.stringify(keys.sort()); + for (const button of Array.from(this.element.querySelectorAll("[data-trix-key]"))) { + const buttonKeys = button.getAttribute("data-trix-key").split("+"); + const buttonKeyString = JSON.stringify(buttonKeys.sort()); + if (buttonKeyString === keyString) { + triggerEvent("mousedown", { + onElement: button + }); + return true; + } + } + return false; + } + + // Dialogs + + dialogIsVisible(dialogName) { + const element = this.getDialog(dialogName); + if (element) { + return element.hasAttribute("data-trix-active"); + } + } + toggleDialog(dialogName) { + if (this.dialogIsVisible(dialogName)) { + return this.hideDialog(); + } else { + return this.showDialog(dialogName); + } + } + showDialog(dialogName) { + var _this$delegate5, _this$delegate6; + this.hideDialog(); + (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.toolbarWillShowDialog(); + const element = this.getDialog(dialogName); + element.setAttribute("data-trix-active", ""); + element.classList.add("trix-active"); + Array.from(element.querySelectorAll("input[disabled]")).forEach(disabledInput => { + disabledInput.removeAttribute("disabled"); + }); + const attributeName = getAttributeName(element); + if (attributeName) { + const input = getInputForDialog(element, dialogName); + if (input) { + input.value = this.attributes[attributeName] || ""; + input.select(); + } + } + return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 ? void 0 : _this$delegate6.toolbarDidShowDialog(dialogName); + } + setAttribute(dialogElement) { + const attributeName = getAttributeName(dialogElement); + const input = getInputForDialog(dialogElement, attributeName); + if (input.willValidate && !input.checkValidity()) { + input.setAttribute("data-trix-validate", ""); + input.classList.add("trix-validate"); + return input.focus(); + } else { + var _this$delegate7; + (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || _this$delegate7.toolbarDidUpdateAttribute(attributeName, input.value); + return this.hideDialog(); + } + } + removeAttribute(dialogElement) { + var _this$delegate8; + const attributeName = getAttributeName(dialogElement); + (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || _this$delegate8.toolbarDidRemoveAttribute(attributeName); + return this.hideDialog(); + } + hideDialog() { + const element = this.element.querySelector(activeDialogSelector); + if (element) { + var _this$delegate9; + element.removeAttribute("data-trix-active"); + element.classList.remove("trix-active"); + this.resetDialogInputs(); + return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 ? void 0 : _this$delegate9.toolbarDidHideDialog(getDialogName(element)); + } + } + resetDialogInputs() { + Array.from(this.element.querySelectorAll(dialogInputSelector)).forEach(input => { + input.setAttribute("disabled", "disabled"); + input.removeAttribute("data-trix-validate"); + input.classList.remove("trix-validate"); + }); + } + getDialog(dialogName) { + return this.element.querySelector("[data-trix-dialog=".concat(dialogName, "]")); + } + } + + const snapshotsAreEqual = (a, b) => rangesAreEqual(a.selectedRange, b.selectedRange) && a.document.isEqualTo(b.document); + class EditorController extends Controller { + constructor(_ref) { + let { + editorElement, + document, + html + } = _ref; + super(...arguments); + this.editorElement = editorElement; + this.selectionManager = new SelectionManager(this.editorElement); + this.selectionManager.delegate = this; + this.composition = new Composition(); + this.composition.delegate = this; + this.attachmentManager = new AttachmentManager(this.composition.getAttachments()); + this.attachmentManager.delegate = this; + this.inputController = input.getLevel() === 2 ? new Level2InputController(this.editorElement) : new Level0InputController(this.editorElement); + this.inputController.delegate = this; + this.inputController.responder = this.composition; + this.compositionController = new CompositionController(this.editorElement, this.composition); + this.compositionController.delegate = this; + this.toolbarController = new ToolbarController(this.editorElement.toolbarElement); + this.toolbarController.delegate = this; + this.editor = new Editor(this.composition, this.selectionManager, this.editorElement); + if (document) { + this.editor.loadDocument(document); + } else { + this.editor.loadHTML(html); + } + } + registerSelectionManager() { + return selectionChangeObserver.registerSelectionManager(this.selectionManager); + } + unregisterSelectionManager() { + return selectionChangeObserver.unregisterSelectionManager(this.selectionManager); + } + render() { + return this.compositionController.render(); + } + reparse() { + return this.composition.replaceHTML(this.editorElement.innerHTML); + } + + // Composition delegate + + compositionDidChangeDocument(document) { + this.notifyEditorElement("document-change"); + if (!this.handlingInput) { + return this.render(); + } + } + compositionDidChangeCurrentAttributes(currentAttributes) { + this.currentAttributes = currentAttributes; + this.toolbarController.updateAttributes(this.currentAttributes); + this.updateCurrentActions(); + return this.notifyEditorElement("attributes-change", { + attributes: this.currentAttributes + }); + } + compositionDidPerformInsertionAtRange(range) { + if (this.pasting) { + this.pastedRange = range; + } + } + compositionShouldAcceptFile(file) { + return this.notifyEditorElement("file-accept", { + file + }); + } + compositionDidAddAttachment(attachment) { + const managedAttachment = this.attachmentManager.manageAttachment(attachment); + return this.notifyEditorElement("attachment-add", { + attachment: managedAttachment + }); + } + compositionDidEditAttachment(attachment) { + this.compositionController.rerenderViewForObject(attachment); + const managedAttachment = this.attachmentManager.manageAttachment(attachment); + this.notifyEditorElement("attachment-edit", { + attachment: managedAttachment + }); + return this.notifyEditorElement("change"); + } + compositionDidChangeAttachmentPreviewURL(attachment) { + this.compositionController.invalidateViewForObject(attachment); + return this.notifyEditorElement("change"); + } + compositionDidRemoveAttachment(attachment) { + const managedAttachment = this.attachmentManager.unmanageAttachment(attachment); + return this.notifyEditorElement("attachment-remove", { + attachment: managedAttachment + }); + } + compositionDidStartEditingAttachment(attachment, options) { + this.attachmentLocationRange = this.composition.document.getLocationRangeOfAttachment(attachment); + this.compositionController.installAttachmentEditorForAttachment(attachment, options); + return this.selectionManager.setLocationRange(this.attachmentLocationRange); + } + compositionDidStopEditingAttachment(attachment) { + this.compositionController.uninstallAttachmentEditor(); + this.attachmentLocationRange = null; + } + compositionDidRequestChangingSelectionToLocationRange(locationRange) { + if (this.loadingSnapshot && !this.isFocused()) return; + this.requestedLocationRange = locationRange; + this.compositionRevisionWhenLocationRangeRequested = this.composition.revision; + if (!this.handlingInput) { + return this.render(); + } + } + compositionWillLoadSnapshot() { + this.loadingSnapshot = true; + } + compositionDidLoadSnapshot() { + this.compositionController.refreshViewCache(); + this.render(); + this.loadingSnapshot = false; + } + getSelectionManager() { + return this.selectionManager; + } + + // Attachment manager delegate + + attachmentManagerDidRequestRemovalOfAttachment(attachment) { + return this.removeAttachment(attachment); + } + + // Document controller delegate + + compositionControllerWillSyncDocumentView() { + this.inputController.editorWillSyncDocumentView(); + this.selectionManager.lock(); + return this.selectionManager.clearSelection(); + } + compositionControllerDidSyncDocumentView() { + this.inputController.editorDidSyncDocumentView(); + this.selectionManager.unlock(); + this.updateCurrentActions(); + return this.notifyEditorElement("sync"); + } + compositionControllerDidRender() { + if (this.requestedLocationRange) { + if (this.compositionRevisionWhenLocationRangeRequested === this.composition.revision) { + this.selectionManager.setLocationRange(this.requestedLocationRange); + } + this.requestedLocationRange = null; + this.compositionRevisionWhenLocationRangeRequested = null; + } + if (this.renderedCompositionRevision !== this.composition.revision) { + this.runEditorFilters(); + this.composition.updateCurrentAttributes(); + this.notifyEditorElement("render"); + } + this.renderedCompositionRevision = this.composition.revision; + } + compositionControllerDidFocus() { + if (this.isFocusedInvisibly()) { + this.setLocationRange({ + index: 0, + offset: 0 + }); + } + this.toolbarController.hideDialog(); + return this.notifyEditorElement("focus"); + } + compositionControllerDidBlur() { + return this.notifyEditorElement("blur"); + } + compositionControllerDidSelectAttachment(attachment, options) { + this.toolbarController.hideDialog(); + return this.composition.editAttachment(attachment, options); + } + compositionControllerDidRequestDeselectingAttachment(attachment) { + const locationRange = this.attachmentLocationRange || this.composition.document.getLocationRangeOfAttachment(attachment); + return this.selectionManager.setLocationRange(locationRange[1]); + } + compositionControllerWillUpdateAttachment(attachment) { + return this.editor.recordUndoEntry("Edit Attachment", { + context: attachment.id, + consolidatable: true + }); + } + compositionControllerDidRequestRemovalOfAttachment(attachment) { + return this.removeAttachment(attachment); + } + + // Input controller delegate + + inputControllerWillHandleInput() { + this.handlingInput = true; + this.requestedRender = false; + } + inputControllerDidRequestRender() { + this.requestedRender = true; + } + inputControllerDidHandleInput() { + this.handlingInput = false; + if (this.requestedRender) { + this.requestedRender = false; + return this.render(); + } + } + inputControllerDidAllowUnhandledInput() { + return this.notifyEditorElement("change"); + } + inputControllerDidRequestReparse() { + return this.reparse(); + } + inputControllerWillPerformTyping() { + return this.recordTypingUndoEntry(); + } + inputControllerWillPerformFormatting(attributeName) { + return this.recordFormattingUndoEntry(attributeName); + } + inputControllerWillCutText() { + return this.editor.recordUndoEntry("Cut"); + } + inputControllerWillPaste(paste) { + this.editor.recordUndoEntry("Paste"); + this.pasting = true; + return this.notifyEditorElement("before-paste", { + paste + }); + } + inputControllerDidPaste(paste) { + paste.range = this.pastedRange; + this.pastedRange = null; + this.pasting = null; + return this.notifyEditorElement("paste", { + paste + }); + } + inputControllerWillMoveText() { + return this.editor.recordUndoEntry("Move"); + } + inputControllerWillAttachFiles() { + return this.editor.recordUndoEntry("Drop Files"); + } + inputControllerWillPerformUndo() { + return this.editor.undo(); + } + inputControllerWillPerformRedo() { + return this.editor.redo(); + } + inputControllerDidReceiveKeyboardCommand(keys) { + return this.toolbarController.applyKeyboardCommand(keys); + } + inputControllerDidStartDrag() { + this.locationRangeBeforeDrag = this.selectionManager.getLocationRange(); + } + inputControllerDidReceiveDragOverPoint(point) { + return this.selectionManager.setLocationRangeFromPointRange(point); + } + inputControllerDidCancelDrag() { + this.selectionManager.setLocationRange(this.locationRangeBeforeDrag); + this.locationRangeBeforeDrag = null; + } + + // Selection manager delegate + + locationRangeDidChange(locationRange) { + this.composition.updateCurrentAttributes(); + this.updateCurrentActions(); + if (this.attachmentLocationRange && !rangesAreEqual(this.attachmentLocationRange, locationRange)) { + this.composition.stopEditingAttachment(); + } + return this.notifyEditorElement("selection-change"); + } + + // Toolbar controller delegate + + toolbarDidClickButton() { + if (!this.getLocationRange()) { + return this.setLocationRange({ + index: 0, + offset: 0 + }); + } + } + toolbarDidInvokeAction(actionName, invokingElement) { + return this.invokeAction(actionName, invokingElement); + } + toolbarDidToggleAttribute(attributeName) { + this.recordFormattingUndoEntry(attributeName); + this.composition.toggleCurrentAttribute(attributeName); + this.render(); + if (!this.selectionFrozen) { + return this.editorElement.focus(); + } + } + toolbarDidUpdateAttribute(attributeName, value) { + this.recordFormattingUndoEntry(attributeName); + this.composition.setCurrentAttribute(attributeName, value); + this.render(); + if (!this.selectionFrozen) { + return this.editorElement.focus(); + } + } + toolbarDidRemoveAttribute(attributeName) { + this.recordFormattingUndoEntry(attributeName); + this.composition.removeCurrentAttribute(attributeName); + this.render(); + if (!this.selectionFrozen) { + return this.editorElement.focus(); + } + } + toolbarWillShowDialog(dialogElement) { + this.composition.expandSelectionForEditing(); + return this.freezeSelection(); + } + toolbarDidShowDialog(dialogName) { + return this.notifyEditorElement("toolbar-dialog-show", { + dialogName + }); + } + toolbarDidHideDialog(dialogName) { + this.thawSelection(); + this.editorElement.focus(); + return this.notifyEditorElement("toolbar-dialog-hide", { + dialogName + }); + } + + // Selection + + freezeSelection() { + if (!this.selectionFrozen) { + this.selectionManager.lock(); + this.composition.freezeSelection(); + this.selectionFrozen = true; + return this.render(); + } + } + thawSelection() { + if (this.selectionFrozen) { + this.composition.thawSelection(); + this.selectionManager.unlock(); + this.selectionFrozen = false; + return this.render(); + } + } + canInvokeAction(actionName) { + if (this.actionIsExternal(actionName)) { + return true; + } else { + var _this$actions$actionN; + return !!((_this$actions$actionN = this.actions[actionName]) !== null && _this$actions$actionN !== void 0 && (_this$actions$actionN = _this$actions$actionN.test) !== null && _this$actions$actionN !== void 0 && _this$actions$actionN.call(this)); + } + } + invokeAction(actionName, invokingElement) { + if (this.actionIsExternal(actionName)) { + return this.notifyEditorElement("action-invoke", { + actionName, + invokingElement + }); + } else { + var _this$actions$actionN2; + return (_this$actions$actionN2 = this.actions[actionName]) === null || _this$actions$actionN2 === void 0 || (_this$actions$actionN2 = _this$actions$actionN2.perform) === null || _this$actions$actionN2 === void 0 ? void 0 : _this$actions$actionN2.call(this); + } + } + actionIsExternal(actionName) { + return /^x-./.test(actionName); + } + getCurrentActions() { + const result = {}; + for (const actionName in this.actions) { + result[actionName] = this.canInvokeAction(actionName); + } + return result; + } + updateCurrentActions() { + const currentActions = this.getCurrentActions(); + if (!objectsAreEqual(currentActions, this.currentActions)) { + this.currentActions = currentActions; + this.toolbarController.updateActions(this.currentActions); + return this.notifyEditorElement("actions-change", { + actions: this.currentActions + }); + } + } + + // Editor filters + + runEditorFilters() { + let snapshot = this.composition.getSnapshot(); + Array.from(this.editor.filters).forEach(filter => { + const { + document, + selectedRange + } = snapshot; + snapshot = filter.call(this.editor, snapshot) || {}; + if (!snapshot.document) { + snapshot.document = document; + } + if (!snapshot.selectedRange) { + snapshot.selectedRange = selectedRange; + } + }); + if (!snapshotsAreEqual(snapshot, this.composition.getSnapshot())) { + return this.composition.loadSnapshot(snapshot); + } + } + + // Private + + updateInputElement() { + const element = this.compositionController.getSerializableElement(); + const value = serializeToContentType(element, "text/html"); + return this.editorElement.setFormValue(value); + } + notifyEditorElement(message, data) { + switch (message) { + case "document-change": + this.documentChangedSinceLastRender = true; + break; + case "render": + if (this.documentChangedSinceLastRender) { + this.documentChangedSinceLastRender = false; + this.notifyEditorElement("change"); + } + break; + case "change": + case "attachment-add": + case "attachment-edit": + case "attachment-remove": + this.updateInputElement(); + break; + } + return this.editorElement.notify(message, data); + } + removeAttachment(attachment) { + this.editor.recordUndoEntry("Delete Attachment"); + this.composition.removeAttachment(attachment); + return this.render(); + } + recordFormattingUndoEntry(attributeName) { + const blockConfig = getBlockConfig(attributeName); + const locationRange = this.selectionManager.getLocationRange(); + if (blockConfig || !rangeIsCollapsed(locationRange)) { + return this.editor.recordUndoEntry("Formatting", { + context: this.getUndoContext(), + consolidatable: true + }); + } + } + recordTypingUndoEntry() { + return this.editor.recordUndoEntry("Typing", { + context: this.getUndoContext(this.currentAttributes), + consolidatable: true + }); + } + getUndoContext() { + for (var _len = arguments.length, context = new Array(_len), _key = 0; _key < _len; _key++) { + context[_key] = arguments[_key]; + } + return [this.getLocationContext(), this.getTimeContext(), ...Array.from(context)]; + } + getLocationContext() { + const locationRange = this.selectionManager.getLocationRange(); + if (rangeIsCollapsed(locationRange)) { + return locationRange[0].index; + } else { + return locationRange; + } + } + getTimeContext() { + if (undo.interval > 0) { + return Math.floor(new Date().getTime() / undo.interval); + } else { + return 0; + } + } + isFocused() { + var _this$editorElement$o; + return this.editorElement === ((_this$editorElement$o = this.editorElement.ownerDocument) === null || _this$editorElement$o === void 0 ? void 0 : _this$editorElement$o.activeElement); + } + + // Detect "Cursor disappears sporadically" Firefox bug. + // - https://bugzilla.mozilla.org/show_bug.cgi?id=226301 + isFocusedInvisibly() { + return this.isFocused() && !this.getLocationRange(); + } + get actions() { + return this.constructor.actions; + } + } + _defineProperty(EditorController, "actions", { + undo: { + test() { + return this.editor.canUndo(); + }, + perform() { + return this.editor.undo(); + } + }, + redo: { + test() { + return this.editor.canRedo(); + }, + perform() { + return this.editor.redo(); + } + }, + link: { + test() { + return this.editor.canActivateAttribute("href"); + } + }, + increaseNestingLevel: { + test() { + return this.editor.canIncreaseNestingLevel(); + }, + perform() { + return this.editor.increaseNestingLevel() && this.render(); + } + }, + decreaseNestingLevel: { + test() { + return this.editor.canDecreaseNestingLevel(); + }, + perform() { + return this.editor.decreaseNestingLevel() && this.render(); + } + }, + attachFiles: { + test() { + return true; + }, + perform() { + return input.pickFiles(this.editor.insertFiles); + } + } + }); + EditorController.proxyMethod("getSelectionManager().setLocationRange"); + EditorController.proxyMethod("getSelectionManager().getLocationRange"); + + var controllers = /*#__PURE__*/Object.freeze({ + __proto__: null, + AttachmentEditorController: AttachmentEditorController, + CompositionController: CompositionController, + Controller: Controller, + EditorController: EditorController, + InputController: InputController, + Level0InputController: Level0InputController, + Level2InputController: Level2InputController, + ToolbarController: ToolbarController + }); + + var observers = /*#__PURE__*/Object.freeze({ + __proto__: null, + MutationObserver: MutationObserver, + SelectionChangeObserver: SelectionChangeObserver + }); + + var operations = /*#__PURE__*/Object.freeze({ + __proto__: null, + FileVerificationOperation: FileVerificationOperation, + ImagePreloadOperation: ImagePreloadOperation + }); + + installDefaultCSSForTagName("trix-toolbar", "%t {\n display: block;\n}\n\n%t {\n white-space: nowrap;\n}\n\n%t [data-trix-dialog] {\n display: none;\n}\n\n%t [data-trix-dialog][data-trix-active] {\n display: block;\n}\n\n%t [data-trix-dialog] [data-trix-validate]:invalid {\n background-color: #ffdddd;\n}"); + class TrixToolbarElement extends HTMLElement { + // Element lifecycle + + connectedCallback() { + if (this.innerHTML === "") { + this.innerHTML = toolbar.getDefaultHTML(); + } + } + } + + let id = 0; + + // Contenteditable support helpers + + const autofocus = function (element) { + if (!document.querySelector(":focus")) { + if (element.hasAttribute("autofocus") && document.querySelector("[autofocus]") === element) { + return element.focus(); + } + } + }; + const makeEditable = function (element) { + if (element.hasAttribute("contenteditable")) { + return; + } + element.setAttribute("contenteditable", ""); + return handleEventOnce("focus", { + onElement: element, + withCallback() { + return configureContentEditable(element); + } + }); + }; + const configureContentEditable = function (element) { + disableObjectResizing(element); + return setDefaultParagraphSeparator(element); + }; + const disableObjectResizing = function (element) { + var _document$queryComman, _document; + if ((_document$queryComman = (_document = document).queryCommandSupported) !== null && _document$queryComman !== void 0 && _document$queryComman.call(_document, "enableObjectResizing")) { + document.execCommand("enableObjectResizing", false, false); + return handleEvent("mscontrolselect", { + onElement: element, + preventDefault: true + }); + } + }; + const setDefaultParagraphSeparator = function (element) { + var _document$queryComman2, _document2; + if ((_document$queryComman2 = (_document2 = document).queryCommandSupported) !== null && _document$queryComman2 !== void 0 && _document$queryComman2.call(_document2, "DefaultParagraphSeparator")) { + const { + tagName + } = attributes.default; + if (["div", "p"].includes(tagName)) { + return document.execCommand("DefaultParagraphSeparator", false, tagName); + } + } + }; + + // Accessibility helpers + + const addAccessibilityRole = function (element) { + if (element.hasAttribute("role")) { + return; + } + return element.setAttribute("role", "textbox"); + }; + const ensureAriaLabel = function (element) { + if (element.hasAttribute("aria-label") || element.hasAttribute("aria-labelledby")) { + return; + } + const update = function () { + const texts = Array.from(element.labels).map(label => { + if (!label.contains(element)) return label.textContent; + }).filter(text => text); + const text = texts.join(" "); + if (text) { + return element.setAttribute("aria-label", text); + } else { + return element.removeAttribute("aria-label"); + } + }; + update(); + return handleEvent("focus", { + onElement: element, + withCallback: update + }); + }; + + // Style + + const cursorTargetStyles = function () { + if (browser$1.forcesObjectResizing) { + return { + display: "inline", + width: "auto" + }; + } else { + return { + display: "inline-block", + width: "1px" + }; + } + }(); + installDefaultCSSForTagName("trix-editor", "%t {\n display: block;\n}\n\n%t:empty::before {\n content: attr(placeholder);\n color: graytext;\n cursor: text;\n pointer-events: none;\n white-space: pre-line;\n}\n\n%t a[contenteditable=false] {\n cursor: text;\n}\n\n%t img {\n max-width: 100%;\n height: auto;\n}\n\n%t ".concat(attachmentSelector, " figcaption textarea {\n resize: none;\n}\n\n%t ").concat(attachmentSelector, " figcaption textarea.trix-autoresize-clone {\n position: absolute;\n left: -9999px;\n max-height: 0px;\n}\n\n%t ").concat(attachmentSelector, " figcaption[data-trix-placeholder]:empty::before {\n content: attr(data-trix-placeholder);\n color: graytext;\n}\n\n%t [data-trix-cursor-target] {\n display: ").concat(cursorTargetStyles.display, " !important;\n width: ").concat(cursorTargetStyles.width, " !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n}\n\n%t [data-trix-cursor-target=left] {\n vertical-align: top !important;\n margin-left: -1px !important;\n}\n\n%t [data-trix-cursor-target=right] {\n vertical-align: bottom !important;\n margin-right: -1px !important;\n}")); + var _internals = /*#__PURE__*/new WeakMap(); + var _validate = /*#__PURE__*/new WeakSet(); + class ElementInternalsDelegate { + constructor(element) { + _classPrivateMethodInitSpec(this, _validate); + _classPrivateFieldInitSpec(this, _internals, { + writable: true, + value: void 0 + }); + this.element = element; + _classPrivateFieldSet(this, _internals, element.attachInternals()); + } + connectedCallback() { + _classPrivateMethodGet(this, _validate, _validate2).call(this); + } + disconnectedCallback() {} + get labels() { + return _classPrivateFieldGet(this, _internals).labels; + } + get disabled() { + var _this$element$inputEl; + return (_this$element$inputEl = this.element.inputElement) === null || _this$element$inputEl === void 0 ? void 0 : _this$element$inputEl.disabled; + } + set disabled(value) { + this.element.toggleAttribute("disabled", value); + } + get required() { + return this.element.hasAttribute("required"); + } + set required(value) { + this.element.toggleAttribute("required", value); + _classPrivateMethodGet(this, _validate, _validate2).call(this); + } + get validity() { + return _classPrivateFieldGet(this, _internals).validity; + } + get validationMessage() { + return _classPrivateFieldGet(this, _internals).validationMessage; + } + get willValidate() { + return _classPrivateFieldGet(this, _internals).willValidate; + } + setFormValue(value) { + _classPrivateMethodGet(this, _validate, _validate2).call(this); + } + checkValidity() { + return _classPrivateFieldGet(this, _internals).checkValidity(); + } + reportValidity() { + return _classPrivateFieldGet(this, _internals).reportValidity(); + } + setCustomValidity(validationMessage) { + _classPrivateMethodGet(this, _validate, _validate2).call(this, validationMessage); + } + } + function _validate2() { + let customValidationMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + const { + required, + value + } = this.element; + const valueMissing = required && !value; + const customError = !!customValidationMessage; + const input = makeElement("input", { + required + }); + const validationMessage = customValidationMessage || input.validationMessage; + _classPrivateFieldGet(this, _internals).setValidity({ + valueMissing, + customError + }, validationMessage); + } + var _focusHandler = /*#__PURE__*/new WeakMap(); + var _resetBubbled = /*#__PURE__*/new WeakMap(); + var _clickBubbled = /*#__PURE__*/new WeakMap(); + class LegacyDelegate { + constructor(element) { + _classPrivateFieldInitSpec(this, _focusHandler, { + writable: true, + value: void 0 + }); + _classPrivateFieldInitSpec(this, _resetBubbled, { + writable: true, + value: event => { + if (event.defaultPrevented) return; + if (event.target !== this.element.form) return; + this.element.reset(); + } + }); + _classPrivateFieldInitSpec(this, _clickBubbled, { + writable: true, + value: event => { + if (event.defaultPrevented) return; + if (this.element.contains(event.target)) return; + const label = findClosestElementFromNode(event.target, { + matchingSelector: "label" + }); + if (!label) return; + if (!Array.from(this.labels).includes(label)) return; + this.element.focus(); + } + }); + this.element = element; + } + connectedCallback() { + _classPrivateFieldSet(this, _focusHandler, ensureAriaLabel(this.element)); + window.addEventListener("reset", _classPrivateFieldGet(this, _resetBubbled), false); + window.addEventListener("click", _classPrivateFieldGet(this, _clickBubbled), false); + } + disconnectedCallback() { + var _classPrivateFieldGet2; + (_classPrivateFieldGet2 = _classPrivateFieldGet(this, _focusHandler)) === null || _classPrivateFieldGet2 === void 0 || _classPrivateFieldGet2.destroy(); + window.removeEventListener("reset", _classPrivateFieldGet(this, _resetBubbled), false); + window.removeEventListener("click", _classPrivateFieldGet(this, _clickBubbled), false); + } + get labels() { + const labels = []; + if (this.element.id && this.element.ownerDocument) { + labels.push(...Array.from(this.element.ownerDocument.querySelectorAll("label[for='".concat(this.element.id, "']")) || [])); + } + const label = findClosestElementFromNode(this.element, { + matchingSelector: "label" + }); + if (label) { + if ([this.element, null].includes(label.control)) { + labels.push(label); + } + } + return labels; + } + get disabled() { + console.warn("This browser does not support the [disabled] attribute for trix-editor elements."); + return false; + } + set disabled(value) { + console.warn("This browser does not support the [disabled] attribute for trix-editor elements."); + } + get required() { + console.warn("This browser does not support the [required] attribute for trix-editor elements."); + return false; + } + set required(value) { + console.warn("This browser does not support the [required] attribute for trix-editor elements."); + } + get validity() { + console.warn("This browser does not support the validity property for trix-editor elements."); + return null; + } + get validationMessage() { + console.warn("This browser does not support the validationMessage property for trix-editor elements."); + return ""; + } + get willValidate() { + console.warn("This browser does not support the willValidate property for trix-editor elements."); + return false; + } + setFormValue(value) {} + checkValidity() { + console.warn("This browser does not support checkValidity() for trix-editor elements."); + return true; + } + reportValidity() { + console.warn("This browser does not support reportValidity() for trix-editor elements."); + return true; + } + setCustomValidity(validationMessage) { + console.warn("This browser does not support setCustomValidity(validationMessage) for trix-editor elements."); + } + } + var _delegate = /*#__PURE__*/new WeakMap(); + class TrixEditorElement extends HTMLElement { + constructor() { + super(); + _classPrivateFieldInitSpec(this, _delegate, { + writable: true, + value: void 0 + }); + _classPrivateFieldSet(this, _delegate, this.constructor.formAssociated ? new ElementInternalsDelegate(this) : new LegacyDelegate(this)); + } + + // Properties + + get trixId() { + if (this.hasAttribute("trix-id")) { + return this.getAttribute("trix-id"); + } else { + this.setAttribute("trix-id", ++id); + return this.trixId; + } + } + get labels() { + return _classPrivateFieldGet(this, _delegate).labels; + } + get disabled() { + return _classPrivateFieldGet(this, _delegate).disabled; + } + set disabled(value) { + _classPrivateFieldGet(this, _delegate).disabled = value; + } + get required() { + return _classPrivateFieldGet(this, _delegate).required; + } + set required(value) { + _classPrivateFieldGet(this, _delegate).required = value; + } + get validity() { + return _classPrivateFieldGet(this, _delegate).validity; + } + get validationMessage() { + return _classPrivateFieldGet(this, _delegate).validationMessage; + } + get willValidate() { + return _classPrivateFieldGet(this, _delegate).willValidate; + } + get type() { + return this.localName; + } + get toolbarElement() { + if (this.hasAttribute("toolbar")) { + var _this$ownerDocument; + return (_this$ownerDocument = this.ownerDocument) === null || _this$ownerDocument === void 0 ? void 0 : _this$ownerDocument.getElementById(this.getAttribute("toolbar")); + } else if (this.parentNode) { + const toolbarId = "trix-toolbar-".concat(this.trixId); + this.setAttribute("toolbar", toolbarId); + const element = makeElement("trix-toolbar", { + id: toolbarId + }); + this.parentNode.insertBefore(element, this); + return element; + } else { + return undefined; + } + } + get form() { + var _this$inputElement; + return (_this$inputElement = this.inputElement) === null || _this$inputElement === void 0 ? void 0 : _this$inputElement.form; + } + get inputElement() { + if (this.hasAttribute("input")) { + var _this$ownerDocument2; + return (_this$ownerDocument2 = this.ownerDocument) === null || _this$ownerDocument2 === void 0 ? void 0 : _this$ownerDocument2.getElementById(this.getAttribute("input")); + } else if (this.parentNode) { + const inputId = "trix-input-".concat(this.trixId); + this.setAttribute("input", inputId); + const element = makeElement("input", { + type: "hidden", + id: inputId + }); + this.parentNode.insertBefore(element, this.nextElementSibling); + return element; + } else { + return undefined; + } + } + get editor() { + var _this$editorControlle; + return (_this$editorControlle = this.editorController) === null || _this$editorControlle === void 0 ? void 0 : _this$editorControlle.editor; + } + get name() { + var _this$inputElement2; + return (_this$inputElement2 = this.inputElement) === null || _this$inputElement2 === void 0 ? void 0 : _this$inputElement2.name; + } + get value() { + var _this$inputElement3; + return (_this$inputElement3 = this.inputElement) === null || _this$inputElement3 === void 0 ? void 0 : _this$inputElement3.value; + } + set value(defaultValue) { + var _this$editor; + this.defaultValue = defaultValue; + (_this$editor = this.editor) === null || _this$editor === void 0 || _this$editor.loadHTML(this.defaultValue); + } + + // Controller delegate methods + + notify(message, data) { + if (this.editorController) { + return triggerEvent("trix-".concat(message), { + onElement: this, + attributes: data + }); + } + } + setFormValue(value) { + if (this.inputElement) { + this.inputElement.value = value; + _classPrivateFieldGet(this, _delegate).setFormValue(value); + } + } + + // Element lifecycle + + connectedCallback() { + if (!this.hasAttribute("data-trix-internal")) { + makeEditable(this); + addAccessibilityRole(this); + if (!this.editorController) { + triggerEvent("trix-before-initialize", { + onElement: this + }); + this.editorController = new EditorController({ + editorElement: this, + html: this.defaultValue = this.value + }); + requestAnimationFrame(() => triggerEvent("trix-initialize", { + onElement: this + })); + } + this.editorController.registerSelectionManager(); + _classPrivateFieldGet(this, _delegate).connectedCallback(); + autofocus(this); + } + } + disconnectedCallback() { + var _this$editorControlle2; + (_this$editorControlle2 = this.editorController) === null || _this$editorControlle2 === void 0 || _this$editorControlle2.unregisterSelectionManager(); + _classPrivateFieldGet(this, _delegate).disconnectedCallback(); + } + + // Form support + + checkValidity() { + return _classPrivateFieldGet(this, _delegate).checkValidity(); + } + reportValidity() { + return _classPrivateFieldGet(this, _delegate).reportValidity(); + } + setCustomValidity(validationMessage) { + _classPrivateFieldGet(this, _delegate).setCustomValidity(validationMessage); + } + formDisabledCallback(disabled) { + if (this.inputElement) { + this.inputElement.disabled = disabled; + } + this.toggleAttribute("contenteditable", !disabled); + } + formResetCallback() { + this.reset(); + } + reset() { + this.value = this.defaultValue; + } + } + _defineProperty(TrixEditorElement, "formAssociated", "ElementInternals" in window); + + var elements = /*#__PURE__*/Object.freeze({ + __proto__: null, + TrixEditorElement: TrixEditorElement, + TrixToolbarElement: TrixToolbarElement + }); + + var filters = /*#__PURE__*/Object.freeze({ + __proto__: null, + Filter: Filter, + attachmentGalleryFilter: attachmentGalleryFilter + }); + + const Trix = { + VERSION: version, + config, + core, + models, + views, + controllers, + observers, + operations, + elements, + filters + }; + + // Expose models under the Trix constant for compatibility with v1 + Object.assign(Trix, models); + function start() { + if (!customElements.get("trix-toolbar")) { + customElements.define("trix-toolbar", TrixToolbarElement); + } + if (!customElements.get("trix-editor")) { + customElements.define("trix-editor", TrixEditorElement); + } + } + window.Trix = Trix; + setTimeout(start, 0); + + return Trix; + +})); diff --git a/backend/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js.gz b/backend/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js.gz new file mode 100644 index 0000000..5784aa8 Binary files /dev/null and b/backend/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js.gz differ diff --git a/backend/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css b/backend/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css new file mode 100644 index 0000000..b07d206 --- /dev/null +++ b/backend/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css @@ -0,0 +1,412 @@ +trix-editor { + border: 1px solid #bbb; + border-radius: 3px; + margin: 0; + padding: 0.4em 0.6em; + min-height: 5em; + outline: none; } + +trix-toolbar * { + box-sizing: border-box; } + +trix-toolbar .trix-button-row { + display: flex; + flex-wrap: nowrap; + justify-content: space-between; + overflow-x: auto; } + +trix-toolbar .trix-button-group { + display: flex; + margin-bottom: 10px; + border: 1px solid #bbb; + border-top-color: #ccc; + border-bottom-color: #888; + border-radius: 3px; } + trix-toolbar .trix-button-group:not(:first-child) { + margin-left: 1.5vw; } + @media (max-width: 768px) { + trix-toolbar .trix-button-group:not(:first-child) { + margin-left: 0; } } + +trix-toolbar .trix-button-group-spacer { + flex-grow: 1; } + @media (max-width: 768px) { + trix-toolbar .trix-button-group-spacer { + display: none; } } + +trix-toolbar .trix-button { + position: relative; + float: left; + color: rgba(0, 0, 0, 0.6); + font-size: 0.75em; + font-weight: 600; + white-space: nowrap; + padding: 0 0.5em; + margin: 0; + outline: none; + border: none; + border-bottom: 1px solid #ddd; + border-radius: 0; + background: transparent; } + trix-toolbar .trix-button:not(:first-child) { + border-left: 1px solid #ccc; } + trix-toolbar .trix-button.trix-active { + background: #cbeefa; + color: black; } + trix-toolbar .trix-button:not(:disabled) { + cursor: pointer; } + trix-toolbar .trix-button:disabled { + color: rgba(0, 0, 0, 0.125); } + @media (max-width: 768px) { + trix-toolbar .trix-button { + letter-spacing: -0.01em; + padding: 0 0.3em; } } + +trix-toolbar .trix-button--icon { + font-size: inherit; + width: 2.6em; + height: 1.6em; + max-width: calc(0.8em + 4vw); + text-indent: -9999px; } + @media (max-width: 768px) { + trix-toolbar .trix-button--icon { + height: 2em; + max-width: calc(0.8em + 3.5vw); } } + trix-toolbar .trix-button--icon::before { + display: inline-block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + opacity: 0.6; + content: ""; + background-position: center; + background-repeat: no-repeat; + background-size: contain; } + @media (max-width: 768px) { + trix-toolbar .trix-button--icon::before { + right: 6%; + left: 6%; } } + trix-toolbar .trix-button--icon.trix-active::before { + opacity: 1; } + trix-toolbar .trix-button--icon:disabled::before { + opacity: 0.125; } + +trix-toolbar .trix-button--icon-attach::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M10.5%2018V7.5c0-2.25%203-2.25%203%200V18c0%204.125-6%204.125-6%200V7.5c0-6.375%209-6.375%209%200V18%22%20stroke%3D%22%23000%22%20stroke-width%3D%222%22%20stroke-miterlimit%3D%2210%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E"); + top: 8%; + bottom: 4%; } + +trix-toolbar .trix-button--icon-bold::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M6.522%2019.242a.5.5%200%200%201-.5-.5V5.35a.5.5%200%200%201%20.5-.5h5.783c1.347%200%202.46.345%203.24.982.783.64%201.216%201.562%201.216%202.683%200%201.13-.587%202.129-1.476%202.71a.35.35%200%200%200%20.049.613c1.259.56%202.101%201.742%202.101%203.22%200%201.282-.483%202.334-1.363%203.063-.876.726-2.132%201.12-3.66%201.12h-5.89ZM9.27%207.347v3.362h1.97c.766%200%201.347-.17%201.733-.464.38-.291.587-.716.587-1.27%200-.53-.183-.928-.513-1.198-.334-.273-.838-.43-1.505-.43H9.27Zm0%205.606v3.791h2.389c.832%200%201.448-.177%201.853-.497.399-.315.614-.786.614-1.423%200-.62-.22-1.077-.63-1.385-.418-.313-1.053-.486-1.905-.486H9.27Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-italic::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M9%205h6.5v2h-2.23l-2.31%2010H13v2H6v-2h2.461l2.306-10H9V5Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-link::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M18.948%205.258a4.337%204.337%200%200%200-6.108%200L11.217%206.87a.993.993%200%200%200%200%201.41c.392.39%201.027.39%201.418%200l1.623-1.613a2.323%202.323%200%200%201%203.271%200%202.29%202.29%200%200%201%200%203.251l-2.393%202.38a3.021%203.021%200%200%201-4.255%200l-.05-.049a1.007%201.007%200%200%200-1.418%200%20.993.993%200%200%200%200%201.41l.05.049a5.036%205.036%200%200%200%207.091%200l2.394-2.38a4.275%204.275%200%200%200%200-6.072Zm-13.683%2013.6a4.337%204.337%200%200%200%206.108%200l1.262-1.255a.993.993%200%200%200%200-1.41%201.007%201.007%200%200%200-1.418%200L9.954%2017.45a2.323%202.323%200%200%201-3.27%200%202.29%202.29%200%200%201%200-3.251l2.344-2.331a2.579%202.579%200%200%201%203.631%200c.392.39%201.027.39%201.419%200a.993.993%200%200%200%200-1.41%204.593%204.593%200%200%200-6.468%200l-2.345%202.33a4.275%204.275%200%200%200%200%206.072Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-strike::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M6%2014.986c.088%202.647%202.246%204.258%205.635%204.258%203.496%200%205.713-1.728%205.713-4.463%200-.275-.02-.536-.062-.781h-3.461c.398.293.573.654.573%201.123%200%201.035-1.074%201.787-2.646%201.787-1.563%200-2.773-.762-2.91-1.924H6ZM6.432%2010h3.763c-.632-.314-.914-.715-.914-1.273%200-1.045.977-1.739%202.432-1.739%201.475%200%202.52.723%202.617%201.914h2.764c-.05-2.548-2.11-4.238-5.39-4.238-3.145%200-5.392%201.719-5.392%204.316%200%20.363.04.703.12%201.02ZM4%2011a1%201%200%201%200%200%202h15a1%201%200%201%200%200-2H4Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-quote::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M4.581%208.471c.44-.5%201.056-.834%201.758-.995C8.074%207.17%209.201%207.822%2010%208.752c1.354%201.578%201.33%203.555.394%205.277-.941%201.731-2.788%203.163-4.988%203.56a.622.622%200%200%201-.653-.317c-.113-.205-.121-.49.16-.764.294-.286.567-.566.791-.835.222-.266.413-.54.524-.815.113-.28.156-.597.026-.908-.128-.303-.39-.524-.72-.69a3.02%203.02%200%200%201-1.674-2.7c0-.905.283-1.59.72-2.088Zm9.419%200c.44-.5%201.055-.834%201.758-.995%201.734-.306%202.862.346%203.66%201.276%201.355%201.578%201.33%203.555.395%205.277-.941%201.731-2.789%203.163-4.988%203.56a.622.622%200%200%201-.653-.317c-.113-.205-.122-.49.16-.764.294-.286.567-.566.791-.835.222-.266.412-.54.523-.815.114-.28.157-.597.026-.908-.127-.303-.39-.524-.72-.69a3.02%203.02%200%200%201-1.672-2.701c0-.905.283-1.59.72-2.088Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-heading-1::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21.5%207.5v-3h-12v3H14v13h3v-13h4.5ZM9%2013.5h3.5v-3h-10v3H6v7h3v-7Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-code::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3.293%2011.293a1%201%200%200%200%200%201.414l4%204a1%201%200%201%200%201.414-1.414L5.414%2012l3.293-3.293a1%201%200%200%200-1.414-1.414l-4%204Zm13.414%205.414%204-4a1%201%200%200%200%200-1.414l-4-4a1%201%200%201%200-1.414%201.414L18.586%2012l-3.293%203.293a1%201%200%200%200%201.414%201.414Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-bullet-list::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%207.5a1.5%201.5%200%201%200%200-3%201.5%201.5%200%200%200%200%203ZM8%206a1%201%200%200%201%201-1h11a1%201%200%201%201%200%202H9a1%201%200%200%201-1-1Zm1%205a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm0%206a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm-2.5-5a1.5%201.5%200%201%201-3%200%201.5%201.5%200%200%201%203%200ZM5%2019.5a1.5%201.5%200%201%200%200-3%201.5%201.5%200%200%200%200%203Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-number-list::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3%204h2v4H4V5H3V4Zm5%202a1%201%200%200%201%201-1h11a1%201%200%201%201%200%202H9a1%201%200%200%201-1-1Zm1%205a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm0%206a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm-3.5-7H6v1l-1.5%202H6v1H3v-1l1.667-2H3v-1h2.5ZM3%2017v-1h3v4H3v-1h2v-.5H4v-1h1V17H3Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-undo::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3%2014a1%201%200%200%200%201%201h6a1%201%200%201%200%200-2H6.257c2.247-2.764%205.151-3.668%207.579-3.264%202.589.432%204.739%202.356%205.174%205.405a1%201%200%200%200%201.98-.283c-.564-3.95-3.415-6.526-6.825-7.095C11.084%207.25%207.63%208.377%205%2011.39V8a1%201%200%200%200-2%200v6Zm2-1Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-redo::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21%2014a1%201%200%200%201-1%201h-6a1%201%200%201%201%200-2h3.743c-2.247-2.764-5.151-3.668-7.579-3.264-2.589.432-4.739%202.356-5.174%205.405a1%201%200%200%201-1.98-.283c.564-3.95%203.415-6.526%206.826-7.095%203.08-.513%206.534.614%209.164%203.626V8a1%201%200%201%201%202%200v6Zm-2-1Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-decrease-nesting-level::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%206a1%201%200%200%201%201-1h12a1%201%200%201%201%200%202H6a1%201%200%200%201-1-1Zm4%205a1%201%200%201%200%200%202h9a1%201%200%201%200%200-2H9Zm-3%206a1%201%200%201%200%200%202h12a1%201%200%201%200%200-2H6Zm-3.707-5.707a1%201%200%200%200%200%201.414l2%202a1%201%200%201%200%201.414-1.414L4.414%2012l1.293-1.293a1%201%200%200%200-1.414-1.414l-2%202Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-button--icon-increase-nesting-level::before { + background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%206a1%201%200%200%201%201-1h12a1%201%200%201%201%200%202H6a1%201%200%200%201-1-1Zm4%205a1%201%200%201%200%200%202h9a1%201%200%201%200%200-2H9Zm-3%206a1%201%200%201%200%200%202h12a1%201%200%201%200%200-2H6Zm-2.293-2.293%202-2a1%201%200%200%200%200-1.414l-2-2a1%201%200%201%200-1.414%201.414L3.586%2012l-1.293%201.293a1%201%200%201%200%201.414%201.414Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); } + +trix-toolbar .trix-dialogs { + position: relative; } + +trix-toolbar .trix-dialog { + position: absolute; + top: 0; + left: 0; + right: 0; + font-size: 0.75em; + padding: 15px 10px; + background: #fff; + box-shadow: 0 0.3em 1em #ccc; + border-top: 2px solid #888; + border-radius: 5px; + z-index: 5; } + +trix-toolbar .trix-input--dialog { + font-size: inherit; + font-weight: normal; + padding: 0.5em 0.8em; + margin: 0 10px 0 0; + border-radius: 3px; + border: 1px solid #bbb; + background-color: #fff; + box-shadow: none; + outline: none; + -webkit-appearance: none; + -moz-appearance: none; } + trix-toolbar .trix-input--dialog.validate:invalid { + box-shadow: #F00 0px 0px 1.5px 1px; } + +trix-toolbar .trix-button--dialog { + font-size: inherit; + padding: 0.5em; + border-bottom: none; } + +trix-toolbar .trix-dialog--link { + max-width: 600px; } + +trix-toolbar .trix-dialog__link-fields { + display: flex; + align-items: baseline; } + trix-toolbar .trix-dialog__link-fields .trix-input { + flex: 1; } + trix-toolbar .trix-dialog__link-fields .trix-button-group { + flex: 0 0 content; + margin: 0; } + +trix-editor [data-trix-mutable]:not(.attachment__caption-editor) { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +trix-editor [data-trix-mutable]::-moz-selection, +trix-editor [data-trix-cursor-target]::-moz-selection, trix-editor [data-trix-mutable] ::-moz-selection { + background: none; } + +trix-editor [data-trix-mutable]::selection, +trix-editor [data-trix-cursor-target]::selection, trix-editor [data-trix-mutable] ::selection { + background: none; } + +trix-editor .attachment__caption-editor:focus[data-trix-mutable]::-moz-selection { + background: highlight; } + +trix-editor .attachment__caption-editor:focus[data-trix-mutable]::selection { + background: highlight; } + +trix-editor [data-trix-mutable].attachment.attachment--file { + box-shadow: 0 0 0 2px highlight; + border-color: transparent; } + +trix-editor [data-trix-mutable].attachment img { + box-shadow: 0 0 0 2px highlight; } + +trix-editor .attachment { + position: relative; } + trix-editor .attachment:hover { + cursor: default; } + +trix-editor .attachment--preview .attachment__caption:hover { + cursor: text; } + +trix-editor .attachment__progress { + position: absolute; + z-index: 1; + height: 20px; + top: calc(50% - 10px); + left: 5%; + width: 90%; + opacity: 0.9; + transition: opacity 200ms ease-in; } + trix-editor .attachment__progress[value="100"] { + opacity: 0; } + +trix-editor .attachment__caption-editor { + display: inline-block; + width: 100%; + margin: 0; + padding: 0; + font-size: inherit; + font-family: inherit; + line-height: inherit; + color: inherit; + text-align: center; + vertical-align: top; + border: none; + outline: none; + -webkit-appearance: none; + -moz-appearance: none; } + +trix-editor .attachment__toolbar { + position: absolute; + z-index: 1; + top: -0.9em; + left: 0; + width: 100%; + text-align: center; } + +trix-editor .trix-button-group { + display: inline-flex; } + +trix-editor .trix-button { + position: relative; + float: left; + color: #666; + white-space: nowrap; + font-size: 80%; + padding: 0 0.8em; + margin: 0; + outline: none; + border: none; + border-radius: 0; + background: transparent; } + trix-editor .trix-button:not(:first-child) { + border-left: 1px solid #ccc; } + trix-editor .trix-button.trix-active { + background: #cbeefa; } + trix-editor .trix-button:not(:disabled) { + cursor: pointer; } + +trix-editor .trix-button--remove { + text-indent: -9999px; + display: inline-block; + padding: 0; + outline: none; + width: 1.8em; + height: 1.8em; + line-height: 1.8em; + border-radius: 50%; + background-color: #fff; + border: 2px solid highlight; + box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.25); } + trix-editor .trix-button--remove::before { + display: inline-block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + opacity: 0.7; + content: ""; + background-image: url("data:image/svg+xml,%3Csvg%20height%3D%2224%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M19%206.41%2017.59%205%2012%2010.59%206.41%205%205%206.41%2010.59%2012%205%2017.59%206.41%2019%2012%2013.41%2017.59%2019%2019%2017.59%2013.41%2012z%22%2F%3E%3Cpath%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E"); + background-position: center; + background-repeat: no-repeat; + background-size: 90%; } + trix-editor .trix-button--remove:hover { + border-color: #333; } + trix-editor .trix-button--remove:hover::before { + opacity: 1; } + +trix-editor .attachment__metadata-container { + position: relative; } + +trix-editor .attachment__metadata { + position: absolute; + left: 50%; + top: 2em; + transform: translate(-50%, 0); + max-width: 90%; + padding: 0.1em 0.6em; + font-size: 0.8em; + color: #fff; + background-color: rgba(0, 0, 0, 0.7); + border-radius: 3px; } + trix-editor .attachment__metadata .attachment__name { + display: inline-block; + max-width: 100%; + vertical-align: bottom; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + trix-editor .attachment__metadata .attachment__size { + margin-left: 0.2em; + white-space: nowrap; } + +.trix-content { + line-height: 1.5; + overflow-wrap: break-word; + word-break: break-word; } + .trix-content * { + box-sizing: border-box; + margin: 0; + padding: 0; } + .trix-content h1 { + font-size: 1.2em; + line-height: 1.2; } + .trix-content blockquote { + border: 0 solid #ccc; + border-left-width: 0.3em; + margin-left: 0.3em; + padding-left: 0.6em; } + .trix-content [dir=rtl] blockquote, + .trix-content blockquote[dir=rtl] { + border-width: 0; + border-right-width: 0.3em; + margin-right: 0.3em; + padding-right: 0.6em; } + .trix-content li { + margin-left: 1em; } + .trix-content [dir=rtl] li { + margin-right: 1em; } + .trix-content pre { + display: inline-block; + width: 100%; + vertical-align: top; + font-family: monospace; + font-size: 0.9em; + padding: 0.5em; + white-space: pre; + background-color: #eee; + overflow-x: auto; } + .trix-content img { + max-width: 100%; + height: auto; } + .trix-content .attachment { + display: inline-block; + position: relative; + max-width: 100%; } + .trix-content .attachment a { + color: inherit; + text-decoration: none; } + .trix-content .attachment a:hover, .trix-content .attachment a:visited:hover { + color: inherit; } + .trix-content .attachment__caption { + text-align: center; } + .trix-content .attachment__caption .attachment__name + .attachment__size::before { + content: ' \2022 '; } + .trix-content .attachment--preview { + width: 100%; + text-align: center; } + .trix-content .attachment--preview .attachment__caption { + color: #666; + font-size: 0.9em; + line-height: 1.2; } + .trix-content .attachment--file { + color: #333; + line-height: 1; + margin: 0 2px 2px 2px; + padding: 0.4em 1em; + border: 1px solid #bbb; + border-radius: 5px; } + .trix-content .attachment-gallery { + display: flex; + flex-wrap: wrap; + position: relative; } + .trix-content .attachment-gallery .attachment { + flex: 1 0 33%; + padding: 0 0.5em; + max-width: 33%; } + .trix-content .attachment-gallery.attachment-gallery--2 .attachment, .trix-content .attachment-gallery.attachment-gallery--4 .attachment { + flex-basis: 50%; + max-width: 50%; } diff --git a/backend/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css.gz b/backend/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css.gz new file mode 100644 index 0000000..4457d85 Binary files /dev/null and b/backend/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css.gz differ