update to node 18

This commit is contained in:
Joerg Reichert 2023-04-08 00:01:31 +02:00
parent 30fb4b37a0
commit 168149936c
57 changed files with 53882 additions and 31 deletions

View file

@ -1 +1 @@
3.2.2 3.0.2

View file

@ -1,14 +1,14 @@
FROM amd64/ruby:3.2.2-bullseye FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
RUN apt-get update && apt-get install -y ruby ruby-dev ruby-bundler \
build-essential zlib1g-dev libsqlite3-dev libxml2-dev libxslt1-dev pkg-config nodejs
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN gem install bundler RUN gem install bundler
# Add google package repository for google chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
RUN apt-get update && \
apt-get install -y build-essential zlib1g-dev libsqlite3-dev nodejs npm \
libxml2-dev libxslt1-dev pkg-config google-chrome-stable
ENV DOCKERIZE_VERSION v0.6.1 ENV DOCKERIZE_VERSION v0.6.1
RUN curl -sSLO https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ RUN curl -sSLO https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
&& tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
@ -19,7 +19,7 @@ RUN mkdir -p /app
WORKDIR /tmp WORKDIR /tmp
COPY Gemfile Gemfile COPY Gemfile Gemfile
#COPY Gemfile.lock Gemfile.lock COPY Gemfile.lock Gemfile.lock
RUN bundle config build.nokogiri --use-system-libraries RUN bundle config build.nokogiri --use-system-libraries
RUN bundle update RUN bundle update
RUN bundle install RUN bundle install
@ -27,7 +27,7 @@ RUN bundle install
ADD . /app ADD . /app
WORKDIR /app WORKDIR /app
RUN npm install -g yarn RUN npm install -g yarn sass
COPY ./docker-entrypoint.sh / COPY ./docker-entrypoint.sh /
RUN chmod +x docker-entrypoint.sh RUN chmod +x docker-entrypoint.sh

View file

@ -1,6 +1,6 @@
source 'https://rubygems.org' source 'https://rubygems.org'
ruby "3.2.2" ruby "3.0.2"
gem 'rails', '~> 7.0.4' gem 'rails', '~> 7.0.4'
gem 'rails-i18n' gem 'rails-i18n'
@ -25,9 +25,6 @@ gem 'cssbundling-rails'
gem "jsbundling-rails", "~> 1.1" gem "jsbundling-rails", "~> 1.1"
gem 'jquery-rails' gem 'jquery-rails'
gem 'bootstrap' gem 'bootstrap'
gem "sass", "~> 3.7"
gem 'sassc'
gem 'sassc-rails'
gem "importmap-rails", "~> 1.1" gem "importmap-rails", "~> 1.1"
gem 'slim-rails' gem 'slim-rails'
gem 'turbolinks' gem 'turbolinks'
@ -66,3 +63,7 @@ group :test do
gem 'shoulda-matchers', '~> 3.1' gem 'shoulda-matchers', '~> 3.1'
gem 'simplecov', require: false gem 'simplecov', require: false
end end
gem "dartsass", "~> 1.49"
gem "tzinfo-data", "~> 1.2023"

View file

