@opentiny/fluent-editor
Version:
A rich text editor based on Quill 2.0, which extends rich modules and formats on the basis of Quill. It's powerful and out-of-the-box.
140 lines (139 loc) • 4.91 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const Quill = require("quill");
const is = require("../utils/is.cjs.js");
const Uploader = Quill.import("modules/uploader");
const Delta = Quill.import("delta");
class FileUploader extends Uploader {
constructor(quill, options) {
super(quill, options);
this.quill = quill;
this.options = this.resolveOptions(options);
}
resolveOptions(options = {}) {
return Object.assign({
mimetypes: ["*"],
maxSize: Number.POSITIVE_INFINITY,
multiple: true,
handler(range, files) {
return files.map((file) => URL.createObjectURL(file));
},
success() {
},
fail() {
}
}, options);
}
inferKind(file) {
const type = file.type || "";
if (type.startsWith("image/")) return "image";
if (type.startsWith("video/")) return "video";
return "file";
}
filterFromArray(types, kind) {
if (kind === "file") return types;
const prefix = `${kind}/`;
return types.filter((type) => {
if (type === "*") return true;
if (type.includes("/")) return type.startsWith(prefix);
return true;
});
}
getAccept(kind) {
var _a;
const mimetypes = this.options.mimetypes;
if (Array.isArray(mimetypes)) {
return this.filterFromArray(mimetypes, kind);
}
const map = mimetypes || {};
const fromKind = map[kind];
if (fromKind == null ? void 0 : fromKind.length) return fromKind;
if (((_a = map.file) == null ? void 0 : _a.length) && kind !== "file") return map.file;
return [];
}
getMaxSize(kind) {
const maxSize = this.options.maxSize;
if (typeof maxSize === "number") {
return maxSize;
}
const map = maxSize || {};
const fromKind = map[kind];
if (typeof fromKind === "number") return fromKind;
if (typeof map.file === "number" && kind !== "file") return map.file;
return Number.POSITIVE_INFINITY;
}
getMultiple(kind) {
const multiple = this.options.multiple;
if (typeof multiple === "boolean") {
return multiple;
}
const map = multiple || {};
const fromKind = map[kind];
if (typeof fromKind === "boolean") return fromKind;
if (typeof map.file === "boolean" && kind !== "file") return map.file;
return true;
}
validateFile(file, kind) {
const inferredKind = kind ?? this.inferKind(file);
const accept = this.getAccept(inferredKind);
const maxSize = this.getMaxSize(inferredKind);
const mimeOk = accept.some((type) => {
if (type.includes("/")) {
return (file.type || "text/plain").match(type.replaceAll("*", ".*"));
} else {
const ext = type.startsWith(".") ? type.toLowerCase() : `.${type.toLowerCase()}`;
return file.name.toLowerCase().endsWith(ext);
}
});
return mimeOk && file.size < maxSize;
}
async getFileUrls(files, range, kind) {
const uploads = files.filter((file) => this.validateFile(file, kind));
return this.options.handler.call(this, range, uploads);
}
async upload(range, files, kind) {
const uploads = [];
const fails = [];
for (const file of Array.from(files)) {
if (this.validateFile(file, kind)) {
uploads.push(file);
} else {
fails.push(file);
}
}
const result = await this.options.handler.call(this, range, uploads);
const updateDelta = result.reduce((delta, url, i) => {
if (is.isString(url)) {
const type = uploads[i].type;
if (type.startsWith("image/")) {
delta.insert({ image: url });
} else if (type.startsWith("video/")) {
delta.insert({ video: { src: url } });
} else {
delta.insert({ file: { size: uploads[i].size, title: uploads[i].name, src: url } });
}
} else {
delta.insert(" ");
}
return delta;
}, new Delta().retain(range.index).delete(range.length));
this.quill.updateContents(updateDelta, Quill.sources.USER);
this.quill.setSelection(range.index + result.length, Quill.sources.SILENT);
for (const file of fails) {
this.options.fail.call(this, file, range);
}
for (const [i, res] of result.entries()) {
if (is.isString(res)) {
this.options.success.call(this, files[i], { index: range.index + i, length: 0 });
} else {
this.options.fail.call(this, files[i], { index: range.index + i, length: 0 });
}
}
}
}
__publicField(FileUploader, "DEFAULTS", {});
exports.FileUploader = FileUploader;
//# sourceMappingURL=custom-uploader.cjs.js.map