@editorjs/image
Version:
Image Tool for Editor.js
1,104 lines (1,103 loc) • 46.2 kB
JavaScript
(function(){"use strict";try{if(typeof document<"u"){var o=document.createElement("style");o.appendChild(document.createTextNode('.image-tool{--bg-color: #cdd1e0;--front-color: #388ae5;--border-color: #e8e8eb}.image-tool__image{border-radius:3px;overflow:hidden;margin-bottom:10px;padding-bottom:0}.image-tool__image-picture{max-width:100%;vertical-align:bottom;display:block}.image-tool__image-preloader{width:50px;height:50px;border-radius:50%;background-size:cover;margin:auto;position:relative;background-color:var(--bg-color);background-position:center center}.image-tool__image-preloader:after{content:"";position:absolute;z-index:3;width:60px;height:60px;border-radius:50%;border:2px solid var(--bg-color);border-top-color:var(--front-color);left:50%;top:50%;margin-top:-30px;margin-left:-30px;animation:image-preloader-spin 2s infinite linear;box-sizing:border-box}.image-tool__caption{visibility:hidden;position:absolute;bottom:0;left:0;margin-bottom:10px}.image-tool__caption[contentEditable=true][data-placeholder]:before{position:absolute!important;content:attr(data-placeholder);color:#707684;font-weight:400;display:none}.image-tool__caption[contentEditable=true][data-placeholder]:empty:before{display:block}.image-tool__caption[contentEditable=true][data-placeholder]:empty:focus:before{display:none}.image-tool--empty .image-tool__image,.image-tool--empty .image-tool__image-preloader{display:none}.image-tool--empty .image-tool__caption,.image-tool--uploading .image-tool__caption{visibility:hidden!important}.image-tool .cdx-button{display:flex;align-items:center;justify-content:center}.image-tool .cdx-button svg{height:auto;margin:0 6px 0 0}.image-tool--filled .cdx-button,.image-tool--filled .image-tool__image-preloader{display:none}.image-tool--uploading .image-tool__image{min-height:200px;display:flex;border:1px solid var(--border-color);background-color:#fff}.image-tool--uploading .image-tool__image-picture,.image-tool--uploading .cdx-button{display:none}.image-tool--withBorder .image-tool__image{border:1px solid var(--border-color)}.image-tool--withBackground .image-tool__image{padding:15px;background:var(--bg-color)}.image-tool--withBackground .image-tool__image-picture{max-width:60%;margin:0 auto}.image-tool--stretched .image-tool__image-picture{width:100%}.image-tool--caption .image-tool__caption{visibility:visible}.image-tool--caption{padding-bottom:50px}@keyframes image-preloader-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}')),document.head.appendChild(o)}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
const R = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 19V19C9.13623 19 8.20435 19 7.46927 18.6955C6.48915 18.2895 5.71046 17.5108 5.30448 16.5307C5 15.7956 5 14.8638 5 13V12C5 9.19108 5 7.78661 5.67412 6.77772C5.96596 6.34096 6.34096 5.96596 6.77772 5.67412C7.78661 5 9.19108 5 12 5H13.5C14.8956 5 15.5933 5 16.1611 5.17224C17.4395 5.56004 18.44 6.56046 18.8278 7.83886C19 8.40666 19 9.10444 19 10.5V10.5"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M16 13V16M16 19V16M19 16H16M16 16H13"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6.5 17.5L17.5 6.5"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.9919 10.5H19.0015"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.9919 19H11.0015"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13L13 5"/></svg>', I = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.9919 9.5H19.0015"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.5 5H14.5096"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M14.625 5H15C17.2091 5 19 6.79086 19 9V9.375"/><path stroke="currentColor" stroke-width="2" d="M9.375 5L9 5C6.79086 5 5 6.79086 5 9V9.375"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.3725 5H9.38207"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 9.5H5.00957"/><path stroke="currentColor" stroke-width="2" d="M9.375 19H9C6.79086 19 5 17.2091 5 15V14.625"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.3725 19H9.38207"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 14.55H5.00957"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M16 13V16M16 19V16M19 16H16M16 16H13"/></svg>', L = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><rect width="14" height="14" x="5" y="5" stroke="currentColor" stroke-width="2" rx="4"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.13968 15.32L8.69058 11.5661C9.02934 11.2036 9.48873 11 9.96774 11C10.4467 11 10.9061 11.2036 11.2449 11.5661L15.3871 16M13.5806 14.0664L15.0132 12.533C15.3519 12.1705 15.8113 11.9668 16.2903 11.9668C16.7693 11.9668 17.2287 12.1705 17.5675 12.533L18.841 13.9634"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.7778 9.33331H13.7867"/></svg>', x = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9L20 12L17 15"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 12H20"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 9L4 12L7 15"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 12H10"/></svg>', B = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M8 9V7.2C8 7.08954 8.08954 7 8.2 7L12 7M16 9V7.2C16 7.08954 15.9105 7 15.8 7L12 7M12 7L12 17M12 17H10M12 17H14"/></svg>';
function S(C, i = null, a = {}) {
const s = document.createElement(C);
Array.isArray(i) ? s.classList.add(...i) : i !== null && s.classList.add(i);
for (const r in a)
a.hasOwnProperty(r) && (s[r] = a[r]);
return s;
}
var _ = /* @__PURE__ */ ((C) => (C.Empty = "empty", C.Uploading = "uploading", C.Filled = "filled", C))(_ || {});
class D {
/**
* @param ui - image tool Ui module
* @param ui.api - Editor.js API
* @param ui.config - user config
* @param ui.onSelectFile - callback for clicks on Select file button
* @param ui.readOnly - read-only mode flag
*/
constructor({ api: i, config: a, onSelectFile: s, readOnly: r }) {
this.api = i, this.config = a, this.onSelectFile = s, this.readOnly = r, this.nodes = {
wrapper: S("div", [this.CSS.baseClass, this.CSS.wrapper]),
imageContainer: S("div", [this.CSS.imageContainer]),
fileButton: this.createFileButton(),
imageEl: void 0,
imagePreloader: S("div", this.CSS.imagePreloader),
caption: S("div", [this.CSS.input, this.CSS.caption], {
contentEditable: !this.readOnly
})
}, this.nodes.caption.dataset.placeholder = this.config.captionPlaceholder, this.nodes.imageContainer.appendChild(this.nodes.imagePreloader), this.nodes.wrapper.appendChild(this.nodes.imageContainer), this.nodes.wrapper.appendChild(this.nodes.caption), this.nodes.wrapper.appendChild(this.nodes.fileButton);
}
/**
* Apply visual representation of activated tune
* @param tuneName - one of available tunes {@link Tunes.tunes}
* @param status - true for enable, false for disable
*/
applyTune(i, a) {
this.nodes.wrapper.classList.toggle(`${this.CSS.wrapper}--${i}`, a);
}
/**
* Renders tool UI
*/
render() {
return this.toggleStatus(
"empty"
/* Empty */
), this.nodes.wrapper;
}
/**
* Shows uploading preloader
* @param src - preview source
*/
showPreloader(i) {
this.nodes.imagePreloader.style.backgroundImage = `url(${i})`, this.toggleStatus(
"uploading"
/* Uploading */
);
}
/**
* Hide uploading preloader
*/
hidePreloader() {
this.nodes.imagePreloader.style.backgroundImage = "", this.toggleStatus(
"empty"
/* Empty */
);
}
/**
* Shows an image
* @param url - image source
*/
fillImage(i) {
const a = /\.mp4$/.test(i) ? "VIDEO" : "IMG", s = {
src: i
};
let r = "load";
a === "VIDEO" && (s.autoplay = !0, s.loop = !0, s.muted = !0, s.playsinline = !0, r = "loadeddata"), this.nodes.imageEl = S(a, this.CSS.imageEl, s), this.nodes.imageEl.addEventListener(r, () => {
this.toggleStatus(
"filled"
/* Filled */
), this.nodes.imagePreloader !== void 0 && (this.nodes.imagePreloader.style.backgroundImage = "");
}), this.nodes.imageContainer.appendChild(this.nodes.imageEl);
}
/**
* Shows caption input
* @param text - caption content text
*/
fillCaption(i) {
this.nodes.caption !== void 0 && (this.nodes.caption.innerHTML = i);
}
/**
* Changes UI status
* @param status - see {@link Ui.status} constants
*/
toggleStatus(i) {
for (const a in _)
if (Object.prototype.hasOwnProperty.call(_, a)) {
const s = _[a];
this.nodes.wrapper.classList.toggle(`${this.CSS.wrapper}--${s}`, s === i);
}
}
/**
* CSS classes
*/
get CSS() {
return {
baseClass: this.api.styles.block,
loading: this.api.styles.loader,
input: this.api.styles.input,
button: this.api.styles.button,
/**
* Tool's classes
*/
wrapper: "image-tool",
imageContainer: "image-tool__image",
imagePreloader: "image-tool__image-preloader",
imageEl: "image-tool__image-picture",
caption: "image-tool__caption"
};
}
/**
* Creates upload-file button
*/
createFileButton() {
const i = S("div", [this.CSS.button]);
return i.innerHTML = this.config.buttonContent ?? `${L} ${this.api.i18n.t("Select an Image")}`, i.addEventListener("click", () => {
this.onSelectFile();
}), i;
}
}
function U(C) {
return C && C.__esModule && Object.prototype.hasOwnProperty.call(C, "default") ? C.default : C;
}
var H = { exports: {} };
(function(C, i) {
(function(a, s) {
C.exports = s();
})(window, function() {
return function(a) {
var s = {};
function r(o) {
if (s[o]) return s[o].exports;
var e = s[o] = { i: o, l: !1, exports: {} };
return a[o].call(e.exports, e, e.exports, r), e.l = !0, e.exports;
}
return r.m = a, r.c = s, r.d = function(o, e, d) {
r.o(o, e) || Object.defineProperty(o, e, { enumerable: !0, get: d });
}, r.r = function(o) {
typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(o, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(o, "__esModule", { value: !0 });
}, r.t = function(o, e) {
if (1 & e && (o = r(o)), 8 & e || 4 & e && typeof o == "object" && o && o.__esModule) return o;
var d = /* @__PURE__ */ Object.create(null);
if (r.r(d), Object.defineProperty(d, "default", { enumerable: !0, value: o }), 2 & e && typeof o != "string") for (var v in o) r.d(d, v, (function(l) {
return o[l];
}).bind(null, v));
return d;
}, r.n = function(o) {
var e = o && o.__esModule ? function() {
return o.default;
} : function() {
return o;
};
return r.d(e, "a", e), e;
}, r.o = function(o, e) {
return Object.prototype.hasOwnProperty.call(o, e);
}, r.p = "", r(r.s = 3);
}([function(a, s) {
var r;
r = /* @__PURE__ */ function() {
return this;
}();
try {
r = r || new Function("return this")();
} catch {
typeof window == "object" && (r = window);
}
a.exports = r;
}, function(a, s, r) {
(function(o) {
var e = r(2), d = setTimeout;
function v() {
}
function l(n) {
if (!(this instanceof l)) throw new TypeError("Promises must be constructed via new");
if (typeof n != "function") throw new TypeError("not a function");
this._state = 0, this._handled = !1, this._value = void 0, this._deferreds = [], t(n, this);
}
function f(n, c) {
for (; n._state === 3; ) n = n._value;
n._state !== 0 ? (n._handled = !0, l._immediateFn(function() {
var u = n._state === 1 ? c.onFulfilled : c.onRejected;
if (u !== null) {
var g;
try {
g = u(n._value);
} catch (m) {
return void y(c.promise, m);
}
p(c.promise, g);
} else (n._state === 1 ? p : y)(c.promise, n._value);
})) : n._deferreds.push(c);
}
function p(n, c) {
try {
if (c === n) throw new TypeError("A promise cannot be resolved with itself.");
if (c && (typeof c == "object" || typeof c == "function")) {
var u = c.then;
if (c instanceof l) return n._state = 3, n._value = c, void w(n);
if (typeof u == "function") return void t((g = u, m = c, function() {
g.apply(m, arguments);
}), n);
}
n._state = 1, n._value = c, w(n);
} catch (h) {
y(n, h);
}
var g, m;
}
function y(n, c) {
n._state = 2, n._value = c, w(n);
}
function w(n) {
n._state === 2 && n._deferreds.length === 0 && l._immediateFn(function() {
n._handled || l._unhandledRejectionFn(n._value);
});
for (var c = 0, u = n._deferreds.length; c < u; c++) f(n, n._deferreds[c]);
n._deferreds = null;
}
function b(n, c, u) {
this.onFulfilled = typeof n == "function" ? n : null, this.onRejected = typeof c == "function" ? c : null, this.promise = u;
}
function t(n, c) {
var u = !1;
try {
n(function(g) {
u || (u = !0, p(c, g));
}, function(g) {
u || (u = !0, y(c, g));
});
} catch (g) {
if (u) return;
u = !0, y(c, g);
}
}
l.prototype.catch = function(n) {
return this.then(null, n);
}, l.prototype.then = function(n, c) {
var u = new this.constructor(v);
return f(this, new b(n, c, u)), u;
}, l.prototype.finally = e.a, l.all = function(n) {
return new l(function(c, u) {
if (!n || n.length === void 0) throw new TypeError("Promise.all accepts an array");
var g = Array.prototype.slice.call(n);
if (g.length === 0) return c([]);
var m = g.length;
function h(T, E) {
try {
if (E && (typeof E == "object" || typeof E == "function")) {
var M = E.then;
if (typeof M == "function") return void M.call(E, function(F) {
h(T, F);
}, u);
}
g[T] = E, --m == 0 && c(g);
} catch (F) {
u(F);
}
}
for (var k = 0; k < g.length; k++) h(k, g[k]);
});
}, l.resolve = function(n) {
return n && typeof n == "object" && n.constructor === l ? n : new l(function(c) {
c(n);
});
}, l.reject = function(n) {
return new l(function(c, u) {
u(n);
});
}, l.race = function(n) {
return new l(function(c, u) {
for (var g = 0, m = n.length; g < m; g++) n[g].then(c, u);
});
}, l._immediateFn = typeof o == "function" && function(n) {
o(n);
} || function(n) {
d(n, 0);
}, l._unhandledRejectionFn = function(n) {
typeof console < "u" && console && console.warn("Possible Unhandled Promise Rejection:", n);
}, s.a = l;
}).call(this, r(5).setImmediate);
}, function(a, s, r) {
s.a = function(o) {
var e = this.constructor;
return this.then(function(d) {
return e.resolve(o()).then(function() {
return d;
});
}, function(d) {
return e.resolve(o()).then(function() {
return e.reject(d);
});
});
};
}, function(a, s, r) {
function o(t) {
return (o = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(n) {
return typeof n;
} : function(n) {
return n && typeof Symbol == "function" && n.constructor === Symbol && n !== Symbol.prototype ? "symbol" : typeof n;
})(t);
}
r(4);
var e, d, v, l, f, p, y, w = r(8), b = (d = function(t) {
return new Promise(function(n, c) {
t = l(t), (t = f(t)).beforeSend && t.beforeSend();
var u = window.XMLHttpRequest ? new window.XMLHttpRequest() : new window.ActiveXObject("Microsoft.XMLHTTP");
u.open(t.method, t.url), u.setRequestHeader("X-Requested-With", "XMLHttpRequest"), Object.keys(t.headers).forEach(function(m) {
var h = t.headers[m];
u.setRequestHeader(m, h);
});
var g = t.ratio;
u.upload.addEventListener("progress", function(m) {
var h = Math.round(m.loaded / m.total * 100), k = Math.ceil(h * g / 100);
t.progress(Math.min(k, 100));
}, !1), u.addEventListener("progress", function(m) {
var h = Math.round(m.loaded / m.total * 100), k = Math.ceil(h * (100 - g) / 100) + g;
t.progress(Math.min(k, 100));
}, !1), u.onreadystatechange = function() {
if (u.readyState === 4) {
var m = u.response;
try {
m = JSON.parse(m);
} catch {
}
var h = w.parseHeaders(u.getAllResponseHeaders()), k = { body: m, code: u.status, headers: h };
y(u.status) ? n(k) : c(k);
}
}, u.send(t.data);
});
}, v = function(t) {
return t.method = "POST", d(t);
}, l = function() {
var t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
if (t.url && typeof t.url != "string") throw new Error("Url must be a string");
if (t.url = t.url || "", t.method && typeof t.method != "string") throw new Error("`method` must be a string or null");
if (t.method = t.method ? t.method.toUpperCase() : "GET", t.headers && o(t.headers) !== "object") throw new Error("`headers` must be an object or null");
if (t.headers = t.headers || {}, t.type && (typeof t.type != "string" || !Object.values(e).includes(t.type))) throw new Error("`type` must be taken from module's «contentType» library");
if (t.progress && typeof t.progress != "function") throw new Error("`progress` must be a function or null");
if (t.progress = t.progress || function(n) {
}, t.beforeSend = t.beforeSend || function(n) {
}, t.ratio && typeof t.ratio != "number") throw new Error("`ratio` must be a number");
if (t.ratio < 0 || t.ratio > 100) throw new Error("`ratio` must be in a 0-100 interval");
if (t.ratio = t.ratio || 90, t.accept && typeof t.accept != "string") throw new Error("`accept` must be a string with a list of allowed mime-types");
if (t.accept = t.accept || "*/*", t.multiple && typeof t.multiple != "boolean") throw new Error("`multiple` must be a true or false");
if (t.multiple = t.multiple || !1, t.fieldName && typeof t.fieldName != "string") throw new Error("`fieldName` must be a string");
return t.fieldName = t.fieldName || "files", t;
}, f = function(t) {
switch (t.method) {
case "GET":
var n = p(t.data, e.URLENCODED);
delete t.data, t.url = /\?/.test(t.url) ? t.url + "&" + n : t.url + "?" + n;
break;
case "POST":
case "PUT":
case "DELETE":
case "UPDATE":
var c = function() {
return (arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}).type || e.JSON;
}(t);
(w.isFormData(t.data) || w.isFormElement(t.data)) && (c = e.FORM), t.data = p(t.data, c), c !== b.contentType.FORM && (t.headers["content-type"] = c);
}
return t;
}, p = function() {
var t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
switch (arguments.length > 1 ? arguments[1] : void 0) {
case e.URLENCODED:
return w.urlEncode(t);
case e.JSON:
return w.jsonEncode(t);
case e.FORM:
return w.formEncode(t);
default:
return t;
}
}, y = function(t) {
return t >= 200 && t < 300;
}, { contentType: e = { URLENCODED: "application/x-www-form-urlencoded; charset=utf-8", FORM: "multipart/form-data", JSON: "application/json; charset=utf-8" }, request: d, get: function(t) {
return t.method = "GET", d(t);
}, post: v, transport: function(t) {
return t = l(t), w.selectFiles(t).then(function(n) {
for (var c = new FormData(), u = 0; u < n.length; u++) c.append(t.fieldName, n[u], n[u].name);
w.isObject(t.data) && Object.keys(t.data).forEach(function(m) {
var h = t.data[m];
c.append(m, h);
});
var g = t.beforeSend;
return t.beforeSend = function() {
return g(n);
}, t.data = c, v(t);
});
}, selectFiles: function(t) {
return delete (t = l(t)).beforeSend, w.selectFiles(t);
} });
a.exports = b;
}, function(a, s, r) {
r.r(s);
var o = r(1);
window.Promise = window.Promise || o.a;
}, function(a, s, r) {
(function(o) {
var e = o !== void 0 && o || typeof self < "u" && self || window, d = Function.prototype.apply;
function v(l, f) {
this._id = l, this._clearFn = f;
}
s.setTimeout = function() {
return new v(d.call(setTimeout, e, arguments), clearTimeout);
}, s.setInterval = function() {
return new v(d.call(setInterval, e, arguments), clearInterval);
}, s.clearTimeout = s.clearInterval = function(l) {
l && l.close();
}, v.prototype.unref = v.prototype.ref = function() {
}, v.prototype.close = function() {
this._clearFn.call(e, this._id);
}, s.enroll = function(l, f) {
clearTimeout(l._idleTimeoutId), l._idleTimeout = f;
}, s.unenroll = function(l) {
clearTimeout(l._idleTimeoutId), l._idleTimeout = -1;
}, s._unrefActive = s.active = function(l) {
clearTimeout(l._idleTimeoutId);
var f = l._idleTimeout;
f >= 0 && (l._idleTimeoutId = setTimeout(function() {
l._onTimeout && l._onTimeout();
}, f));
}, r(6), s.setImmediate = typeof self < "u" && self.setImmediate || o !== void 0 && o.setImmediate || this && this.setImmediate, s.clearImmediate = typeof self < "u" && self.clearImmediate || o !== void 0 && o.clearImmediate || this && this.clearImmediate;
}).call(this, r(0));
}, function(a, s, r) {
(function(o, e) {
(function(d, v) {
if (!d.setImmediate) {
var l, f, p, y, w, b = 1, t = {}, n = !1, c = d.document, u = Object.getPrototypeOf && Object.getPrototypeOf(d);
u = u && u.setTimeout ? u : d, {}.toString.call(d.process) === "[object process]" ? l = function(h) {
e.nextTick(function() {
m(h);
});
} : function() {
if (d.postMessage && !d.importScripts) {
var h = !0, k = d.onmessage;
return d.onmessage = function() {
h = !1;
}, d.postMessage("", "*"), d.onmessage = k, h;
}
}() ? (y = "setImmediate$" + Math.random() + "$", w = function(h) {
h.source === d && typeof h.data == "string" && h.data.indexOf(y) === 0 && m(+h.data.slice(y.length));
}, d.addEventListener ? d.addEventListener("message", w, !1) : d.attachEvent("onmessage", w), l = function(h) {
d.postMessage(y + h, "*");
}) : d.MessageChannel ? ((p = new MessageChannel()).port1.onmessage = function(h) {
m(h.data);
}, l = function(h) {
p.port2.postMessage(h);
}) : c && "onreadystatechange" in c.createElement("script") ? (f = c.documentElement, l = function(h) {
var k = c.createElement("script");
k.onreadystatechange = function() {
m(h), k.onreadystatechange = null, f.removeChild(k), k = null;
}, f.appendChild(k);
}) : l = function(h) {
setTimeout(m, 0, h);
}, u.setImmediate = function(h) {
typeof h != "function" && (h = new Function("" + h));
for (var k = new Array(arguments.length - 1), T = 0; T < k.length; T++) k[T] = arguments[T + 1];
var E = { callback: h, args: k };
return t[b] = E, l(b), b++;
}, u.clearImmediate = g;
}
function g(h) {
delete t[h];
}
function m(h) {
if (n) setTimeout(m, 0, h);
else {
var k = t[h];
if (k) {
n = !0;
try {
(function(T) {
var E = T.callback, M = T.args;
switch (M.length) {
case 0:
E();
break;
case 1:
E(M[0]);
break;
case 2:
E(M[0], M[1]);
break;
case 3:
E(M[0], M[1], M[2]);
break;
default:
E.apply(v, M);
}
})(k);
} finally {
g(h), n = !1;
}
}
}
}
})(typeof self > "u" ? o === void 0 ? this : o : self);
}).call(this, r(0), r(7));
}, function(a, s) {
var r, o, e = a.exports = {};
function d() {
throw new Error("setTimeout has not been defined");
}
function v() {
throw new Error("clearTimeout has not been defined");
}
function l(u) {
if (r === setTimeout) return setTimeout(u, 0);
if ((r === d || !r) && setTimeout) return r = setTimeout, setTimeout(u, 0);
try {
return r(u, 0);
} catch {
try {
return r.call(null, u, 0);
} catch {
return r.call(this, u, 0);
}
}
}
(function() {
try {
r = typeof setTimeout == "function" ? setTimeout : d;
} catch {
r = d;
}
try {
o = typeof clearTimeout == "function" ? clearTimeout : v;
} catch {
o = v;
}
})();
var f, p = [], y = !1, w = -1;
function b() {
y && f && (y = !1, f.length ? p = f.concat(p) : w = -1, p.length && t());
}
function t() {
if (!y) {
var u = l(b);
y = !0;
for (var g = p.length; g; ) {
for (f = p, p = []; ++w < g; ) f && f[w].run();
w = -1, g = p.length;
}
f = null, y = !1, function(m) {
if (o === clearTimeout) return clearTimeout(m);
if ((o === v || !o) && clearTimeout) return o = clearTimeout, clearTimeout(m);
try {
o(m);
} catch {
try {
return o.call(null, m);
} catch {
return o.call(this, m);
}
}
}(u);
}
}
function n(u, g) {
this.fun = u, this.array = g;
}
function c() {
}
e.nextTick = function(u) {
var g = new Array(arguments.length - 1);
if (arguments.length > 1) for (var m = 1; m < arguments.length; m++) g[m - 1] = arguments[m];
p.push(new n(u, g)), p.length !== 1 || y || l(t);
}, n.prototype.run = function() {
this.fun.apply(null, this.array);
}, e.title = "browser", e.browser = !0, e.env = {}, e.argv = [], e.version = "", e.versions = {}, e.on = c, e.addListener = c, e.once = c, e.off = c, e.removeListener = c, e.removeAllListeners = c, e.emit = c, e.prependListener = c, e.prependOnceListener = c, e.listeners = function(u) {
return [];
}, e.binding = function(u) {
throw new Error("process.binding is not supported");
}, e.cwd = function() {
return "/";
}, e.chdir = function(u) {
throw new Error("process.chdir is not supported");
}, e.umask = function() {
return 0;
};
}, function(a, s, r) {
function o(d, v) {
for (var l = 0; l < v.length; l++) {
var f = v[l];
f.enumerable = f.enumerable || !1, f.configurable = !0, "value" in f && (f.writable = !0), Object.defineProperty(d, f.key, f);
}
}
var e = r(9);
a.exports = function() {
function d() {
(function(p, y) {
if (!(p instanceof y)) throw new TypeError("Cannot call a class as a function");
})(this, d);
}
var v, l, f;
return v = d, f = [{ key: "urlEncode", value: function(p) {
return e(p);
} }, { key: "jsonEncode", value: function(p) {
return JSON.stringify(p);
} }, { key: "formEncode", value: function(p) {
if (this.isFormData(p)) return p;
if (this.isFormElement(p)) return new FormData(p);
if (this.isObject(p)) {
var y = new FormData();
return Object.keys(p).forEach(function(w) {
var b = p[w];
y.append(w, b);
}), y;
}
throw new Error("`data` must be an instance of Object, FormData or <FORM> HTMLElement");
} }, { key: "isObject", value: function(p) {
return Object.prototype.toString.call(p) === "[object Object]";
} }, { key: "isFormData", value: function(p) {
return p instanceof FormData;
} }, { key: "isFormElement", value: function(p) {
return p instanceof HTMLFormElement;
} }, { key: "selectFiles", value: function() {
var p = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
return new Promise(function(y, w) {
var b = document.createElement("INPUT");
b.type = "file", p.multiple && b.setAttribute("multiple", "multiple"), p.accept && b.setAttribute("accept", p.accept), b.style.display = "none", document.body.appendChild(b), b.addEventListener("change", function(t) {
var n = t.target.files;
y(n), document.body.removeChild(b);
}, !1), b.click();
});
} }, { key: "parseHeaders", value: function(p) {
var y = p.trim().split(/[\r\n]+/), w = {};
return y.forEach(function(b) {
var t = b.split(": "), n = t.shift(), c = t.join(": ");
n && (w[n] = c);
}), w;
} }], (l = null) && o(v.prototype, l), f && o(v, f), d;
}();
}, function(a, s) {
var r = function(e) {
return encodeURIComponent(e).replace(/[!'()*]/g, escape).replace(/%20/g, "+");
}, o = function(e, d, v, l) {
return d = d || null, v = v || "&", l = l || null, e ? function(f) {
for (var p = new Array(), y = 0; y < f.length; y++) f[y] && p.push(f[y]);
return p;
}(Object.keys(e).map(function(f) {
var p, y, w = f;
if (l && (w = l + "[" + w + "]"), typeof e[f] == "object" && e[f] !== null) p = o(e[f], null, v, w);
else {
d && (y = w, w = !isNaN(parseFloat(y)) && isFinite(y) ? d + Number(w) : w);
var b = e[f];
b = (b = (b = (b = b === !0 ? "1" : b) === !1 ? "0" : b) === 0 ? "0" : b) || "", p = r(w) + "=" + r(b);
}
return p;
})).join(v).replace(/[!'()*]/g, "") : "";
};
a.exports = o;
}]);
});
})(H);
var q = H.exports;
const j = /* @__PURE__ */ U(q);
function O(C) {
return C !== void 0 && typeof C.then == "function";
}
class A {
/**
* @param params - uploader module params
* @param params.config - image tool config
* @param params.onUpload - one callback for all uploading (file, url, d-n-d, pasting)
* @param params.onError - callback for uploading errors
*/
constructor({ config: i, onUpload: a, onError: s }) {
this.config = i, this.onUpload = a, this.onError = s;
}
/**
* Handle clicks on the upload file button
* Fires ajax.transport()
* @param onPreview - callback fired when preview is ready
*/
uploadSelectedFile({ onPreview: i }) {
const a = function(r) {
const o = new FileReader();
o.readAsDataURL(r), o.onload = (e) => {
i(e.target.result);
};
};
let s;
if (this.config.uploader && typeof this.config.uploader.uploadByFile == "function") {
const r = this.config.uploader.uploadByFile;
s = j.selectFiles({ accept: this.config.types ?? "image/*" }).then((o) => {
a(o[0]);
const e = r(o[0]);
return O(e) || console.warn("Custom uploader method uploadByFile should return a Promise"), e;
});
} else
s = j.transport({
url: this.config.endpoints.byFile,
data: this.config.additionalRequestData,
accept: this.config.types ?? "image/*",
headers: this.config.additionalRequestHeaders,
beforeSend: (r) => {
a(r[0]);
},
fieldName: this.config.field ?? "image"
}).then((r) => r.body);
s.then((r) => {
this.onUpload(r);
}).catch((r) => {
this.onError(r);
});
}
/**
* Handle clicks on the upload file button
* Fires ajax.post()
* @param url - image source url
*/
uploadByUrl(i) {
let a;
this.config.uploader && typeof this.config.uploader.uploadByUrl == "function" ? (a = this.config.uploader.uploadByUrl(i), O(a) || console.warn("Custom uploader method uploadByUrl should return a Promise")) : a = j.post({
url: this.config.endpoints.byUrl,
data: Object.assign({
url: i
}, this.config.additionalRequestData),
type: j.contentType.JSON,
headers: this.config.additionalRequestHeaders
}).then((s) => s.body), a.then((s) => {
this.onUpload(s);
}).catch((s) => {
this.onError(s);
});
}
/**
* Handle clicks on the upload file button
* Fires ajax.post()
* @param file - file pasted by drag-n-drop
* @param onPreview - file pasted by drag-n-drop
*/
uploadByFile(i, { onPreview: a }) {
const s = new FileReader();
s.readAsDataURL(i), s.onload = (o) => {
a(o.target.result);
};
let r;
if (this.config.uploader && typeof this.config.uploader.uploadByFile == "function")
r = this.config.uploader.uploadByFile(i), O(r) || console.warn("Custom uploader method uploadByFile should return a Promise");
else {
const o = new FormData();
o.append(this.config.field ?? "image", i), this.config.additionalRequestData && Object.keys(this.config.additionalRequestData).length && Object.entries(this.config.additionalRequestData).forEach(([e, d]) => {
o.append(e, d);
}), r = j.post({
url: this.config.endpoints.byFile,
data: o,
type: j.contentType.JSON,
headers: this.config.additionalRequestHeaders
}).then((e) => e.body);
}
r.then((o) => {
this.onUpload(o);
}).catch((o) => {
this.onError(o);
});
}
}
/**
* Image Tool for the Editor.js
* @author CodeX <team@codex.so>
* @license MIT
* @see {@link https://github.com/editor-js/image}
*
* To developers.
* To simplify Tool structure, we split it to 4 parts:
* 1) index.ts — main Tool's interface, public API and methods for working with data
* 2) uploader.ts — module that has methods for sending files via AJAX: from device, by URL or File pasting
* 3) ui.ts — module for UI manipulations: render, showing preloader, etc
*
* For debug purposes there is a testing server
* that can save uploaded files and return a Response {@link UploadResponseFormat}
*
* $ node dev/server.js
*
* It will expose 8008 port, so you can pass http://localhost:8008 with the Tools config:
*
* image: {
* class: ImageTool,
* config: {
* endpoints: {
* byFile: 'http://localhost:8008/uploadFile',
* byUrl: 'http://localhost:8008/fetchUrl',
* }
* },
* },
*/
class P {
/**
* @param tool - tool properties got from editor.js
* @param tool.data - previously saved data
* @param tool.config - user config for Tool
* @param tool.api - Editor.js API
* @param tool.readOnly - read-only mode flag
* @param tool.block - current Block API
*/
constructor({ data: i, config: a, api: s, readOnly: r, block: o }) {
this.isCaptionEnabled = null, this.api = s, this.block = o, this.config = {
endpoints: a.endpoints,
additionalRequestData: a.additionalRequestData,
additionalRequestHeaders: a.additionalRequestHeaders,
field: a.field,
types: a.types,
captionPlaceholder: this.api.i18n.t(a.captionPlaceholder ?? "Caption"),
buttonContent: a.buttonContent,
uploader: a.uploader,
actions: a.actions,
features: a.features || {}
}, this.uploader = new A({
config: this.config,
onUpload: (e) => this.onUpload(e),
onError: (e) => this.uploadingFailed(e)
}), this.ui = new D({
api: s,
config: this.config,
onSelectFile: () => {
this.uploader.uploadSelectedFile({
onPreview: (e) => {
this.ui.showPreloader(e);
}
});
},
readOnly: r
}), this._data = {
caption: "",
withBorder: !1,
withBackground: !1,
stretched: !1,
file: {
url: ""
}
}, this.data = i;
}
/**
* Notify core that read-only mode is supported
*/
static get isReadOnlySupported() {
return !0;
}
/**
* Get Tool toolbox settings
* icon - Tool icon's SVG
* title - title to show in toolbox
*/
static get toolbox() {
return {
icon: L,
title: "Image"
};
}
/**
* Available image tools
*/
static get tunes() {
return [
{
name: "withBorder",
icon: I,
title: "With border",
toggle: !0
},
{
name: "stretched",
icon: x,
title: "Stretch image",
toggle: !0
},
{
name: "withBackground",
icon: R,
title: "With background",
toggle: !0
}
];
}
/**
* Renders Block content
*/
render() {
var i, a, s;
return (((i = this.config.features) == null ? void 0 : i.caption) === !0 || ((a = this.config.features) == null ? void 0 : a.caption) === void 0 || ((s = this.config.features) == null ? void 0 : s.caption) === "optional" && this.data.caption) && (this.isCaptionEnabled = !0, this.ui.applyTune("caption", !0)), this.ui.render();
}
/**
* Validate data: check if Image exists
* @param savedData — data received after saving
* @returns false if saved data is not correct, otherwise true
*/
validate(i) {
return !!i.file.url;
}
/**
* Return Block data
*/
save() {
const i = this.ui.nodes.caption;
return this._data.caption = i.innerHTML, this.data;
}
/**
* Returns configuration for block tunes: add background, add border, stretch image
* @returns TunesMenuConfig
*/
renderSettings() {
var o;
const i = P.tunes.concat(this.config.actions || []), a = {
border: "withBorder",
background: "withBackground",
stretch: "stretched",
caption: "caption"
};
((o = this.config.features) == null ? void 0 : o.caption) === "optional" && i.push({
name: "caption",
icon: B,
title: "With caption",
toggle: !0
});
const s = i.filter((e) => {
var v, l;
const d = Object.keys(a).find((f) => a[f] === e.name);
return d === "caption" ? ((v = this.config.features) == null ? void 0 : v.caption) !== !1 : d == null || ((l = this.config.features) == null ? void 0 : l[d]) !== !1;
}), r = (e) => {
let d = this.data[e.name];
return e.name === "caption" && (d = this.isCaptionEnabled ?? d), d;
};
return s.map((e) => ({
icon: e.icon,
label: this.api.i18n.t(e.title),
name: e.name,
toggle: e.toggle,
isActive: r(e),
onActivate: () => {
if (typeof e.action == "function") {
e.action(e.name);
return;
}
let d = !r(e);
e.name === "caption" && (this.isCaptionEnabled = !(this.isCaptionEnabled ?? !1), d = this.isCaptionEnabled), this.tuneToggled(e.name, d);
}
}));
}
/**
* Fires after clicks on the Toolbox Image Icon
* Initiates click on the Select File button
*/
appendCallback() {
this.ui.nodes.fileButton.click();
}
/**
* Specify paste substitutes
* @see {@link https://github.com/codex-team/editor.js/blob/master/docs/tools.md#paste-handling}
*/
static get pasteConfig() {
return {
/**
* Paste HTML into Editor
*/
tags: [
{
img: { src: !0 }
}
],
/**
* Paste URL of image into the Editor
*/
patterns: {
image: /https?:\/\/\S+\.(gif|jpe?g|tiff|png|svg|webp)(\?[a-z0-9=]*)?$/i
},
/**
* Drag n drop file from into the Editor
*/
files: {
mimeTypes: ["image/*"]
}
};
}
/**
* Specify paste handlers
* @see {@link https://github.com/codex-team/editor.js/blob/master/docs/tools.md#paste-handling}
* @param event - editor.js custom paste event
* {@link https://github.com/codex-team/editor.js/blob/master/types/tools/paste-events.d.ts}
*/
async onPaste(i) {
switch (i.type) {
case "tag": {
const a = i.detail.data;
if (/^blob:/.test(a.src)) {
const r = await (await fetch(a.src)).blob();
this.uploadFile(r);
break;
}
this.uploadUrl(a.src);
break;
}
case "pattern": {
const a = i.detail.data;
this.uploadUrl(a);
break;
}
case "file": {
const a = i.detail.file;
this.uploadFile(a);
break;
}
}
}
/**
* Private methods
* ̿̿ ̿̿ ̿̿ ̿'̿'\̵͇̿̿\з= ( ▀ ͜͞ʖ▀) =ε/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿ ̿̿
*/
/**
* Stores all Tool's data
* @param data - data in Image Tool format
*/
set data(i) {
var a;
this.image = i.file, this._data.caption = i.caption || "", this.ui.fillCaption(this._data.caption), P.tunes.forEach(({ name: s }) => {
const r = typeof i[s] < "u" ? i[s] === !0 || i[s] === "true" : !1;
this.setTune(s, r);
}), i.caption ? this.setTune("caption", !0) : ((a = this.config.features) == null ? void 0 : a.caption) === !0 && this.setTune("caption", !0);
}
/**
* Return Tool data
*/
get data() {
return this._data;
}
/**
* Set new image file
* @param file - uploaded file data
*/
set image(i) {
this._data.file = i || { url: "" }, i && i.url && this.ui.fillImage(i.url);
}
/**
* File uploading callback
* @param response - uploading server response
*/
onUpload(i) {
i.success && i.file ? this.image = i.file : this.uploadingFailed("incorrect response: " + JSON.stringify(i));
}
/**
* Handle uploader errors
* @param errorText - uploading error info
*/
uploadingFailed(i) {
console.log("Image Tool: uploading failed because of", i), this.api.notifier.show({
message: this.api.i18n.t("Couldn’t upload image. Please try another."),
style: "error"
}), this.ui.hidePreloader();
}
/**
* Callback fired when Block Tune is activated
* @param tuneName - tune that has been clicked
* @param state - new state
*/
tuneToggled(i, a) {
i === "caption" ? (this.ui.applyTune(i, a), a == !1 && (this._data.caption = "", this.ui.fillCaption(""))) : this.setTune(i, a);
}
/**
* Set one tune
* @param tuneName - {@link Tunes.tunes}
* @param value - tune state
*/
setTune(i, a) {
this._data[i] = a, this.ui.applyTune(i, a), i === "stretched" && Promise.resolve().then(() => {
this.block.stretched = a;
}).catch((s) => {
console.error(s);
});
}
/**
* Show preloader and upload image file
* @param file - file that is currently uploading (from paste)
*/
uploadFile(i) {
this.uploader.uploadByFile(i, {
onPreview: (a) => {
this.ui.showPreloader(a);
}
});
}
/**
* Show preloader and upload image by target url
* @param url - url pasted
*/
uploadUrl(i) {
this.ui.showPreloader(i), this.uploader.uploadByUrl(i);
}
}
export {
P as default
};