@ -100,6 +100,7 @@ GEM
crass (1.0.6) crass (1.0.6)
cssbundling-rails (1.1.2) cssbundling-rails (1.1.2)
railties (>= 6.0.0) railties (>= 6.0.0)
dartsass (1.49.8)
database_cleaner (2.0.2) database_cleaner (2.0.2)
database_cleaner-active_record (>= 2, < 3) database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.1.0) database_cleaner-active_record (2.1.0)
@ -284,9 +285,6 @@ GEM
zeitwerk (~> 2.5) zeitwerk (~> 2.5)
rainbow (3.1.1) rainbow (3.1.1)
rake (13.0.6) rake (13.0.6)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
regexp_parser (2.7.0) regexp_parser (2.7.0)
rest-client (2.1.0) rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0) http-accept (>= 1.7.0, < 2.0)
@ -328,11 +326,6 @@ GEM
rubocop (>= 0.82.0) rubocop (>= 0.82.0)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sassc (2.4.0) sassc (2.4.0)
ffi (~> 1.9) ffi (~> 1.9)
sassc-rails (2.1.2) sassc-rails (2.1.2)
@ -381,6 +374,8 @@ GEM
turbolinks-source (5.2.0) turbolinks-source (5.2.0)
tzinfo (2.0.6) tzinfo (2.0.6)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
tzinfo-data (1.2023.3)
tzinfo (>= 1.0.0)
uglifier (4.2.0) uglifier (4.2.0)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
unf (0.1.4) unf (0.1.4)
@ -407,6 +402,7 @@ DEPENDENCIES
capybara capybara
coveralls coveralls
cssbundling-rails cssbundling-rails
dartsass (~> 1.49)
database_cleaner database_cleaner
elasticsearch (~> 7.10.1) elasticsearch (~> 7.10.1)
elasticsearch-dsl elasticsearch-dsl
@ -432,9 +428,6 @@ DEPENDENCIES
rspec-rails (~> 3.0) rspec-rails (~> 3.0)
rubocop rubocop
rubocop-faker rubocop-faker
sass (~> 3.7)
sassc
sassc-rails
shoulda-matchers (~> 3.1) shoulda-matchers (~> 3.1)
simplecov simplecov
slim-rails slim-rails
@ -442,11 +435,12 @@ DEPENDENCIES
spring-commands-rspec spring-commands-rspec
sqlite3 sqlite3
turbolinks turbolinks
tzinfo-data (~> 1.2023)
uglifier uglifier
validate_url validate_url
RUBY VERSION RUBY VERSION
ruby 3.2.2p53 ruby 3.0.2p107
BUNDLED WITH BUNDLED WITH
2.4.10 2.4.10

View file

@ -73,9 +73,10 @@ rake assets:clean
rake assets:clobber rake assets:clobber
rake tmp:clear rake tmp:clear
rails css:install:bootstrap npm install -g sass
sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --load-path=node_modules #rails css:install:bootstrap
rails javascript:install:esbuild #rails javascript:install:esbuild
rake assets:precompile
``` ```

View file

@ -0,0 +1 @@
// Entry point for your Sass build

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
export{afterMain,afterRead,afterWrite,auto,basePlacements,beforeMain,beforeRead,beforeWrite,bottom,clippingParents,end,left,main,modifierPhases,placements,popper,read,reference,right,start,top,variationPlacements,viewport,write}from"./enums.js";import"./modifiers/index.js";export{c as createPopperBase,p as popperGenerator}from"../_/1f65884f.js";export{createPopper}from"./popper.js";export{createPopper as createPopperLite}from"./popper-lite.js";export{default as detectOverflow}from"./utils/detectOverflow.js";export{default as applyStyles}from"./modifiers/applyStyles.js";export{default as arrow}from"./modifiers/arrow.js";export{default as computeStyles}from"./modifiers/computeStyles.js";export{default as eventListeners}from"./modifiers/eventListeners.js";export{default as flip}from"./modifiers/flip.js";export{default as hide}from"./modifiers/hide.js";export{default as offset}from"./modifiers/offset.js";export{default as popperOffsets}from"./modifiers/popperOffsets.js";export{default as preventOverflow}from"./modifiers/preventOverflow.js";import"./dom-utils/getCompositeRect.js";import"../_/bde78e08.js";import"./dom-utils/instanceOf.js";import"./dom-utils/getWindow.js";import"../_/69760856.js";import"../_/3601fa6b.js";import"./dom-utils/getNodeScroll.js";import"./dom-utils/getWindowScroll.js";import"./dom-utils/getHTMLElementScroll.js";import"./dom-utils/getNodeName.js";import"./dom-utils/getWindowScrollBarX.js";import"./dom-utils/getDocumentElement.js";import"./dom-utils/isScrollParent.js";import"./dom-utils/getComputedStyle.js";import"./dom-utils/getLayoutRect.js";import"./dom-utils/listScrollParents.js";import"./dom-utils/getScrollParent.js";import"./dom-utils/getParentNode.js";import"./dom-utils/getOffsetParent.js";import"../_/f0637918.js";import"../_/96c549a6.js";import"./dom-utils/getViewportRect.js";import"./dom-utils/getDocumentRect.js";import"../_/63b6cb9b.js";import"../_/c0068ee4.js";import"../_/9a91a998.js";import"./utils/getMainAxisFromPlacement.js";import"../_/c3ec9c52.js";import"../_/dc8ee67b.js";import"./utils/getOppositePlacement.js";import"./utils/getOppositeVariationPlacement.js";import"./utils/computeAutoPlacement.js";

View file

