@milkdown/plugin-upload 6.1.5 → 6.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"default-uploader.d.ts","sourceRoot":"","sources":["../src/default-uploader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAmBzC,eAAO,MAAM,eAAe,EAAE,QAwB7B,CAAC"}
1
+ {"version":3,"file":"default-uploader.d.ts","sourceRoot":"","sources":["../src/default-uploader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAmBzC,eAAO,MAAM,eAAe,EAAE,QAwB7B,CAAC"}
package/lib/index.es.js CHANGED
@@ -1,128 +1,94 @@
1
- import { createPlugin, AtomList } from "@milkdown/utils";
2
- import { schemaCtx, themeManagerCtx, ThemeIcon } from "@milkdown/core";
3
- import { PluginKey, Plugin } from "@milkdown/prose/state";
4
- import { DecorationSet, Decoration } from "@milkdown/prose/view";
5
- const readImageAsBase64 = (file) => {
6
- return new Promise((resolve) => {
7
- const reader = new FileReader();
8
- reader.addEventListener("load", () => {
9
- resolve({
10
- alt: file.name,
11
- src: reader.result
12
- });
13
- }, false);
14
- reader.readAsDataURL(file);
15
- });
16
- };
17
- const defaultUploader = async (files, schema) => {
18
- const imgs = [];
19
- for (let i = 0; i < files.length; i++) {
20
- const file = files.item(i);
21
- if (!file) {
22
- continue;
23
- }
24
- if (!file.type.includes("image")) {
25
- continue;
26
- }
27
- imgs.push(file);
1
+ import { createPlugin as I, AtomList as w } from "@milkdown/utils";
2
+ import { schemaCtx as C, themeManagerCtx as E, ThemeIcon as L } from "@milkdown/core";
3
+ import { missingNodeInSchema as M, missingIcon as S } from "@milkdown/exception";
4
+ import { PluginKey as U, Plugin as D } from "@milkdown/prose/state";
5
+ import { DecorationSet as _, Decoration as x } from "@milkdown/prose/view";
6
+ const F = (l) => new Promise((o) => {
7
+ const i = new FileReader();
8
+ i.addEventListener("load", () => {
9
+ o({
10
+ alt: l.name,
11
+ src: i.result
12
+ });
13
+ }, !1), i.readAsDataURL(l);
14
+ }), K = async (l, o) => {
15
+ const i = [];
16
+ for (let s = 0; s < l.length; s++) {
17
+ const d = l.item(s);
18
+ !d || !d.type.includes("image") || i.push(d);
28
19
  }
29
- const { image } = schema.nodes;
30
- if (!image) {
31
- throw new Error();
32
- }
33
- const data = await Promise.all(imgs.map((img) => readImageAsBase64(img)));
34
- return data.map(({ alt, src }) => image.createAndFill({ src, alt }));
35
- };
36
- const key = new PluginKey("MILKDOWN_UPLOAD");
37
- const uploadPlugin = createPlugin((_, options) => {
38
- var _a;
39
- const uploader = (_a = options == null ? void 0 : options.uploader) != null ? _a : defaultUploader;
20
+ const { image: u } = o.nodes;
21
+ if (!u)
22
+ throw M("image");
23
+ return (await Promise.all(i.map((s) => F(s)))).map(({ alt: s, src: d }) => u.createAndFill({ src: d, alt: s }));
24
+ }, N = new U("MILKDOWN_UPLOAD"), O = I((l, o) => {
25
+ var u;
26
+ const i = (u = o == null ? void 0 : o.uploader) != null ? u : K;
40
27
  return {
41
- prosePlugins: (_2, ctx) => {
42
- const schema = ctx.get(schemaCtx);
43
- const placeholderPlugin = new Plugin({
44
- key,
28
+ prosePlugins: (y, s) => {
29
+ const d = s.get(C), p = new D({
30
+ key: N,
45
31
  state: {
46
32
  init() {
47
- return DecorationSet.empty;
33
+ return _.empty;
48
34
  },
49
- apply(tr, set) {
50
- const _set = set.map(tr.mapping, tr.doc);
51
- const action = tr.getMeta(this);
52
- if (!action) {
53
- return _set;
54
- }
55
- if (action.add) {
56
- const widget = document.createElement("span");
57
- const loadingIcon = ctx.get(themeManagerCtx).get(ThemeIcon, "loading");
58
- if (!loadingIcon) {
59
- throw new Error("Loading icon is not found");
60
- }
61
- widget.appendChild(loadingIcon.dom);
62
- const decoration = Decoration.widget(action.add.pos, widget, { id: action.add.id });
63
- return _set.add(tr.doc, [decoration]);
64
- }
65
- if (action.remove) {
66
- return _set.remove(_set.find(null, null, (spec) => spec.id === action.remove.id));
35
+ apply(e, r) {
36
+ const t = r.map(e.mapping, e.doc), n = e.getMeta(this);
37
+ if (!n)
38
+ return t;
39
+ if (n.add) {
40
+ const a = document.createElement("span"), c = s.get(E).get(L, "loading");
41
+ if (!c)
42
+ throw S("loading");
43
+ a.appendChild(c.dom);
44
+ const m = x.widget(n.add.pos, a, { id: n.add.id });
45
+ return t.add(e.doc, [m]);
67
46
  }
47
+ return n.remove ? t.remove(t.find(void 0, void 0, (a) => a.id === n.remove.id)) : t;
68
48
  }
69
49
  },
70
50
  props: {
71
- decorations(state) {
72
- return this.getState(state);
51
+ decorations(e) {
52
+ return this.getState(e);
73
53
  }
74
54
  }
75
- });
76
- const findPlaceholder = (state, id) => {
77
- const decorations = placeholderPlugin.getState(state);
78
- const found = decorations.find(null, null, (spec) => spec.id === id);
79
- return found.length ? found[0].from : -1;
80
- };
81
- const handleUpload = (view, event, files) => {
82
- var _a2, _b;
83
- if (!files || files.length <= 0) {
84
- return false;
85
- }
86
- const id = Symbol("upload symbol");
87
- const { tr } = view.state;
88
- const insertPos = event instanceof DragEvent ? (_b = (_a2 = view.posAtCoords({ left: event.clientX, top: event.clientY })) == null ? void 0 : _a2.pos) != null ? _b : tr.selection.from : tr.selection.from;
89
- view.dispatch(tr.setMeta(placeholderPlugin, { add: { id, pos: insertPos } }));
90
- uploader(files, schema).then((fragment) => {
91
- const pos = findPlaceholder(view.state, id);
92
- if (pos < 0)
93
- return;
94
- view.dispatch(view.state.tr.replaceWith(pos, pos, fragment).setMeta(placeholderPlugin, { remove: { id } }));
95
- return;
96
- }).catch((e) => {
97
- console.error(e);
98
- });
99
- return true;
100
- };
101
- const uploadPlugin2 = new Plugin({
55
+ }), b = (e, r) => {
56
+ var a, c;
57
+ const t = p.getState(e);
58
+ if (!t)
59
+ return -1;
60
+ const n = t.find(void 0, void 0, (m) => m.id === r);
61
+ return n.length && (c = (a = n[0]) == null ? void 0 : a.from) != null ? c : -1;
62
+ }, h = (e, r, t) => {
63
+ var m, P;
64
+ if (!t || t.length <= 0)
65
+ return !1;
66
+ const n = Symbol("upload symbol"), { tr: a } = e.state, c = r instanceof DragEvent && (P = (m = e.posAtCoords({ left: r.clientX, top: r.clientY })) == null ? void 0 : m.pos) != null ? P : a.selection.from;
67
+ return e.dispatch(a.setMeta(p, { add: { id: n, pos: c } })), i(t, d).then((f) => {
68
+ const g = b(e.state, n);
69
+ g < 0 || e.dispatch(e.state.tr.replaceWith(g, g, f).setMeta(p, { remove: { id: n } }));
70
+ }).catch((f) => {
71
+ console.error(f);
72
+ }), !0;
73
+ }, A = new D({
102
74
  props: {
103
- handlePaste: (view, event) => {
104
- var _a2, _b;
105
- if (!(event instanceof ClipboardEvent)) {
106
- return false;
107
- }
108
- if (!(options == null ? void 0 : options.enableHtmlFileUploader) && ((_a2 = event.clipboardData) == null ? void 0 : _a2.getData("text/html"))) {
109
- return false;
110
- }
111
- return handleUpload(view, event, (_b = event.clipboardData) == null ? void 0 : _b.files);
75
+ handlePaste: (e, r) => {
76
+ var t, n;
77
+ return !(r instanceof ClipboardEvent) || !(o != null && o.enableHtmlFileUploader) && ((t = r.clipboardData) == null ? void 0 : t.getData("text/html")) ? !1 : h(e, r, (n = r.clipboardData) == null ? void 0 : n.files);
112
78
  },
113
- handleDrop: (view, event) => {
114
- var _a2;
115
- if (!(event instanceof DragEvent)) {
116
- return false;
117
- }
118
- return handleUpload(view, event, (_a2 = event.dataTransfer) == null ? void 0 : _a2.files);
79
+ handleDrop: (e, r) => {
80
+ var t;
81
+ return r instanceof DragEvent ? h(e, r, (t = r.dataTransfer) == null ? void 0 : t.files) : !1;
119
82
  }
120
83
  }
121
84
  });
122
- return [placeholderPlugin, uploadPlugin2];
85
+ return [p, A];
123
86
  }
124
87
  };
125
- });
126
- const upload = AtomList.create([uploadPlugin()]);
127
- export { key, upload, uploadPlugin };
88
+ }), H = w.create([O()]);
89
+ export {
90
+ N as key,
91
+ H as upload,
92
+ O as uploadPlugin
93
+ };
128
94
  //# sourceMappingURL=index.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/default-uploader.ts","../src/upload.ts","../src/index.ts"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nimport type { Node } from '@milkdown/prose/model';\n\nimport type { Uploader } from './upload';\n\nconst readImageAsBase64 = (file: File): Promise<{ alt: string; src: string }> => {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.addEventListener(\n 'load',\n () => {\n resolve({\n alt: file.name,\n src: reader.result as string,\n });\n },\n false,\n );\n reader.readAsDataURL(file);\n });\n};\n\nexport const defaultUploader: Uploader = async (files, schema) => {\n const imgs: File[] = [];\n\n for (let i = 0; i < files.length; i++) {\n const file = files.item(i);\n if (!file) {\n continue;\n }\n\n if (!file.type.includes('image')) {\n continue;\n }\n\n imgs.push(file);\n }\n\n const { image } = schema.nodes;\n if (!image) {\n throw new Error();\n }\n\n const data = await Promise.all(imgs.map((img) => readImageAsBase64(img)));\n\n return data.map(({ alt, src }) => image.createAndFill({ src, alt }) as Node);\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { schemaCtx, ThemeIcon, themeManagerCtx } from '@milkdown/core';\nimport { Fragment, Node, Schema } from '@milkdown/prose/model';\nimport { EditorState, Plugin, PluginKey } from '@milkdown/prose/state';\nimport { Decoration, DecorationSet, EditorView } from '@milkdown/prose/view';\nimport { createPlugin } from '@milkdown/utils';\n\nimport { defaultUploader } from './default-uploader';\n\nexport type Uploader = (files: FileList, schema: Schema) => Promise<Fragment | Node | Node[]>;\ntype Spec = { id: symbol; pos: number };\nexport type Options = {\n uploader: Uploader;\n enableHtmlFileUploader: boolean;\n};\nexport const key = new PluginKey('MILKDOWN_UPLOAD');\n\nexport const uploadPlugin = createPlugin<string, Options>((_, options) => {\n const uploader = options?.uploader ?? defaultUploader;\n\n return {\n prosePlugins: (_, ctx) => {\n const schema = ctx.get(schemaCtx);\n\n const placeholderPlugin = new Plugin({\n key,\n state: {\n init() {\n return DecorationSet.empty;\n },\n apply(tr, set) {\n const _set = set.map(tr.mapping, tr.doc);\n const action = tr.getMeta(this);\n if (!action) {\n return _set;\n }\n if (action.add) {\n const widget = document.createElement('span');\n const loadingIcon = ctx.get(themeManagerCtx).get(ThemeIcon, 'loading');\n if (!loadingIcon) {\n throw new Error('Loading icon is not found');\n }\n widget.appendChild(loadingIcon.dom);\n const decoration = Decoration.widget(action.add.pos, widget, { id: action.add.id });\n return _set.add(tr.doc, [decoration]);\n }\n if (action.remove) {\n return _set.remove(_set.find(null, null, (spec: Spec) => spec.id === action.remove.id));\n }\n },\n },\n props: {\n decorations(state) {\n return this.getState(state);\n },\n },\n });\n\n const findPlaceholder = (state: EditorState, id: symbol): number => {\n const decorations = placeholderPlugin.getState(state);\n const found = decorations.find(null, null, (spec: Spec) => spec.id === id);\n return found.length ? found[0].from : -1;\n };\n\n const handleUpload = (\n view: EditorView<Schema>,\n event: DragEvent | ClipboardEvent,\n files: FileList | undefined,\n ) => {\n if (!files || files.length <= 0) {\n return false;\n }\n const id = Symbol('upload symbol');\n const { tr } = view.state;\n const insertPos =\n event instanceof DragEvent\n ? view.posAtCoords({ left: event.clientX, top: event.clientY })?.pos ?? tr.selection.from\n : tr.selection.from;\n view.dispatch(tr.setMeta(placeholderPlugin, { add: { id, pos: insertPos } }));\n\n uploader(files, schema)\n .then((fragment) => {\n const pos = findPlaceholder(view.state, id);\n if (pos < 0) return;\n\n view.dispatch(\n view.state.tr\n .replaceWith(pos, pos, fragment)\n .setMeta(placeholderPlugin, { remove: { id } }),\n );\n return;\n })\n .catch((e) => {\n console.error(e);\n });\n return true;\n };\n\n const uploadPlugin = new Plugin({\n props: {\n handlePaste: (view, event) => {\n if (!(event instanceof ClipboardEvent)) {\n return false;\n }\n\n if (!options?.enableHtmlFileUploader && event.clipboardData?.getData('text/html')) {\n return false;\n }\n\n return handleUpload(view, event, event.clipboardData?.files);\n },\n handleDrop: (view, event) => {\n if (!(event instanceof DragEvent)) {\n return false;\n }\n\n return handleUpload(view, event, event.dataTransfer?.files);\n },\n },\n });\n return [placeholderPlugin, uploadPlugin];\n },\n };\n});\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { AtomList } from '@milkdown/utils';\n\nimport { uploadPlugin } from './upload';\n\nexport type { Uploader } from './upload';\nexport { key, uploadPlugin } from './upload';\n\nexport const upload = AtomList.create([uploadPlugin()]);\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/default-uploader.ts","../src/upload.ts","../src/index.ts"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nimport { missingNodeInSchema } from '@milkdown/exception';\nimport type { Node } from '@milkdown/prose/model';\n\nimport type { Uploader } from './upload';\n\nconst readImageAsBase64 = (file: File): Promise<{ alt: string; src: string }> => {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.addEventListener(\n 'load',\n () => {\n resolve({\n alt: file.name,\n src: reader.result as string,\n });\n },\n false,\n );\n reader.readAsDataURL(file);\n });\n};\n\nexport const defaultUploader: Uploader = async (files, schema) => {\n const imgs: File[] = [];\n\n for (let i = 0; i < files.length; i++) {\n const file = files.item(i);\n if (!file) {\n continue;\n }\n\n if (!file.type.includes('image')) {\n continue;\n }\n\n imgs.push(file);\n }\n\n const { image } = schema.nodes;\n if (!image) {\n throw missingNodeInSchema('image');\n }\n\n const data = await Promise.all(imgs.map((img) => readImageAsBase64(img)));\n\n return data.map(({ alt, src }) => image.createAndFill({ src, alt }) as Node);\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { schemaCtx, ThemeIcon, themeManagerCtx } from '@milkdown/core';\nimport { missingIcon } from '@milkdown/exception';\nimport { Fragment, Node, Schema } from '@milkdown/prose/model';\nimport { EditorState, Plugin, PluginKey } from '@milkdown/prose/state';\nimport { Decoration, DecorationSet, EditorView } from '@milkdown/prose/view';\nimport { createPlugin } from '@milkdown/utils';\n\nimport { defaultUploader } from './default-uploader';\n\nexport type Uploader = (files: FileList, schema: Schema) => Promise<Fragment | Node | Node[]>;\ntype Spec = { id: symbol; pos: number };\nexport type Options = {\n uploader: Uploader;\n enableHtmlFileUploader: boolean;\n};\nexport const key = new PluginKey('MILKDOWN_UPLOAD');\n\nexport const uploadPlugin = createPlugin<string, Options>((_, options) => {\n const uploader = options?.uploader ?? defaultUploader;\n\n return {\n prosePlugins: (_, ctx) => {\n const schema = ctx.get(schemaCtx);\n\n const placeholderPlugin = new Plugin({\n key,\n state: {\n init() {\n return DecorationSet.empty;\n },\n apply(this: Plugin, tr, set) {\n const _set = set.map(tr.mapping, tr.doc);\n const action = tr.getMeta(this);\n if (!action) {\n return _set;\n }\n if (action.add) {\n const widget = document.createElement('span');\n const loadingIcon = ctx.get(themeManagerCtx).get(ThemeIcon, 'loading');\n if (!loadingIcon) {\n throw missingIcon('loading');\n }\n widget.appendChild(loadingIcon.dom);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const decoration = Decoration.widget(action.add.pos, widget, { id: action.add.id } as any);\n return _set.add(tr.doc, [decoration]);\n }\n if (action.remove) {\n return _set.remove(\n _set.find(undefined, undefined, (spec: Spec) => spec.id === action.remove.id),\n );\n }\n\n return _set;\n },\n },\n props: {\n decorations(this: Plugin, state) {\n return this.getState(state);\n },\n },\n });\n\n const findPlaceholder = (state: EditorState, id: symbol): number => {\n const decorations = placeholderPlugin.getState(state);\n if (!decorations) return -1;\n const found = decorations.find(undefined, undefined, (spec: Spec) => spec.id === id);\n if (!found.length) return -1;\n return found[0]?.from ?? -1;\n };\n\n const handleUpload = (view: EditorView, event: DragEvent | ClipboardEvent, files: FileList | undefined) => {\n if (!files || files.length <= 0) {\n return false;\n }\n const id = Symbol('upload symbol');\n const { tr } = view.state;\n const insertPos =\n event instanceof DragEvent\n ? view.posAtCoords({ left: event.clientX, top: event.clientY })?.pos ?? tr.selection.from\n : tr.selection.from;\n view.dispatch(tr.setMeta(placeholderPlugin, { add: { id, pos: insertPos } }));\n\n uploader(files, schema)\n .then((fragment) => {\n const pos = findPlaceholder(view.state, id);\n if (pos < 0) return;\n\n view.dispatch(\n view.state.tr\n .replaceWith(pos, pos, fragment)\n .setMeta(placeholderPlugin, { remove: { id } }),\n );\n return;\n })\n .catch((e) => {\n console.error(e);\n });\n return true;\n };\n\n const uploadPlugin = new Plugin({\n props: {\n handlePaste: (view, event) => {\n if (!(event instanceof ClipboardEvent)) {\n return false;\n }\n\n if (!options?.enableHtmlFileUploader && event.clipboardData?.getData('text/html')) {\n return false;\n }\n\n return handleUpload(view, event, event.clipboardData?.files);\n },\n handleDrop: (view, event) => {\n if (!(event instanceof DragEvent)) {\n return false;\n }\n\n return handleUpload(view, event, event.dataTransfer?.files);\n },\n },\n });\n return [placeholderPlugin, uploadPlugin];\n },\n };\n});\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { AtomList } from '@milkdown/utils';\n\nimport { uploadPlugin } from './upload';\n\nexport type { Uploader } from './upload';\nexport { key, uploadPlugin } from './upload';\n\nexport const upload = AtomList.create([uploadPlugin()]);\n"],"names":[],"mappings":"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"}
package/lib/upload.d.ts CHANGED
@@ -5,20 +5,6 @@ export declare type Options = {
5
5
  uploader: Uploader;
6
6
  enableHtmlFileUploader: boolean;
7
7
  };
8
- export declare const key: PluginKey<any, any>;
9
- export declare const uploadPlugin: import("@milkdown/utils").WithExtend<string, Options, {
10
- [x: string]: import("@milkdown/prose/model").NodeType<any>;
11
- } & {
12
- [x: string]: import("@milkdown/prose/model").MarkType<any>;
13
- }, {
14
- schema?: ((ctx: import("@milkdown/core").Ctx) => {
15
- node?: Record<string, import("@milkdown/core").NodeSchema> | undefined;
16
- mark?: Record<string, import("@milkdown/core").MarkSchema> | undefined;
17
- }) | undefined;
18
- view?: ((ctx: import("@milkdown/core").Ctx) => Partial<{
19
- [x: string]: import("@milkdown/prose").NodeViewFactory;
20
- } & {
21
- [x: string]: import("@milkdown/prose").MarkViewFactory;
22
- }>) | undefined;
23
- }>;
8
+ export declare const key: PluginKey<any>;
9
+ export declare const uploadPlugin: import("@milkdown/utils").WithExtend<string, Options, import("@milkdown/utils").TypeMapping<string, string>, import("@milkdown/utils").PluginRest<string, string>>;
24
10
  //# sourceMappingURL=upload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAuB,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAMvE,oBAAY,QAAQ,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;AAE9F,oBAAY,OAAO,GAAG;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,sBAAsB,EAAE,OAAO,CAAC;CACnC,CAAC;AACF,eAAO,MAAM,GAAG,qBAAmC,CAAC;AAEpD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;EA0GvB,CAAC"}
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAuB,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAMvE,oBAAY,QAAQ,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;AAE9F,oBAAY,OAAO,GAAG;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,sBAAsB,EAAE,OAAO,CAAC;CACnC,CAAC;AACF,eAAO,MAAM,GAAG,gBAAmC,CAAC;AAEpD,eAAO,MAAM,YAAY,oKA6GvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milkdown/plugin-upload",
3
- "version": "6.1.5",
3
+ "version": "6.3.1",
4
4
  "type": "module",
5
5
  "main": "./lib/index.es.js",
6
6
  "types": "./lib/index.d.ts",
@@ -15,16 +15,17 @@
15
15
  "milkdown plugin"
16
16
  ],
17
17
  "devDependencies": {
18
- "@milkdown/core": "6.1.5",
19
- "@milkdown/prose": "6.1.5"
18
+ "@milkdown/core": "6.3.1",
19
+ "@milkdown/prose": "6.3.1"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "@milkdown/core": "^6.0.1",
23
23
  "@milkdown/prose": "^6.0.1"
24
24
  },
25
25
  "dependencies": {
26
- "@milkdown/utils": "6.1.5",
27
- "tslib": "^2.3.1"
26
+ "@milkdown/utils": "6.3.1",
27
+ "@milkdown/exception": "6.3.1",
28
+ "tslib": "^2.4.0"
28
29
  },
29
30
  "nx": {
30
31
  "targets": {
@@ -1,4 +1,5 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
+ import { missingNodeInSchema } from '@milkdown/exception';
2
3
  import type { Node } from '@milkdown/prose/model';
3
4
 
4
5
  import type { Uploader } from './upload';
@@ -38,7 +39,7 @@ export const defaultUploader: Uploader = async (files, schema) => {
38
39
 
39
40
  const { image } = schema.nodes;
40
41
  if (!image) {
41
- throw new Error();
42
+ throw missingNodeInSchema('image');
42
43
  }
43
44
 
44
45
  const data = await Promise.all(imgs.map((img) => readImageAsBase64(img)));
package/src/upload.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
2
  import { schemaCtx, ThemeIcon, themeManagerCtx } from '@milkdown/core';
3
+ import { missingIcon } from '@milkdown/exception';
3
4
  import { Fragment, Node, Schema } from '@milkdown/prose/model';
4
5
  import { EditorState, Plugin, PluginKey } from '@milkdown/prose/state';
5
6
  import { Decoration, DecorationSet, EditorView } from '@milkdown/prose/view';
@@ -28,7 +29,7 @@ export const uploadPlugin = createPlugin<string, Options>((_, options) => {
28
29
  init() {
29
30
  return DecorationSet.empty;
30
31
  },
31
- apply(tr, set) {
32
+ apply(this: Plugin, tr, set) {
32
33
  const _set = set.map(tr.mapping, tr.doc);
33
34
  const action = tr.getMeta(this);
34
35
  if (!action) {
@@ -38,19 +39,24 @@ export const uploadPlugin = createPlugin<string, Options>((_, options) => {
38
39
  const widget = document.createElement('span');
39
40
  const loadingIcon = ctx.get(themeManagerCtx).get(ThemeIcon, 'loading');
40
41
  if (!loadingIcon) {
41
- throw new Error('Loading icon is not found');
42
+ throw missingIcon('loading');
42
43
  }
43
44
  widget.appendChild(loadingIcon.dom);
44
- const decoration = Decoration.widget(action.add.pos, widget, { id: action.add.id });
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ const decoration = Decoration.widget(action.add.pos, widget, { id: action.add.id } as any);
45
47
  return _set.add(tr.doc, [decoration]);
46
48
  }
47
49
  if (action.remove) {
48
- return _set.remove(_set.find(null, null, (spec: Spec) => spec.id === action.remove.id));
50
+ return _set.remove(
51
+ _set.find(undefined, undefined, (spec: Spec) => spec.id === action.remove.id),
52
+ );
49
53
  }
54
+
55
+ return _set;
50
56
  },
51
57
  },
52
58
  props: {
53
- decorations(state) {
59
+ decorations(this: Plugin, state) {
54
60
  return this.getState(state);
55
61
  },
56
62
  },
@@ -58,15 +64,13 @@ export const uploadPlugin = createPlugin<string, Options>((_, options) => {
58
64
 
59
65
  const findPlaceholder = (state: EditorState, id: symbol): number => {
60
66
  const decorations = placeholderPlugin.getState(state);
61
- const found = decorations.find(null, null, (spec: Spec) => spec.id === id);
62
- return found.length ? found[0].from : -1;
67
+ if (!decorations) return -1;
68
+ const found = decorations.find(undefined, undefined, (spec: Spec) => spec.id === id);
69
+ if (!found.length) return -1;
70
+ return found[0]?.from ?? -1;
63
71
  };
64
72
 
65
- const handleUpload = (
66
- view: EditorView<Schema>,
67
- event: DragEvent | ClipboardEvent,
68
- files: FileList | undefined,
69
- ) => {
73
+ const handleUpload = (view: EditorView, event: DragEvent | ClipboardEvent, files: FileList | undefined) => {
70
74
  if (!files || files.length <= 0) {
71
75
  return false;
72
76
  }