@opentiny/fluent-editor 4.0.0-alpha.0 → 4.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/config/editor.config.es.js +0 -7
- package/es/config/editor.config.es.js.map +1 -1
- package/es/config/i18n/en-us.es.js +0 -13
- package/es/config/i18n/en-us.es.js.map +1 -1
- package/es/config/i18n/zh-cn.es.js +0 -13
- package/es/config/i18n/zh-cn.es.js.map +1 -1
- package/es/config/index.es.js +6 -11
- package/es/config/index.es.js.map +1 -1
- package/es/core/fluent-editor.es.js +3 -4
- package/es/core/fluent-editor.es.js.map +1 -1
- package/es/fluent-editor.es.js +12 -3
- package/es/fluent-editor.es.js.map +1 -1
- package/es/formats/video.es.js +2 -2
- package/es/formats/video.es.js.map +1 -1
- package/es/index.es.js +3 -2
- package/es/index.es.js.map +1 -1
- package/es/modules/custom-clipboard.es.js +3 -5
- package/es/modules/custom-clipboard.es.js.map +1 -1
- package/es/modules/custom-image/BlotFormatter.es.js +1 -2
- package/es/modules/custom-image/BlotFormatter.es.js.map +1 -1
- package/es/modules/custom-image/image.es.js +4 -16
- package/es/modules/custom-image/image.es.js.map +1 -1
- package/es/modules/custom-uploader.es.js +60 -193
- package/es/modules/custom-uploader.es.js.map +1 -1
- package/es/modules/file/formats/file.es.js +12 -14
- package/es/modules/file/formats/file.es.js.map +1 -1
- package/es/modules/file/index.es.js +6 -7
- package/es/modules/file/index.es.js.map +1 -1
- package/es/modules/i18n.es.js +28 -9
- package/es/modules/i18n.es.js.map +1 -1
- package/es/modules/link/modules/tooltip.es.js +3 -2
- package/es/modules/link/modules/tooltip.es.js.map +1 -1
- package/es/modules/shortcut-key/index.es.js +17 -1
- package/es/modules/shortcut-key/index.es.js.map +1 -1
- package/es/modules/table-up/index.es.js +5 -2
- package/es/modules/table-up/index.es.js.map +1 -1
- package/es/modules/toolbar/toolbar-tip.es.js +6 -1
- package/es/modules/toolbar/toolbar-tip.es.js.map +1 -1
- package/es/themes/snow.es.js +14 -5
- package/es/themes/snow.es.js.map +1 -1
- package/es/ui/icons.es.js.map +1 -1
- package/es/utils/is.es.js +4 -0
- package/es/utils/is.es.js.map +1 -1
- package/lib/config/editor.config.cjs.js +0 -7
- package/lib/config/editor.config.cjs.js.map +1 -1
- package/lib/config/i18n/en-us.cjs.js +0 -13
- package/lib/config/i18n/en-us.cjs.js.map +1 -1
- package/lib/config/i18n/zh-cn.cjs.js +0 -13
- package/lib/config/i18n/zh-cn.cjs.js.map +1 -1
- package/lib/config/index.cjs.js +5 -10
- package/lib/config/index.cjs.js.map +1 -1
- package/lib/core/fluent-editor.cjs.js +2 -3
- package/lib/core/fluent-editor.cjs.js.map +1 -1
- package/lib/fluent-editor.cjs.js +11 -2
- package/lib/fluent-editor.cjs.js.map +1 -1
- package/lib/formats/video.cjs.js +2 -2
- package/lib/formats/video.cjs.js.map +1 -1
- package/lib/index.cjs.js +2 -1
- package/lib/index.cjs.js.map +1 -1
- package/lib/modules/custom-clipboard.cjs.js +2 -4
- package/lib/modules/custom-clipboard.cjs.js.map +1 -1
- package/lib/modules/custom-image/BlotFormatter.cjs.js +0 -1
- package/lib/modules/custom-image/BlotFormatter.cjs.js.map +1 -1
- package/lib/modules/custom-image/image.cjs.js +4 -16
- package/lib/modules/custom-image/image.cjs.js.map +1 -1
- package/lib/modules/custom-uploader.cjs.js +61 -194
- package/lib/modules/custom-uploader.cjs.js.map +1 -1
- package/lib/modules/file/formats/file.cjs.js +12 -14
- package/lib/modules/file/formats/file.cjs.js.map +1 -1
- package/lib/modules/file/index.cjs.js +6 -7
- package/lib/modules/file/index.cjs.js.map +1 -1
- package/lib/modules/i18n.cjs.js +27 -8
- package/lib/modules/i18n.cjs.js.map +1 -1
- package/lib/modules/link/modules/tooltip.cjs.js +2 -1
- package/lib/modules/link/modules/tooltip.cjs.js.map +1 -1
- package/lib/modules/shortcut-key/index.cjs.js +16 -0
- package/lib/modules/shortcut-key/index.cjs.js.map +1 -1
- package/lib/modules/table-up/index.cjs.js +5 -2
- package/lib/modules/table-up/index.cjs.js.map +1 -1
- package/lib/modules/toolbar/toolbar-tip.cjs.js +6 -1
- package/lib/modules/toolbar/toolbar-tip.cjs.js.map +1 -1
- package/lib/themes/snow.cjs.js +14 -5
- package/lib/themes/snow.cjs.js.map +1 -1
- package/lib/ui/icons.cjs.js.map +1 -1
- package/lib/utils/is.cjs.js +4 -0
- package/lib/utils/is.cjs.js.map +1 -1
- package/package.json +2 -2
- package/style.css +6 -19
- package/types/config/editor.config.d.ts +0 -274
- package/types/config/i18n/en-us.d.ts +0 -13
- package/types/config/i18n/zh-cn.d.ts +0 -13
- package/types/config/index.d.ts +1 -1
- package/types/config/types/editor-config.interface.d.ts +0 -19
- package/types/config/types/editor-modules.interface.d.ts +2 -0
- package/types/core/fluent-editor.d.ts +3 -1
- package/types/index.d.ts +2 -1
- package/types/modules/counter.d.ts +1 -1
- package/types/modules/custom-clipboard.d.ts +1 -1
- package/types/modules/custom-image/image.d.ts +8 -11
- package/types/modules/file/formats/file.d.ts +12 -8
- package/types/modules/file/index.d.ts +5 -5
- package/types/modules/i18n.d.ts +3 -3
- package/types/modules/shortcut-key/index.d.ts +4 -33
- package/types/modules/table-up/index.d.ts +26 -26
- package/types/utils/is.d.ts +2 -0
- package/types/modules/custom-uploader.d.ts +0 -31
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlotFormatter.es.js","sources":["../../../../src/modules/custom-image/BlotFormatter.ts"],"sourcesContent":["import type Action from './actions/Action'\r\nimport type { Options } from './Options'\r\nimport type BlotSpec from './specs/BlotSpec'\r\nimport { merge as deepmerge } from 'lodash-es'\r\nimport Quill from 'quill'\r\nimport ImageBlot
|
|
1
|
+
{"version":3,"file":"BlotFormatter.es.js","sources":["../../../../src/modules/custom-image/BlotFormatter.ts"],"sourcesContent":["import type Action from './actions/Action'\r\nimport type { Options } from './Options'\r\nimport type BlotSpec from './specs/BlotSpec'\r\nimport { merge as deepmerge } from 'lodash-es'\r\nimport Quill from 'quill'\r\nimport ImageBlot from './image'\r\nimport ImageBar from './image-bar'\r\nimport DefaultOptions from './Options'\r\nimport { CustomImageSpec } from './specs/CustomImageSpec'\r\n\r\nconst dontMerge = (_destination: Array<any>, source: Array<any>) => source\r\n\r\n// @dynamic\r\nexport default class BlotFormatter {\r\n quill: any\r\n options: Options\r\n currentSpec: BlotSpec\r\n specs: BlotSpec[]\r\n overlay: HTMLElement\r\n actions: Action[]\r\n observer: any\r\n imageBar: ImageBar\r\n private debounceTimer: number | null = null\r\n\r\n static register() {\r\n Quill.register('formats/image', ImageBlot, true)\r\n Quill.register('modules/image-spec', CustomImageSpec, true)\r\n }\r\n\r\n constructor(quill: any, options: any = {}) {\r\n this.quill = quill\r\n this.options = deepmerge(DefaultOptions, options, { arrayMerge: dontMerge })\r\n this.currentSpec = null\r\n this.actions = []\r\n this.overlay = document.createElement('div')\r\n this.overlay.classList.add(this.options.overlay.className)\r\n if (this.options.overlay.style) {\r\n Object.assign(this.overlay.style, this.options.overlay.style)\r\n }\r\n\r\n // disable native image resizing on firefox\r\n document.execCommand('enableObjectResizing', false, 'false') // eslint-disable-next-line-line no-undef\r\n this.quill.root.addEventListener('click', this.onClick)\r\n this.quill.root.addEventListener('mouseover', event => this.onMouseOver(event))\r\n this.specs = this.options.specs.map((SpecClass: any) => new SpecClass(this))\r\n this.specs.forEach(spec => spec.init())\r\n }\r\n\r\n show(spec: BlotSpec) {\r\n this.currentSpec = spec\r\n this.currentSpec.setSelection()\r\n this.setUserSelect('none')\r\n this.quill.root.parentNode.appendChild(this.overlay)\r\n this.repositionOverlay()\r\n this.createActions(spec)\r\n\r\n // fix: 图片对齐之后,虚线外框应该跟随移动\r\n const imageDom = spec.getTargetElement()\r\n const win: any = window\r\n const MutationObserver = win.MutationObserver || win.WebKitMutationObserver || win.MozMutationObserver\r\n const element = imageDom.parentNode\r\n this.observer = new MutationObserver((mutationList) => {\r\n for (const mutation of mutationList) {\r\n const target = mutation.target\r\n const image = target.querySelector('img')\r\n if (image) {\r\n this.repositionOverlay()\r\n }\r\n }\r\n })\r\n this.observer.observe(element, {\r\n attributes: true,\r\n attributeFilter: ['class'],\r\n attributeOldValue: true,\r\n subtree: true,\r\n })\r\n document.body.addEventListener('click', this.hideImageOverlay, true)\r\n }\r\n\r\n hide() {\r\n if (!this.currentSpec) {\r\n return\r\n }\r\n\r\n const imgDom = this.currentSpec.getTargetElement()\r\n if (imgDom) {\r\n imgDom.classList.remove('current-select-img')\r\n }\r\n\r\n this.currentSpec.onHide()\r\n this.currentSpec = null\r\n this.quill.root.parentNode.removeChild(this.overlay)\r\n this.overlay.style.setProperty('display', 'none')\r\n this.setUserSelect('')\r\n this.destroyActions()\r\n }\r\n\r\n update() {\r\n this.repositionOverlay()\r\n this.actions.forEach(action => action.onUpdate())\r\n }\r\n\r\n createActions(spec: BlotSpec) {\r\n this.actions = spec.getActions().map((ActionClass: any) => {\r\n const action: Action = new ActionClass(this)\r\n action.onCreate()\r\n return action\r\n })\r\n }\r\n\r\n destroyActions() {\r\n this.actions.forEach((action: Action) => action.onDestroy())\r\n this.actions = []\r\n }\r\n\r\n repositionOverlay() {\r\n if (!this.currentSpec) {\r\n return\r\n }\r\n\r\n const overlayTarget = this.currentSpec.getOverlayElement()\r\n if (!overlayTarget) {\r\n return\r\n }\r\n\r\n const parent: HTMLElement = this.quill.root.parentNode\r\n const specRect = overlayTarget.getBoundingClientRect()\r\n const parentRect = parent.getBoundingClientRect()\r\n\r\n Object.assign(this.overlay.style, {\r\n display: 'block',\r\n left: `${specRect.left - parentRect.left - 1 + parent.scrollLeft}px`,\r\n top: `${specRect.top - parentRect.top + parent.scrollTop}px`,\r\n width: `${specRect.width}px`,\r\n height: `${specRect.height}px`,\r\n })\r\n }\r\n\r\n setUserSelect(value: string) {\r\n const props: string[] = [\r\n 'userSelect',\r\n 'mozUserSelect',\r\n 'webkitUserSelect',\r\n 'msUserSelect',\r\n ]\r\n\r\n props.forEach((prop: string) => {\r\n // set on contenteditable element and <html>\r\n this.quill.root.style.setProperty(prop, value)\r\n if (document.documentElement) {\r\n document.documentElement.style.setProperty(prop, value)\r\n }\r\n })\r\n }\r\n\r\n onClick = () => {\r\n this.hide()\r\n this.hideImageBar()\r\n }\r\n\r\n onMouseOver = (event) => {\r\n if (this.debounceTimer) {\r\n clearTimeout(this.debounceTimer)\r\n }\r\n this.debounceTimer = window.setTimeout(() => {\r\n if (event.target.tagName === 'IMG') {\r\n const target = event.target\r\n if (target) {\r\n if (this.imageBar) {\r\n this.imageBar.destroy()\r\n }\r\n this.imageBar = new ImageBar(this.quill, target)\r\n }\r\n }\r\n else {\r\n this.hideImageBar()\r\n }\r\n }, 150)\r\n }\r\n\r\n hideImageBar = () => {\r\n if (this.imageBar) {\r\n this.imageBar.destroy()\r\n this.imageBar = null\r\n }\r\n }\r\n\r\n hideImageOverlay = (event) => {\r\n const target = event.target\r\n const isBlotFormatter = target?.classList?.contains('blot-formatter__overlay')\r\n // 点击图片操作框之外应该将其销毁\r\n if (!isBlotFormatter) {\r\n this.hide()\r\n }\r\n document.body.removeEventListener('click', this.hideImageOverlay)\r\n }\r\n}\r\n"],"names":["deepmerge","ImageBlot"],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Quill from "quill";
|
|
2
2
|
import { sanitize, isNullOrUndefined } from "../../config/editor.utils.es.js";
|
|
3
|
-
const Embed = Quill.
|
|
4
|
-
const Inline = Quill.imports["blots/inline"];
|
|
3
|
+
const Embed = Quill.import("blots/embed");
|
|
5
4
|
const ATTRIBUTES = ["alt", "height", "width", "image-id"];
|
|
6
5
|
const _CustomImage = class _CustomImage extends Embed {
|
|
7
6
|
static create(value) {
|
|
@@ -15,7 +14,7 @@ const _CustomImage = class _CustomImage extends Embed {
|
|
|
15
14
|
node.setAttribute("src", imgURL);
|
|
16
15
|
}
|
|
17
16
|
node.setAttribute("data-image-id", `img${_CustomImage.ID_SEED++}`);
|
|
18
|
-
node.setAttribute("devui-editorx-image", true);
|
|
17
|
+
node.setAttribute("devui-editorx-image", "true");
|
|
19
18
|
node.style.verticalAlign = "baseline";
|
|
20
19
|
return node;
|
|
21
20
|
}
|
|
@@ -33,12 +32,12 @@ const _CustomImage = class _CustomImage extends Embed {
|
|
|
33
32
|
static register() {
|
|
34
33
|
if (/Firefox/i.test(navigator.userAgent)) {
|
|
35
34
|
setTimeout(() => {
|
|
36
|
-
document.execCommand("enableObjectResizing", false, false);
|
|
35
|
+
document.execCommand("enableObjectResizing", false, "false");
|
|
37
36
|
}, 1);
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
static sanitize(url) {
|
|
41
|
-
return sanitize(url, ["http", "https", "data"]) ? url : "//:0";
|
|
40
|
+
return sanitize(url, ["http", "https", "blob", "data"]) ? url : "//:0";
|
|
42
41
|
}
|
|
43
42
|
static value(domNode) {
|
|
44
43
|
const formats = {};
|
|
@@ -78,18 +77,7 @@ _CustomImage.ID_SEED = 0;
|
|
|
78
77
|
let CustomImage = _CustomImage;
|
|
79
78
|
CustomImage.blotName = "image";
|
|
80
79
|
CustomImage.tagName = "IMG";
|
|
81
|
-
class CustomImageContainer extends Inline {
|
|
82
|
-
constructor(scroll, domNode) {
|
|
83
|
-
super(scroll, domNode);
|
|
84
|
-
domNode.setAttribute("contenteditable", false);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
CustomImageContainer.blotName = "image-container";
|
|
88
|
-
CustomImageContainer.className = "ql-image-container";
|
|
89
|
-
CustomImageContainer.tagName = "DIV";
|
|
90
|
-
CustomImageContainer.allowedChildren = [CustomImage];
|
|
91
80
|
export {
|
|
92
|
-
CustomImageContainer as ImageContainerBlot,
|
|
93
81
|
CustomImage as default
|
|
94
82
|
};
|
|
95
83
|
//# sourceMappingURL=image.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.es.js","sources":["../../../../src/modules/custom-image/image.ts"],"sourcesContent":["import Quill from 'quill'\r\nimport { isNullOrUndefined, sanitize } from '../../config/editor.utils'\r\n\r\nconst Embed = Quill.
|
|
1
|
+
{"version":3,"file":"image.es.js","sources":["../../../../src/modules/custom-image/image.ts"],"sourcesContent":["import type TypeEmbed from 'quill/blots/embed'\r\nimport Quill from 'quill'\r\nimport { isNullOrUndefined, sanitize } from '../../config/editor.utils'\r\n\r\nconst Embed = Quill.import('blots/embed') as typeof TypeEmbed\r\nconst ATTRIBUTES = ['alt', 'height', 'width', 'image-id']\r\n\r\nexport type ImageValue = string | { src: string }\r\nclass CustomImage extends Embed {\r\n static ID_SEED = 0\r\n static blotName: string\r\n static tagName: string\r\n domNode: any\r\n parent: any\r\n scroll: any\r\n next: any\r\n static create(value: ImageValue) {\r\n const node = super.create(value) as HTMLElement\r\n const url = typeof value === 'string' ? value : value.src\r\n if (url) {\r\n const imgURL = this.sanitize(url)\r\n if (!imgURL?.startsWith('data:image')) {\r\n node.dataset.src = imgURL\r\n }\r\n node.setAttribute('src', imgURL)\r\n }\r\n node.setAttribute('data-image-id', `img${CustomImage.ID_SEED++}`)\r\n node.setAttribute('devui-editorx-image', 'true')\r\n node.style.verticalAlign = 'baseline'\r\n return node\r\n }\r\n\r\n static formats(domNode) {\r\n return ATTRIBUTES.reduce((formats, attribute) => {\r\n if (domNode.hasAttribute(attribute)) {\r\n formats[attribute] = domNode.getAttribute(attribute)\r\n }\r\n return formats\r\n }, {})\r\n }\r\n\r\n static match(url) {\r\n return /\\.(jpe?g|gif|png)$/.test(url) || /^data:image\\/.+;base64/.test(url)\r\n }\r\n\r\n static register() {\r\n if (/Firefox/i.test(navigator.userAgent)) {\r\n setTimeout(() => {\r\n // Disable image resizing in Firefox\r\n document.execCommand('enableObjectResizing', false, 'false')\r\n }, 1)\r\n }\r\n }\r\n\r\n static sanitize(url) {\r\n return sanitize(url, ['http', 'https', 'blob', 'data']) ? url : '//:0'\r\n }\r\n\r\n static value(domNode) {\r\n const formats: any = {}\r\n const imageSrc = domNode.getAttribute('src')\r\n formats.src = this.sanitize(imageSrc)\r\n formats.hasExisted = domNode.getAttribute('devui-editorx-image')\r\n formats.imageId = domNode.dataset.imageId\r\n return formats\r\n }\r\n\r\n format(name, value) {\r\n if (ATTRIBUTES.includes(name)) {\r\n if (value) {\r\n this.domNode.setAttribute(name, value)\r\n }\r\n else {\r\n this.domNode.removeAttribute(name)\r\n }\r\n }\r\n else {\r\n super.format(name, value)\r\n }\r\n }\r\n\r\n unWrap() {\r\n this.parent.replaceWith(this)\r\n }\r\n\r\n wrap(name, value) {\r\n const wrapper = typeof name === 'string' ? this.scroll.create(name, value) : name\r\n if (!isNullOrUndefined(this.parent)) {\r\n this.parent.insertBefore(wrapper, this.next || undefined)\r\n }\r\n if (typeof wrapper.appendChild !== 'function') {\r\n throw new TypeError(`Cannot wrap ${name}`)\r\n }\r\n wrapper.appendChild(this)\r\n return wrapper\r\n }\r\n}\r\nCustomImage.blotName = 'image'\r\nCustomImage.tagName = 'IMG'\r\n\r\nexport { CustomImage as default }\r\n"],"names":[],"mappings":";;AAIA,MAAM,QAAQ,MAAM,OAAO,aAAa;AACxC,MAAM,aAAa,CAAC,OAAO,UAAU,SAAS,UAAU;AAGxD,MAAM,eAAN,MAAM,qBAAoB,MAAM;AAAA,EAQ9B,OAAO,OAAO,OAAmB;AACzB,UAAA,OAAO,MAAM,OAAO,KAAK;AAC/B,UAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,MAAM;AACtD,QAAI,KAAK;AACD,YAAA,SAAS,KAAK,SAAS,GAAG;AAChC,UAAI,EAAC,iCAAQ,WAAW,gBAAe;AACrC,aAAK,QAAQ,MAAM;AAAA,MAAA;AAEhB,WAAA,aAAa,OAAO,MAAM;AAAA,IAAA;AAEjC,SAAK,aAAa,iBAAiB,MAAM,aAAY,SAAS,EAAE;AAC3D,SAAA,aAAa,uBAAuB,MAAM;AAC/C,SAAK,MAAM,gBAAgB;AACpB,WAAA;AAAA,EAAA;AAAA,EAGT,OAAO,QAAQ,SAAS;AACtB,WAAO,WAAW,OAAO,CAAC,SAAS,cAAc;AAC3C,UAAA,QAAQ,aAAa,SAAS,GAAG;AACnC,gBAAQ,SAAS,IAAI,QAAQ,aAAa,SAAS;AAAA,MAAA;AAE9C,aAAA;AAAA,IACT,GAAG,EAAE;AAAA,EAAA;AAAA,EAGP,OAAO,MAAM,KAAK;AAChB,WAAO,qBAAqB,KAAK,GAAG,KAAK,yBAAyB,KAAK,GAAG;AAAA,EAAA;AAAA,EAG5E,OAAO,WAAW;AAChB,QAAI,WAAW,KAAK,UAAU,SAAS,GAAG;AACxC,iBAAW,MAAM;AAEN,iBAAA,YAAY,wBAAwB,OAAO,OAAO;AAAA,SAC1D,CAAC;AAAA,IAAA;AAAA,EACN;AAAA,EAGF,OAAO,SAAS,KAAK;AACZ,WAAA,SAAS,KAAK,CAAC,QAAQ,SAAS,QAAQ,MAAM,CAAC,IAAI,MAAM;AAAA,EAAA;AAAA,EAGlE,OAAO,MAAM,SAAS;AACpB,UAAM,UAAe,CAAC;AAChB,UAAA,WAAW,QAAQ,aAAa,KAAK;AACnC,YAAA,MAAM,KAAK,SAAS,QAAQ;AAC5B,YAAA,aAAa,QAAQ,aAAa,qBAAqB;AACvD,YAAA,UAAU,QAAQ,QAAQ;AAC3B,WAAA;AAAA,EAAA;AAAA,EAGT,OAAO,MAAM,OAAO;AACd,QAAA,WAAW,SAAS,IAAI,GAAG;AAC7B,UAAI,OAAO;AACJ,aAAA,QAAQ,aAAa,MAAM,KAAK;AAAA,MAAA,OAElC;AACE,aAAA,QAAQ,gBAAgB,IAAI;AAAA,MAAA;AAAA,IACnC,OAEG;AACG,YAAA,OAAO,MAAM,KAAK;AAAA,IAAA;AAAA,EAC1B;AAAA,EAGF,SAAS;AACF,SAAA,OAAO,YAAY,IAAI;AAAA,EAAA;AAAA,EAG9B,KAAK,MAAM,OAAO;AACV,UAAA,UAAU,OAAO,SAAS,WAAW,KAAK,OAAO,OAAO,MAAM,KAAK,IAAI;AAC7E,QAAI,CAAC,kBAAkB,KAAK,MAAM,GAAG;AACnC,WAAK,OAAO,aAAa,SAAS,KAAK,QAAQ,MAAS;AAAA,IAAA;AAEtD,QAAA,OAAO,QAAQ,gBAAgB,YAAY;AAC7C,YAAM,IAAI,UAAU,eAAe,IAAI,EAAE;AAAA,IAAA;AAE3C,YAAQ,YAAY,IAAI;AACjB,WAAA;AAAA,EAAA;AAEX;AAvFE,aAAO,UAAU;AADnB,IAAM,cAAN;AAyFA,YAAY,WAAW;AACvB,YAAY,UAAU;"}
|
|
@@ -1,209 +1,76 @@
|
|
|
1
1
|
import Quill from "quill";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
const Uploader = Quill.imports["modules/uploader"];
|
|
2
|
+
import { isString } from "../utils/is.es.js";
|
|
3
|
+
const Uploader = Quill.import("modules/uploader");
|
|
5
4
|
const Delta = Quill.import("delta");
|
|
6
|
-
class
|
|
7
|
-
constructor() {
|
|
8
|
-
super(
|
|
9
|
-
this.
|
|
10
|
-
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
return file.size <= maxSize;
|
|
14
|
-
};
|
|
15
|
-
this.isAllowedFileType = (accept, file) => {
|
|
16
|
-
if (accept) {
|
|
17
|
-
const baseMimeType = file.type.replace(/\/.*$/, "");
|
|
18
|
-
const acceptArr = typeof accept === "string" ? accept.split(",") : accept;
|
|
19
|
-
return acceptArr.some((type) => {
|
|
20
|
-
const validType = type.trim();
|
|
21
|
-
if (validType.startsWith(".")) {
|
|
22
|
-
return file.name.toLowerCase().includes(validType.toLowerCase(), file.name.toLowerCase().length - validType.toLowerCase().length);
|
|
23
|
-
} else if (/\/\*$/.test(validType)) {
|
|
24
|
-
return baseMimeType === validType.replace(/\/.*$/, "");
|
|
25
|
-
}
|
|
26
|
-
return file.type === validType;
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
return true;
|
|
30
|
-
};
|
|
5
|
+
const _FileUploader = class _FileUploader extends Uploader {
|
|
6
|
+
constructor(quill, options) {
|
|
7
|
+
super(quill, options);
|
|
8
|
+
this.quill = quill;
|
|
9
|
+
this.options = this.resolveOptions(options);
|
|
31
10
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
file: uploadOption.fileAccept
|
|
43
|
-
} || {};
|
|
44
|
-
Array.from(files).forEach((file) => {
|
|
45
|
-
var _a, _b;
|
|
46
|
-
if (file) {
|
|
47
|
-
const fileFlag = typeof isFile === "boolean" ? isFile : !/^image\/[-\w.]+$/.test(file.type);
|
|
48
|
-
const fileType = fileFlag ? "file" : "image";
|
|
49
|
-
const accept = acceptObj[fileType] || this.options[fileType];
|
|
50
|
-
if (this.isAllowedFileType(accept, file) && this.isAllowedFileSize(uploadOption == null ? void 0 : uploadOption.maxSize, file)) {
|
|
51
|
-
uploads.push(file);
|
|
52
|
-
fileFlags.push(fileFlag);
|
|
53
|
-
(_a = uploadOption == null ? void 0 : uploadOption.success) == null ? void 0 : _a.call(uploadOption, file);
|
|
54
|
-
} else {
|
|
55
|
-
rejectFlags[fileType] = true;
|
|
56
|
-
(_b = uploadOption == null ? void 0 : uploadOption.fail) == null ? void 0 : _b.call(uploadOption, file);
|
|
57
|
-
}
|
|
11
|
+
resolveOptions(options = {}) {
|
|
12
|
+
return Object.assign({
|
|
13
|
+
mimetypes: ["*"],
|
|
14
|
+
maxSize: Number.POSITIVE_INFINITY,
|
|
15
|
+
handler(range, files) {
|
|
16
|
+
return files.map((file) => URL.createObjectURL(file));
|
|
17
|
+
},
|
|
18
|
+
success() {
|
|
19
|
+
},
|
|
20
|
+
fail() {
|
|
58
21
|
}
|
|
59
|
-
});
|
|
60
|
-
this.options.handler.call(this, range, uploads, fileFlags, rejectFlags);
|
|
22
|
+
}, options);
|
|
61
23
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
var _a;
|
|
65
|
-
if ((_a = this.quill.options.uploadOption) == null ? void 0 : _a.fileUpload) {
|
|
66
|
-
const initialRange = range;
|
|
67
|
-
files.forEach((file) => {
|
|
68
|
-
var _a2;
|
|
69
|
-
const result = {
|
|
70
|
-
file,
|
|
71
|
-
callback: (res) => {
|
|
72
|
-
if (!res) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
this.insertFileToEditor(initialRange, file, {
|
|
76
|
-
code: 0,
|
|
77
|
-
data: {
|
|
78
|
-
title: file.name,
|
|
79
|
-
size: file.size,
|
|
80
|
-
src: res.fileUrl
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
initialRange.index += 1;
|
|
84
|
-
},
|
|
85
|
-
editor: this.quill
|
|
86
|
-
};
|
|
87
|
-
(_a2 = this.quill.options.uploadOption) == null ? void 0 : _a2.fileUpload(result);
|
|
88
|
-
});
|
|
89
|
-
} else {
|
|
90
|
-
files.forEach((file) => {
|
|
91
|
-
const fileUrl = URL.createObjectURL(file);
|
|
92
|
-
const initialRange = range;
|
|
93
|
-
this.insertFileToEditor(initialRange, file, {
|
|
94
|
-
code: 0,
|
|
95
|
-
data: {
|
|
96
|
-
title: file.name,
|
|
97
|
-
size: file.size,
|
|
98
|
-
src: file.src ?? fileUrl
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
initialRange.index += 1;
|
|
102
|
-
});
|
|
103
|
-
}
|
|
24
|
+
validateFile(file) {
|
|
25
|
+
return this.options.mimetypes.some((type) => (file.type || "text/plain").match(type.replaceAll("*", ".*"))) && file.size < this.options.maxSize;
|
|
104
26
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const oldContent = new Delta().retain(range.index).delete(range.length);
|
|
109
|
-
const videoFlag = this.uploadOption && this.uploadOption.isVideoPlay && /^video\/[-\w.]+$/.test(file.type);
|
|
110
|
-
const insertObj = videoFlag ? { video: data } : { file: data };
|
|
111
|
-
const currentContent = new Delta([{ insert: insertObj }]);
|
|
112
|
-
const newContent = oldContent.concat(currentContent);
|
|
113
|
-
this.quill.updateContents(newContent, Quill.sources.USER);
|
|
114
|
-
this.quill.setSelection(range.index + 1);
|
|
115
|
-
} else {
|
|
116
|
-
console.error("error message:", message);
|
|
117
|
-
}
|
|
27
|
+
async getFileUrls(files, range) {
|
|
28
|
+
const uploads = files.filter((file) => this.validateFile(file));
|
|
29
|
+
return this.options.handler.call(this, range, uploads);
|
|
118
30
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
]);
|
|
130
|
-
const newContent = oldContent.concat(currentContent);
|
|
131
|
-
this.quill.updateContents(newContent, Quill.sources.USER);
|
|
132
|
-
this.quill.setSelection(range.index + 1);
|
|
133
|
-
} else {
|
|
134
|
-
console.error("error message:", message);
|
|
31
|
+
async upload(range, files) {
|
|
32
|
+
const uploads = [];
|
|
33
|
+
const fails = [];
|
|
34
|
+
for (const file of Array.from(files)) {
|
|
35
|
+
if (this.validateFile(file)) {
|
|
36
|
+
uploads.push(file);
|
|
37
|
+
} else {
|
|
38
|
+
fails.push(file);
|
|
39
|
+
}
|
|
135
40
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
file: file2,
|
|
147
|
-
data: { files: [file2] },
|
|
148
|
-
hasRejectedImage,
|
|
149
|
-
callback: (res) => {
|
|
150
|
-
if (!res) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
if (imageEnableMultiUpload && Array.isArray(res)) {
|
|
154
|
-
res.forEach((value) => {
|
|
155
|
-
this.insertImageToEditor(initialRange, value);
|
|
156
|
-
initialRange.index += 1;
|
|
157
|
-
});
|
|
158
|
-
} else {
|
|
159
|
-
this.insertImageToEditor(initialRange, res);
|
|
160
|
-
initialRange.index += 1;
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
editor: this.quill
|
|
164
|
-
};
|
|
165
|
-
if (imageEnableMultiUpload) {
|
|
166
|
-
result.data = { files };
|
|
41
|
+
const result = await this.options.handler.call(this, range, uploads);
|
|
42
|
+
const updateDelta = result.reduce((delta, url, i) => {
|
|
43
|
+
if (isString(url)) {
|
|
44
|
+
const type = uploads[i].type;
|
|
45
|
+
if (type.startsWith("image/")) {
|
|
46
|
+
delta.insert({ image: url });
|
|
47
|
+
} else if (type.startsWith("video/")) {
|
|
48
|
+
delta.insert({ video: { src: url } });
|
|
49
|
+
} else {
|
|
50
|
+
delta.insert({ file: { size: uploads[i].size, title: uploads[i].name, src: url } });
|
|
167
51
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
reader.readAsDataURL(fileItem);
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
Promise.all(promises).then((images) => {
|
|
181
|
-
const update = images.reduce((delta, image) => {
|
|
182
|
-
return delta.insert({ image });
|
|
183
|
-
}, new Delta().retain(range.index).delete(range.length));
|
|
184
|
-
this.quill.updateContents(update, Quill.sources.USER);
|
|
185
|
-
this.quill.setSelection(range.index + images.length, Quill.sources.SILENT);
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
CustomUploader.DEFAULTS = {
|
|
191
|
-
file: FILE_UPLOADER_MIME_TYPES,
|
|
192
|
-
image: IMAGE_UPLOADER_MIME_TYPES,
|
|
193
|
-
enableMultiUpload: false,
|
|
194
|
-
handler(range, files, fileFlags, rejectFlags) {
|
|
195
|
-
const fileArr = [];
|
|
196
|
-
const imgArr = [];
|
|
197
|
-
files.forEach((file, index) => fileFlags[index] ? fileArr.push(file) : imgArr.push(file));
|
|
198
|
-
if (this.quill.options.modules.file && (fileArr.length || rejectFlags.file)) {
|
|
199
|
-
this.handleUploadFile(range, fileArr, rejectFlags.file);
|
|
52
|
+
} else {
|
|
53
|
+
delta.insert("\n");
|
|
54
|
+
}
|
|
55
|
+
return delta;
|
|
56
|
+
}, new Delta().retain(range.index).delete(range.length));
|
|
57
|
+
this.quill.updateContents(updateDelta, Quill.sources.USER);
|
|
58
|
+
this.quill.setSelection(range.index + result.length, Quill.sources.SILENT);
|
|
59
|
+
for (const file of fails) {
|
|
60
|
+
this.options.fail.call(this, file, range);
|
|
200
61
|
}
|
|
201
|
-
|
|
202
|
-
|
|
62
|
+
for (const [i, res] of result.entries()) {
|
|
63
|
+
if (isString(res)) {
|
|
64
|
+
this.options.success.call(this, files[i], { index: range.index + i, length: 0 });
|
|
65
|
+
} else {
|
|
66
|
+
this.options.fail.call(this, files[i], { index: range.index + i, length: 0 });
|
|
67
|
+
}
|
|
203
68
|
}
|
|
204
69
|
}
|
|
205
70
|
};
|
|
71
|
+
_FileUploader.DEFAULTS = {};
|
|
72
|
+
let FileUploader = _FileUploader;
|
|
206
73
|
export {
|
|
207
|
-
|
|
74
|
+
FileUploader
|
|
208
75
|
};
|
|
209
76
|
//# sourceMappingURL=custom-uploader.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-uploader.es.js","sources":["../../../src/modules/custom-uploader.ts"],"sourcesContent":["import type { Range } from 'quill/core/quill'\r\n\r\nimport Quill from 'quill'\r\nimport {\r\n FILE_UPLOADER_MIME_TYPES,\r\n IMAGE_UPLOADER_MIME_TYPES,\r\n} from '../config/editor.config'\r\nimport {\r\n isNullOrUndefined,\r\n} from '../config/editor.utils'\r\n\r\ninterface InsertFileData {\r\n code: number\r\n message?: string\r\n data: {\r\n title: string\r\n size: number\r\n src: string\r\n }\r\n}\r\n\r\nconst Uploader = Quill.imports['modules/uploader']\r\nconst Delta = Quill.import('delta')\r\n\r\nclass CustomUploader extends Uploader {\r\n quill\r\n options\r\n\r\n upload(range, files, isFile?) {\r\n const uploads = []\r\n const fileFlags = []\r\n const rejectFlags = {\r\n file: false,\r\n image: false,\r\n }\r\n const uploadOption = this.quill.options.uploadOption\r\n const acceptObj\r\n = (uploadOption && {\r\n image: uploadOption.imageAccept,\r\n file: uploadOption.fileAccept,\r\n })\r\n || {}\r\n Array.from(files).forEach((file: any) => {\r\n if (file) {\r\n const fileFlag\r\n = typeof isFile === 'boolean'\r\n ? isFile\r\n : !/^image\\/[-\\w.]+$/.test(file.type)\r\n const fileType = fileFlag ? 'file' : 'image'\r\n const accept = acceptObj[fileType] || this.options[fileType]\r\n if (this.isAllowedFileType(accept, file) && this.isAllowedFileSize(uploadOption?.maxSize, file)) {\r\n uploads.push(file)\r\n fileFlags.push(fileFlag)\r\n uploadOption?.success?.(file)\r\n }\r\n else {\r\n rejectFlags[fileType] = true\r\n uploadOption?.fail?.(file)\r\n }\r\n }\r\n })\r\n this.options.handler.call(this, range, uploads, fileFlags, rejectFlags)\r\n }\r\n\r\n isAllowedFileSize = (maxSize: number, file: File) => {\r\n if (isNullOrUndefined(maxSize)) {\r\n return true\r\n }\r\n\r\n return file.size <= maxSize\r\n }\r\n\r\n isAllowedFileType = (accept: Array<string> | string, file: File) => {\r\n if (accept) {\r\n const baseMimeType = file.type.replace(/\\/.*$/, '')\r\n const acceptArr = typeof accept === 'string' ? accept.split(',') : accept\r\n return acceptArr.some((type: string) => {\r\n const validType = type.trim()\r\n // suffix name (e.g. '.png,.xlsx')\r\n if (validType.startsWith('.')) {\r\n return (\r\n file.name\r\n .toLowerCase()\r\n .includes(validType.toLowerCase(), file.name.toLowerCase().length - validType.toLowerCase().length)\r\n )\r\n // mime type like 'image/*'\r\n }\r\n else if (/\\/\\*$/.test(validType)) {\r\n return baseMimeType === validType.replace(/\\/.*$/, '')\r\n }\r\n // mime type like 'text/plain,application/json'\r\n return file.type === validType\r\n })\r\n }\r\n return true\r\n }\r\n\r\n // 处理上传文件\r\n handleUploadFile(range, files, _hasRejectedFile) {\r\n if (this.quill.options.uploadOption?.fileUpload) {\r\n const initialRange = range\r\n files.forEach((file) => {\r\n const result = {\r\n file,\r\n callback: (res) => {\r\n if (!res) {\r\n return\r\n }\r\n this.insertFileToEditor(initialRange, file, {\r\n code: 0,\r\n data: {\r\n title: file.name,\r\n size: file.size,\r\n src: res.fileUrl,\r\n },\r\n })\r\n initialRange.index += 1\r\n },\r\n editor: this.quill,\r\n }\r\n this.quill.options.uploadOption?.fileUpload(result)\r\n })\r\n }\r\n else {\r\n files.forEach((file) => {\r\n const fileUrl = URL.createObjectURL(file)\r\n const initialRange = range\r\n this.insertFileToEditor(initialRange, file, {\r\n code: 0,\r\n data: {\r\n title: file.name,\r\n size: file.size,\r\n src: file.src ?? fileUrl,\r\n },\r\n })\r\n initialRange.index += 1\r\n })\r\n }\r\n }\r\n\r\n // 将文件插入编辑器\r\n insertFileToEditor(range: Range, file: File, { code, message, data }: InsertFileData) {\r\n if (code === 0) {\r\n const oldContent = new Delta().retain(range.index).delete(range.length)\r\n const videoFlag = this.uploadOption && this.uploadOption.isVideoPlay && /^video\\/[-\\w.]+$/.test(file.type)\r\n const insertObj = videoFlag ? { video: data } : { file: data }\r\n const currentContent = new Delta([{ insert: insertObj }])\r\n const newContent = oldContent.concat(currentContent)\r\n this.quill.updateContents(newContent, Quill.sources.USER)\r\n this.quill.setSelection(range.index + 1)\r\n }\r\n else {\r\n console.error('error message:', message)\r\n }\r\n }\r\n\r\n // 将图片插入编辑器\r\n insertImageToEditor(range, { code, message, data }) {\r\n if (code === 0) {\r\n const { imageId, imageUrl } = data\r\n // 粘贴截图或者从外源直接拷贝的单图时,需要将编辑器中已选中的内容删除\r\n const oldContent = new Delta().retain(range.index).delete(range.length)\r\n const currentContent = new Delta([\r\n {\r\n insert: { image: imageUrl },\r\n attributes: { 'image-id': imageId },\r\n },\r\n ])\r\n const newContent = oldContent.concat(currentContent)\r\n this.quill.updateContents(newContent, Quill.sources.USER)\r\n this.quill.setSelection(range.index + 1)\r\n }\r\n else {\r\n console.error('error message:', message)\r\n }\r\n }\r\n\r\n // 处理上传图片\r\n handleUploadImage(range, { file, files }, hasRejectedImage) {\r\n if (this.quill.options.uploadOption?.imageUpload) {\r\n // const imageEnableMultiUpload = this.enableMultiUpload === true || this.enableMultiUpload?.image\r\n // 此处this获取不到enableMultiUpload\r\n const imageEnableMultiUpload = this.quill.uploader.options.enableMultiUpload === true || this.quill.uploader.options.enableMultiUpload?.image\r\n files.forEach((file) => {\r\n const initialRange = range\r\n const result = {\r\n file,\r\n data: { files: [file] },\r\n hasRejectedImage,\r\n callback: (res) => {\r\n if (!res) {\r\n return\r\n }\r\n if (imageEnableMultiUpload && Array.isArray(res)) {\r\n res.forEach((value) => {\r\n this.insertImageToEditor(initialRange, value)\r\n initialRange.index += 1\r\n })\r\n }\r\n else {\r\n this.insertImageToEditor(initialRange, res)\r\n initialRange.index += 1\r\n }\r\n },\r\n editor: this.quill,\r\n }\r\n if (imageEnableMultiUpload) {\r\n result.data = { files }\r\n }\r\n this.quill.options.uploadOption?.imageUpload(result)\r\n })\r\n }\r\n else {\r\n const promises = files.map((fileItem) => {\r\n return new Promise((resolve) => {\r\n const reader = new FileReader()\r\n reader.onload = (e: any) => {\r\n resolve(e.target.result)\r\n }\r\n reader.readAsDataURL(fileItem)\r\n })\r\n })\r\n Promise.all(promises).then((images) => {\r\n const update = images.reduce((delta: any, image) => {\r\n return delta.insert({ image })\r\n }, new Delta().retain(range.index).delete(range.length))\r\n this.quill.updateContents(update, Quill.sources.USER)\r\n this.quill.setSelection(range.index + images.length, Quill.sources.SILENT)\r\n })\r\n }\r\n }\r\n}\r\n\r\nCustomUploader.DEFAULTS = {\r\n file: FILE_UPLOADER_MIME_TYPES,\r\n image: IMAGE_UPLOADER_MIME_TYPES,\r\n enableMultiUpload: false,\r\n handler(range, files, fileFlags, rejectFlags) {\r\n const fileArr = []\r\n const imgArr = []\r\n files.forEach((file, index) => (fileFlags[index] ? fileArr.push(file) : imgArr.push(file)))\r\n if (this.quill.options.modules.file && (fileArr.length || rejectFlags.file)) {\r\n this.handleUploadFile(range, fileArr, rejectFlags.file)\r\n }\r\n if (imgArr.length || rejectFlags.image) {\r\n this.handleUploadImage(range, { file: imgArr[0], files: imgArr }, rejectFlags.image)\r\n }\r\n },\r\n}\r\n\r\nexport default CustomUploader\r\n"],"names":["_a","file"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom-uploader.es.js","sources":["../../../src/modules/custom-uploader.ts"],"sourcesContent":["import type { Range } from 'quill'\r\nimport type TypeUploader from 'quill/modules/uploader'\r\nimport type FluentEditor from '../core/fluent-editor'\r\nimport Quill from 'quill'\r\nimport { isString } from '../utils/is'\r\n\r\nconst Uploader = Quill.import('modules/uploader') as typeof TypeUploader\r\nconst Delta = Quill.import('delta')\r\n\r\ninterface UploaderOptions {\r\n mimetypes: string[]\r\n handler: (this: { quill: Quill }, range: Range, files: File[]) => void\r\n}\r\nexport interface FileUploaderOptions {\r\n mimetypes: string[]\r\n maxSize: number\r\n handler: (this: { quill: FluentEditor }, range: Range, files: File[]) => Promise<(string | false)[]> | (string | false)[]\r\n success: (this: { quill: FluentEditor }, file: File, range: Range) => void\r\n fail: (this: { quill: FluentEditor }, file: File, range: Range) => void\r\n}\r\nexport class FileUploader extends Uploader {\r\n static DEFAULTS = {} as typeof Uploader.DEFAULTS\r\n // Partial<UploaderOptions> for ts type\r\n options: Partial<UploaderOptions> & FileUploaderOptions\r\n constructor(public quill: FluentEditor, options: Partial<FileUploaderOptions>) {\r\n super(quill, options as any)\r\n this.options = this.resolveOptions(options)\r\n // paste handle in clipboard\r\n }\r\n\r\n resolveOptions(options: Partial<FileUploaderOptions> = {}) {\r\n return Object.assign({\r\n mimetypes: ['*'],\r\n maxSize: Number.POSITIVE_INFINITY,\r\n handler(range: Range, files: File[]) {\r\n return files.map(file => URL.createObjectURL(file))\r\n },\r\n success() {},\r\n fail() {},\r\n }, options)\r\n }\r\n\r\n validateFile(file: File) {\r\n return this.options.mimetypes.some(type => (file.type || 'text/plain').match(type.replaceAll('*', '.*'))) && file.size < this.options.maxSize\r\n }\r\n\r\n async getFileUrls(files: File[], range: Range) {\r\n const uploads = files.filter(file => this.validateFile(file))\r\n return this.options.handler.call(this, range, uploads)\r\n }\r\n\r\n async upload(range: Range, files: FileList | File[]) {\r\n const uploads = []\r\n const fails = []\r\n for (const file of Array.from(files)) {\r\n if (this.validateFile(file)) {\r\n uploads.push(file)\r\n }\r\n else {\r\n fails.push(file)\r\n }\r\n }\r\n const result = await this.options.handler.call(this, range, uploads)\r\n const updateDelta = result.reduce((delta, url, i) => {\r\n if (isString(url)) {\r\n const type = uploads[i].type\r\n if (type.startsWith('image/')) {\r\n delta.insert({ image: url })\r\n }\r\n else if (type.startsWith('video/')) {\r\n delta.insert({ video: { src: url } })\r\n }\r\n else {\r\n delta.insert({ file: { size: uploads[i].size, title: uploads[i].name, src: url } })\r\n }\r\n }\r\n else {\r\n delta.insert('\\n')\r\n }\r\n return delta\r\n }, new Delta().retain(range.index).delete(range.length))\r\n this.quill.updateContents(updateDelta, Quill.sources.USER)\r\n this.quill.setSelection(range.index + result.length, Quill.sources.SILENT)\r\n for (const file of fails) {\r\n this.options.fail.call(this, file, range)\r\n }\r\n for (const [i, res] of result.entries()) {\r\n if (isString(res)) {\r\n this.options.success.call(this, files[i], { index: range.index + i, length: 0 })\r\n }\r\n else {\r\n this.options.fail.call(this, files[i], { index: range.index + i, length: 0 })\r\n }\r\n }\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import Quill from "quill";
|
|
2
2
|
import { sanitize } from "../../../config/editor.utils.es.js";
|
|
3
|
-
const Embed = Quill.
|
|
3
|
+
const Embed = Quill.import("blots/embed");
|
|
4
4
|
const FILE_ATTRIBUTES = ["id", "title", "size", "lastModified"];
|
|
5
|
-
class
|
|
5
|
+
const _File = class _File extends Embed {
|
|
6
6
|
static create(value) {
|
|
7
7
|
const node = super.create(value);
|
|
8
8
|
const size = value.size / 1024;
|
|
9
9
|
const fixSize = !size ? 0 : size < 1 ? 1 : size.toFixed(0);
|
|
10
10
|
node.classList.add("icon-file");
|
|
11
|
-
node.setAttribute("contenteditable", false);
|
|
11
|
+
node.setAttribute("contenteditable", "false");
|
|
12
12
|
const fileSvg = '<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326z m1.8 562H232V136h302v216c0 23.2 18.8 42 42 42h216v494z" p-id="2307"></path></svg>';
|
|
13
13
|
node.innerHTML = `${fileSvg} ${value.title} (${fixSize} KB)`;
|
|
14
|
-
const src =
|
|
14
|
+
const src = this.sanitize(value.src);
|
|
15
15
|
if (src) {
|
|
16
16
|
node.href = src;
|
|
17
17
|
node.target = "_blank";
|
|
@@ -24,14 +24,11 @@ class File extends Embed {
|
|
|
24
24
|
return node;
|
|
25
25
|
}
|
|
26
26
|
static value(domNode) {
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
static formats(domNode) {
|
|
30
|
-
return File.getFormats(domNode);
|
|
27
|
+
return this.getFormats(domNode);
|
|
31
28
|
}
|
|
32
29
|
static getFormats(domNode) {
|
|
33
30
|
const formats = {};
|
|
34
|
-
const href =
|
|
31
|
+
const href = this.sanitize(domNode.href);
|
|
35
32
|
if (href) {
|
|
36
33
|
formats.src = href;
|
|
37
34
|
}
|
|
@@ -45,11 +42,12 @@ class File extends Embed {
|
|
|
45
42
|
static sanitize(url) {
|
|
46
43
|
return sanitize(url, this.PROTOCOL_WHITELIST) && url || "";
|
|
47
44
|
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
};
|
|
46
|
+
_File.blotName = "file";
|
|
47
|
+
_File.tagName = "A";
|
|
48
|
+
_File.className = "ql-file-item";
|
|
49
|
+
_File.PROTOCOL_WHITELIST = ["http", "https", "blob"];
|
|
50
|
+
let File = _File;
|
|
53
51
|
export {
|
|
54
52
|
File as default
|
|
55
53
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.es.js","sources":["../../../../../src/modules/file/formats/file.ts"],"sourcesContent":["import Quill from 'quill'\r\nimport { sanitize } from '../../../config/editor.utils'\r\n\r\nconst Embed = Quill.
|
|
1
|
+
{"version":3,"file":"file.es.js","sources":["../../../../../src/modules/file/formats/file.ts"],"sourcesContent":["import type TypeEmbed from 'quill/blots/embed'\r\nimport Quill from 'quill'\r\nimport { sanitize } from '../../../config/editor.utils'\r\n\r\nconst Embed = Quill.import('blots/embed') as typeof TypeEmbed\r\nconst FILE_ATTRIBUTES = ['id', 'title', 'size', 'lastModified']\r\n\r\nexport interface FileValue {\r\n size: number\r\n src: string\r\n title: string\r\n}\r\nclass File extends Embed {\r\n static blotName = 'file'\r\n static tagName = 'A'\r\n static className = 'ql-file-item'\r\n static PROTOCOL_WHITELIST = ['http', 'https', 'blob']\r\n\r\n static create(value: FileValue) {\r\n const node = super.create(value) as HTMLAnchorElement\r\n const size = value.size / 1024\r\n const fixSize = !size ? 0 : size < 1 ? 1 : size.toFixed(0)\r\n node.classList.add('icon-file')\r\n node.setAttribute('contenteditable', 'false')\r\n const fileSvg = '<svg viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path d=\"M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326z m1.8 562H232V136h302v216c0 23.2 18.8 42 42 42h216v494z\" p-id=\"2307\"></path></svg>'\r\n node.innerHTML = `${fileSvg} ${value.title} (${fixSize} KB)`\r\n const src = this.sanitize(value.src)\r\n if (src) {\r\n node.href = src\r\n node.target = '_blank'\r\n }\r\n FILE_ATTRIBUTES.forEach((key) => {\r\n if (value[key]) {\r\n node.dataset[key] = value[key]\r\n }\r\n })\r\n return node\r\n }\r\n\r\n static value(domNode: HTMLAnchorElement) {\r\n return this.getFormats(domNode)\r\n }\r\n\r\n static getFormats(domNode: HTMLAnchorElement) {\r\n const formats: Record<string, string> = {}\r\n const href = this.sanitize(domNode.href)\r\n if (href) {\r\n formats.src = href\r\n }\r\n FILE_ATTRIBUTES.forEach((key) => {\r\n if (domNode.dataset[key]) {\r\n formats[key] = domNode.dataset[key]\r\n }\r\n })\r\n return formats\r\n }\r\n\r\n static sanitize(url: string) {\r\n return (sanitize(url, this.PROTOCOL_WHITELIST) && url) || ''\r\n }\r\n}\r\n\r\nexport default File\r\n"],"names":[],"mappings":";;AAIA,MAAM,QAAQ,MAAM,OAAO,aAAa;AACxC,MAAM,kBAAkB,CAAC,MAAM,SAAS,QAAQ,cAAc;AAO9D,MAAM,QAAN,MAAM,cAAa,MAAM;AAAA,EAMvB,OAAO,OAAO,OAAkB;AACxB,UAAA,OAAO,MAAM,OAAO,KAAK;AACzB,UAAA,OAAO,MAAM,OAAO;AACpB,UAAA,UAAU,CAAC,OAAO,IAAI,OAAO,IAAI,IAAI,KAAK,QAAQ,CAAC;AACpD,SAAA,UAAU,IAAI,WAAW;AACzB,SAAA,aAAa,mBAAmB,OAAO;AAC5C,UAAM,UAAU;AAChB,SAAK,YAAY,GAAG,OAAO,IAAI,MAAM,KAAK,KAAK,OAAO;AACtD,UAAM,MAAM,KAAK,SAAS,MAAM,GAAG;AACnC,QAAI,KAAK;AACP,WAAK,OAAO;AACZ,WAAK,SAAS;AAAA,IAAA;AAEA,oBAAA,QAAQ,CAAC,QAAQ;AAC3B,UAAA,MAAM,GAAG,GAAG;AACd,aAAK,QAAQ,GAAG,IAAI,MAAM,GAAG;AAAA,MAAA;AAAA,IAC/B,CACD;AACM,WAAA;AAAA,EAAA;AAAA,EAGT,OAAO,MAAM,SAA4B;AAChC,WAAA,KAAK,WAAW,OAAO;AAAA,EAAA;AAAA,EAGhC,OAAO,WAAW,SAA4B;AAC5C,UAAM,UAAkC,CAAC;AACzC,UAAM,OAAO,KAAK,SAAS,QAAQ,IAAI;AACvC,QAAI,MAAM;AACR,cAAQ,MAAM;AAAA,IAAA;AAEA,oBAAA,QAAQ,CAAC,QAAQ;AAC3B,UAAA,QAAQ,QAAQ,GAAG,GAAG;AACxB,gBAAQ,GAAG,IAAI,QAAQ,QAAQ,GAAG;AAAA,MAAA;AAAA,IACpC,CACD;AACM,WAAA;AAAA,EAAA;AAAA,EAGT,OAAO,SAAS,KAAa;AAC3B,WAAQ,SAAS,KAAK,KAAK,kBAAkB,KAAK,OAAQ;AAAA,EAAA;AAE9D;AA/CE,MAAO,WAAW;AAClB,MAAO,UAAU;AACjB,MAAO,YAAY;AACnB,MAAO,qBAAqB,CAAC,QAAQ,SAAS,MAAM;AAJtD,IAAM,OAAN;"}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import Quill from "quill";
|
|
2
2
|
import File from "./formats/file.es.js";
|
|
3
3
|
import FileBar from "./modules/file-bar.es.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Quill.register("formats/file", File, true);
|
|
8
|
-
}
|
|
9
|
-
constructor(quill, options) {
|
|
10
|
-
super(quill, options);
|
|
4
|
+
class FileModule {
|
|
5
|
+
constructor(quill) {
|
|
6
|
+
this.quill = quill;
|
|
11
7
|
this.quill = quill;
|
|
12
8
|
quill.root.addEventListener("click", (event) => this.clickEvent(event), false);
|
|
13
9
|
}
|
|
10
|
+
static register() {
|
|
11
|
+
Quill.register("formats/file", File, true);
|
|
12
|
+
}
|
|
14
13
|
clickEvent(event) {
|
|
15
14
|
event.preventDefault();
|
|
16
15
|
const target = event.target;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../../../../src/modules/file/index.ts"],"sourcesContent":["import Quill from 'quill'\r\nimport File from './formats/file'\r\nimport FileBar from './modules/file-bar'\r\n\r\
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../../../../src/modules/file/index.ts"],"sourcesContent":["import type FluentEditor from '../../core/fluent-editor'\r\nimport Quill from 'quill'\r\nimport File from './formats/file'\r\nimport FileBar from './modules/file-bar'\r\n\r\nclass FileModule {\r\n fileBar: FileBar\r\n\r\n static register() {\r\n Quill.register('formats/file', File, true)\r\n }\r\n\r\n constructor(public quill: FluentEditor) {\r\n this.quill = quill\r\n quill.root.addEventListener('click', event => this.clickEvent(event), false)\r\n }\r\n\r\n clickEvent(event: MouseEvent) {\r\n event.preventDefault()\r\n const target = event.target as HTMLElement\r\n const fileDom = target.closest('a.ql-file-item')\r\n if (fileDom) {\r\n if (this.fileBar) {\r\n this.fileBar.destroy()\r\n }\r\n this.fileBar = new FileBar(this.quill, fileDom)\r\n }\r\n else if (this.fileBar && !target.closest('.ql-file-bar')) {\r\n this.fileBar.destroy()\r\n this.fileBar = null\r\n }\r\n }\r\n}\r\n\r\nexport default FileModule\r\n"],"names":[],"mappings":";;;AAKA,MAAM,WAAW;AAAA,EAOf,YAAmB,OAAqB;AAArB,SAAA,QAAA;AACjB,SAAK,QAAQ;AACP,UAAA,KAAK,iBAAiB,SAAS,CAAA,UAAS,KAAK,WAAW,KAAK,GAAG,KAAK;AAAA,EAAA;AAAA,EAN7E,OAAO,WAAW;AACV,UAAA,SAAS,gBAAgB,MAAM,IAAI;AAAA,EAAA;AAAA,EAQ3C,WAAW,OAAmB;AAC5B,UAAM,eAAe;AACrB,UAAM,SAAS,MAAM;AACf,UAAA,UAAU,OAAO,QAAQ,gBAAgB;AAC/C,QAAI,SAAS;AACX,UAAI,KAAK,SAAS;AAChB,aAAK,QAAQ,QAAQ;AAAA,MAAA;AAEvB,WAAK,UAAU,IAAI,QAAQ,KAAK,OAAO,OAAO;AAAA,IAAA,WAEvC,KAAK,WAAW,CAAC,OAAO,QAAQ,cAAc,GAAG;AACxD,WAAK,QAAQ,QAAQ;AACrB,WAAK,UAAU;AAAA,IAAA;AAAA,EACjB;AAEJ;"}
|
package/es/modules/i18n.es.js
CHANGED
|
@@ -1,28 +1,47 @@
|
|
|
1
1
|
import "../config/index.es.js";
|
|
2
2
|
import { isUndefined } from "../utils/is.es.js";
|
|
3
|
-
import {
|
|
3
|
+
import { defaultLanguage, CHANGE_LANGUAGE_EVENT } from "../config/editor.config.es.js";
|
|
4
|
+
const langs = {};
|
|
4
5
|
class I18N {
|
|
5
6
|
constructor(quill, options) {
|
|
6
7
|
this.quill = quill;
|
|
7
|
-
this.isFullscreen = false;
|
|
8
8
|
this.options = {
|
|
9
|
-
lang: "
|
|
10
|
-
langText: LANG_CONF["en-US"]
|
|
9
|
+
lang: ""
|
|
11
10
|
};
|
|
12
11
|
this.options = Object.assign({}, options, this.resolveLanguageOption(options || {}));
|
|
13
12
|
Promise.resolve().then(() => this.changeLanguage(this.options, true));
|
|
14
13
|
}
|
|
14
|
+
static register(inputLangs, isCover = true) {
|
|
15
|
+
for (const lang in inputLangs) {
|
|
16
|
+
const texts = inputLangs[lang];
|
|
17
|
+
if (isCover) {
|
|
18
|
+
langs[lang] = texts;
|
|
19
|
+
} else {
|
|
20
|
+
if (!langs[lang]) langs[lang] = {};
|
|
21
|
+
Object.assign(langs[lang], texts);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
static parserText(text, lang) {
|
|
26
|
+
var _a;
|
|
27
|
+
const i18nPattern = /^_i18n"([^"]*)"/;
|
|
28
|
+
const match = text.match(i18nPattern);
|
|
29
|
+
let key = text;
|
|
30
|
+
if (match) {
|
|
31
|
+
key = match[1];
|
|
32
|
+
}
|
|
33
|
+
return ((_a = langs[lang]) == null ? void 0 : _a[key]) || key;
|
|
34
|
+
}
|
|
15
35
|
resolveLanguageOption(options) {
|
|
16
36
|
if (isUndefined(options.lang)) {
|
|
17
37
|
options.lang = defaultLanguage;
|
|
18
38
|
}
|
|
19
|
-
if (!(options.lang in
|
|
39
|
+
if (!(options.lang in langs)) {
|
|
20
40
|
console.warn(`The language ${options.lang} is not supported. Use the default language: ${defaultLanguage}`);
|
|
21
41
|
options.lang = defaultLanguage;
|
|
22
42
|
}
|
|
23
43
|
return {
|
|
24
|
-
lang: options.lang
|
|
25
|
-
langText: Object.assign({}, LANG_CONF[options.lang], options.langText || {})
|
|
44
|
+
lang: options.lang
|
|
26
45
|
};
|
|
27
46
|
}
|
|
28
47
|
changeLanguage(options, force = false) {
|
|
@@ -30,11 +49,11 @@ class I18N {
|
|
|
30
49
|
const langOps = this.resolveLanguageOption(options);
|
|
31
50
|
if (langOps.lang === currentLang && !force) return;
|
|
32
51
|
this.options.lang = langOps.lang;
|
|
33
|
-
this.options.
|
|
34
|
-
this.quill.emitter.emit(CHANGE_LANGUAGE_EVENT, this.options.lang, this.options.langText);
|
|
52
|
+
this.quill.emitter.emit(CHANGE_LANGUAGE_EVENT, this.options.lang, langs[langOps.lang]);
|
|
35
53
|
}
|
|
36
54
|
}
|
|
37
55
|
export {
|
|
56
|
+
I18N,
|
|
38
57
|
I18N as default
|
|
39
58
|
};
|
|
40
59
|
//# sourceMappingURL=i18n.es.js.map
|