@ -0,0 +1,489 @@
(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: self.console,
WebSocket: self.WebSocket
};
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;
}
recordPing() {
this.pingedAt = now();
}
recordConnect() {
this.reconnectAttempts = 0;
this.recordPing();
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"
},
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 {
logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${protocols}`);
if (this.webSocket) {
this.uninstallEventHandlers();
}
this.webSocket = new adapters.WebSocket(this.consumer.url, protocols);
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");
}
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);
switch (type) {
case message_types.welcome:
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 this.monitor.recordPing();
case message_types.confirmation:
this.subscriptions.confirmSubscription(identifier);
return this.subscriptions.notify(identifier, "connected");
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);
}
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();
}
}
}
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
});
}));

View file

@ -0,0 +1,491 @@
var adapters = {
logger: self.console,
WebSocket: self.WebSocket
};
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;
}
recordPing() {
this.pingedAt = now();
}
recordConnect() {
this.reconnectAttempts = 0;
this.recordPing();
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"
},
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 {
logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${protocols}`);
if (this.webSocket) {
this.uninstallEventHandlers();
}
this.webSocket = new adapters.WebSocket(this.consumer.url, protocols);
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");
}
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);
switch (type) {
case message_types.welcome:
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 this.monitor.recordPing();
case message_types.confirmation:
this.subscriptions.confirmSubscription(identifier);
return this.subscriptions.notify(identifier, "connected");
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);
}
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();
}
}
}
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 };

View file

@ -0,0 +1,880 @@
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var activestorage = {exports: {}};
(function (module, exports) {
(function(global, factory) {
factory(exports) ;
})(commonjsGlobal, (function(exports) {
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) {
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");
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) {
this.id = ++id;
this.file = file;
this.url = url;
this.delegate = delegate;
}
create(callback) {
FileChecksum.create(this.file, ((error, checksum) => {
if (error) {
callback(error);
return;
}
const blob = new BlobRecord(this.file, checksum, this.url);
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 {target: target} = event;
if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
submitButtonsByForm.set(target.form, target);
}
}
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.start = start;
Object.defineProperty(exports, "__esModule", {
value: true
});
}));
}(activestorage, activestorage.exports));
class AttachmentUpload {
constructor(attachment, element) {
this.attachment = attachment;
this.element = element;
this.directUpload = new activestorage.exports.DirectUpload(attachment.file, this.directUploadUrl, this);
}
start() {
this.directUpload.create(this.directUploadDidComplete.bind(this));
}
directUploadWillStoreFileWithXHR(xhr) {
xhr.upload.addEventListener("progress", event => {
const progress = event.loaded / event.total * 100;
this.attachment.setUploadProgress(progress);
});
}
directUploadDidComplete(error, attributes) {
if (error) {
throw new Error(`Direct upload failed: ${error}`)
}
this.attachment.setAttributes({
sgid: attributes.attachable_sgid,
url: this.createBlobUrl(attributes.signed_id, attributes.filename)
});
}
createBlobUrl(signedId, filename) {
return this.blobUrlTemplate
.replace(":signed_id", signedId)
.replace(":filename", encodeURIComponent(filename))
}
get directUploadUrl() {
return this.element.dataset.directUploadUrl
}
get blobUrlTemplate() {
return this.element.dataset.blobUrlTemplate
}
}
addEventListener("trix-attachment-add", event => {
const { attachment, target } = event;
if (attachment.file) {
const upload = new AttachmentUpload(attachment, target);
upload.start();
}
});

View file

@ -0,0 +1,823 @@
(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) {
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");
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) {
this.id = ++id;
this.file = file;
this.url = url;
this.delegate = delegate;
}
create(callback) {
FileChecksum.create(this.file, ((error, checksum) => {
if (error) {
callback(error);
return;
}
const blob = new BlobRecord(this.file, checksum, this.url);
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 {target: target} = event;
if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
submitButtonsByForm.set(target.form, target);
}
}
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.start = start;
Object.defineProperty(exports, "__esModule", {
value: true
});
}));

View file

@ -0,0 +1,844 @@
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) {
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");
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) {
this.id = ++id;
this.file = file;
this.url = url;
this.delegate = delegate;
}
create(callback) {
FileChecksum.create(this.file, ((error, checksum) => {
if (error) {
callback(error);
return;
}
const blob = new BlobRecord(this.file, checksum, this.url);
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 {target: target} = event;
if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
submitButtonsByForm.set(target.form, target);
}
}
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, start };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
import t from"path";import e from"stylus-type-utils";var n={name:"foundation",version:"4.2.1-1",main:"stylus/foundation",repository:{type:"git",url:"https://github.com/blai/foundation.git"},devDependencies:{grunt:"~0.4.0","grunt-contrib-watch":"~0.1.0","grunt-contrib-qunit":"~0.1.1"},licenses:[{type:"MIT",url:"https://github.com/zurb/foundation/blob/master/LICENSE"}],dependencies:{stylus:"~0.32.1","stylus-type-utils":"~0.0.3"},keywords:["zurb","foundation","stylus","express"]};var s={};var r=t;var i=n;var a=new URL(import.meta.url.slice(0,import.meta.url.lastIndexOf("/"))).pathname;var o=[e];s=s=function plugin(){return function(t){t.include(a);o.forEach((function(e){t.use(e())}))}};s.theme=i.name;s.version=i.version;s.path=a;s.dependencies=o;s.assetPaths=[r.join(new URL(import.meta.url.slice(0,import.meta.url.lastIndexOf("/"))).pathname,"..","js")];var u=s;const p=s.theme,l=s.version,m=s.assetPaths;const c=s.path,d=s.dependencies;export default u;export{m as assetPaths,d as dependencies,c as path,p as theme,l as version};

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

View file

@ -0,0 +1,2 @@
import{e as r}from"../../_/c5b352d6.js";export{e as default}from"../../_/c5b352d6.js";import"../../_/e0803811.js";var a=r._makeLong;var v=r.basename;var o=r.delimiter;var s=r.dirname;var i=r.extname;var m=r.format;var t=r.isAbsolute;var n=r.join;var p=r.normalize;var l=r.parse;var d=r.posix;var b=r.relative;var f=r.resolve;var j=r.sep;var x=r.win32;export{a as _makeLong,v as basename,o as delimiter,s as dirname,i as extname,m as format,t as isAbsolute,n as join,p as normalize,l as parse,d as posix,b as relative,f as resolve,j as sep,x as win32};

View file

@ -0,0 +1,2 @@
var e={name:"stylus-type-utils",version:"0.0.3",description:"Stylus typography functions and type conversion",main:"lib/type-utils.js",scripts:{test:"mocha"},repository:{type:"git",url:"git://github.com/blakeembrey/stylus-type-utils.git"},keywords:["stylus","typeograhy","coercion","rem","em","px","pt","percent"],homepage:"https://github.com/blakeembrey/stylus-type-utils",author:"Blake Embrey",license:"MIT",readmeFilename:"Readme.md",peerDependencies:{stylus:"0.x"},devDependencies:{stylus:"~0.32.0"}};var t={};var s=t=function plugin(){return function(e){e.include(new URL(import.meta.url.slice(0,import.meta.url.lastIndexOf("/"))).pathname);e.import("type-utils")}};s.path=new URL(import.meta.url.slice(0,import.meta.url.lastIndexOf("/"))).pathname;s.version=e.version;var i=t;export default i;

View file

@ -0,0 +1,376 @@
/*
Trix 1.3.1
Copyright © 2020 Basecamp, LLC
http://trix-editor.org/*/
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-device-width: 768px) {
trix-toolbar .trix-button-group:not(:first-child) {
margin-left: 0; } }
trix-toolbar .trix-button-group-spacer {
flex-grow: 1; }
@media (max-device-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-device-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-device-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-device-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%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M16.5%206v11.5a4%204%200%201%201-8%200V5a2.5%202.5%200%200%201%205%200v10.5a1%201%200%201%201-2%200V6H10v9.5a2.5%202.5%200%200%200%205%200V5a4%204%200%201%200-8%200v12.5a5.5%205.5%200%200%200%2011%200V6h-1.5z%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%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M15.6%2011.8c1-.7%201.6-1.8%201.6-2.8a4%204%200%200%200-4-4H7v14h7c2.1%200%203.7-1.7%203.7-3.8%200-1.5-.8-2.8-2.1-3.4zM10%207.5h3a1.5%201.5%200%201%201%200%203h-3v-3zm3.5%209H10v-3h3.5a1.5%201.5%200%201%201%200%203z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-italic::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M10%205v3h2.2l-3.4%208H6v3h8v-3h-2.2l3.4-8H18V5h-8z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-link::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M9.88%2013.7a4.3%204.3%200%200%201%200-6.07l3.37-3.37a4.26%204.26%200%200%201%206.07%200%204.3%204.3%200%200%201%200%206.06l-1.96%201.72a.91.91%200%201%201-1.3-1.3l1.97-1.71a2.46%202.46%200%200%200-3.48-3.48l-3.38%203.37a2.46%202.46%200%200%200%200%203.48.91.91%200%201%201-1.3%201.3z%22%2F%3E%3Cpath%20d%3D%22M4.25%2019.46a4.3%204.3%200%200%201%200-6.07l1.93-1.9a.91.91%200%201%201%201.3%201.3l-1.93%201.9a2.46%202.46%200%200%200%203.48%203.48l3.37-3.38c.96-.96.96-2.52%200-3.48a.91.91%200%201%201%201.3-1.3%204.3%204.3%200%200%201%200%206.07l-3.38%203.38a4.26%204.26%200%200%201-6.07%200z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-strike::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12.73%2014l.28.14c.26.15.45.3.57.44.12.14.18.3.18.5%200%20.3-.15.56-.44.75-.3.2-.76.3-1.39.3A13.52%2013.52%200%200%201%207%2014.95v3.37a10.64%2010.64%200%200%200%204.84.88c1.26%200%202.35-.19%203.28-.56.93-.37%201.64-.9%202.14-1.57s.74-1.45.74-2.32c0-.26-.02-.51-.06-.75h-5.21zm-5.5-4c-.08-.34-.12-.7-.12-1.1%200-1.29.52-2.3%201.58-3.02%201.05-.72%202.5-1.08%204.34-1.08%201.62%200%203.28.34%204.97%201l-1.3%202.93c-1.47-.6-2.73-.9-3.8-.9-.55%200-.96.08-1.2.26-.26.17-.38.38-.38.64%200%20.27.16.52.48.74.17.12.53.3%201.05.53H7.23zM3%2013h18v-2H3v2z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-quote::before {
background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M6%2017h3l2-4V7H5v6h3zm8%200h3l2-4V7h-6v6h3z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-heading-1::before {
background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12%209v3H9v7H6v-7H3V9h9zM8%204h14v3h-6v12h-3V7H8V4z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-code::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M18.2%2012L15%2015.2l1.4%201.4L21%2012l-4.6-4.6L15%208.8l3.2%203.2zM5.8%2012L9%208.8%207.6%207.4%203%2012l4.6%204.6L9%2015.2%205.8%2012z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-bullet-list::before {
background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%204a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm0%206a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm0%206a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm4%203h14v-2H8v2zm0-6h14v-2H8v2zm0-8v2h14V5H8z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-number-list::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M2%2017h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1%203h1.8L2%2013.1v.9h3v-1H3.2L5%2010.9V10H2v1zm5-6v2h14V5H7zm0%2014h14v-2H7v2zm0-6h14v-2H7v2z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-undo::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12.5%208c-2.6%200-5%201-6.9%202.6L2%207v9h9l-3.6-3.6A8%208%200%200%201%2020%2016l2.4-.8a10.5%2010.5%200%200%200-10-7.2z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-redo::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M18.4%2010.6a10.5%2010.5%200%200%200-16.9%204.6L4%2016a8%208%200%200%201%2012.7-3.6L13%2016h9V7l-3.6%203.6z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-decrease-nesting-level::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M3%2019h19v-2H3v2zm7-6h12v-2H10v2zm-8.3-.3l2.8%202.9L6%2014.2%204%2012l2-2-1.4-1.5L1%2012l.7.7zM3%205v2h19V5H3z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-increase-nesting-level::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M3%2019h19v-2H3v2zm7-6h12v-2H10v2zm-6.9-1L1%2014.2l1.4%201.4L6%2012l-.7-.7-2.8-2.8L1%209.9%203.1%2012zM3%205v2h19V5H3z%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;
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]::-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 [data-trix-mutable].attachment__caption-editor:focus::-moz-selection {
background: highlight; }
trix-editor [data-trix-mutable].attachment__caption-editor:focus::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.4L17.6%205%2012%2010.6%206.4%205%205%206.4l5.6%205.6L5%2017.6%206.4%2019l5.6-5.6%205.6%205.6%201.4-1.4-5.6-5.6z%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; }
@charset "UTF-8";
.trix-content {
line-height: 1.5; }
.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: ' · '; }
.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%; }