@jvs-milkdown/components 1.1.5 → 1.1.6

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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/lib/__internal__/components/image-input.d.ts.map +1 -1
  3. package/lib/image-block/convert-plugin.d.ts +2 -0
  4. package/lib/image-block/convert-plugin.d.ts.map +1 -0
  5. package/lib/image-block/index.d.ts +2 -0
  6. package/lib/image-block/index.d.ts.map +1 -1
  7. package/lib/image-block/index.js +345 -75
  8. package/lib/image-block/index.js.map +1 -1
  9. package/lib/image-block/paste-rule.d.ts +2 -0
  10. package/lib/image-block/paste-rule.d.ts.map +1 -0
  11. package/lib/image-block/schema.d.ts.map +1 -1
  12. package/lib/image-block/view/components/image-block.d.ts +1 -0
  13. package/lib/image-block/view/components/image-block.d.ts.map +1 -1
  14. package/lib/image-block/view/components/image-viewer.d.ts.map +1 -1
  15. package/lib/image-block/view/index.d.ts.map +1 -1
  16. package/lib/image-inline/index.js +27 -6
  17. package/lib/image-inline/index.js.map +1 -1
  18. package/lib/link-tooltip/edit/component.d.ts.map +1 -1
  19. package/lib/link-tooltip/index.js +18 -4
  20. package/lib/link-tooltip/index.js.map +1 -1
  21. package/lib/table-block/dnd/drag-over-handler.d.ts.map +1 -1
  22. package/lib/table-block/index.js +139 -53
  23. package/lib/table-block/index.js.map +1 -1
  24. package/lib/table-block/view/component.d.ts.map +1 -1
  25. package/lib/table-block/view/drag.d.ts +3 -0
  26. package/lib/table-block/view/drag.d.ts.map +1 -1
  27. package/lib/table-block/view/utils.d.ts.map +1 -1
  28. package/lib/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +53 -79
  30. package/src/__internal__/components/image-input.tsx +45 -12
  31. package/src/image-block/__tests__/paste-rule.spec.ts +20 -0
  32. package/src/image-block/convert-plugin.ts +147 -0
  33. package/src/image-block/index.ts +6 -0
  34. package/src/image-block/paste-rule.ts +138 -0
  35. package/src/image-block/schema.ts +15 -0
  36. package/src/image-block/view/components/image-block.tsx +5 -0
  37. package/src/image-block/view/components/image-viewer.tsx +4 -0
  38. package/src/image-block/view/index.ts +8 -0
  39. package/src/link-tooltip/edit/component.tsx +27 -3
  40. package/src/table-block/dnd/create-drag-handler.ts +5 -1
  41. package/src/table-block/dnd/drag-over-handler.ts +29 -1
  42. package/src/table-block/dnd/preview.ts +3 -3
  43. package/src/table-block/view/component.tsx +121 -39
  44. package/src/table-block/view/drag.ts +29 -16
  45. package/src/table-block/view/utils.ts +6 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020-present Mirone
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1 +1 @@
1
- {"version":3,"file":"image-input.d.ts","sourceRoot":"","sources":["../../../src/__internal__/components/image-input.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AASvD,KAAK,eAAe,GAAG;IACrB,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC5B,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAE/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAE9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACzC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1D,CAAA;AAED,eAAO,MAAM,UAAU,0SAyJrB,CAAA"}
1
+ {"version":3,"file":"image-input.d.ts","sourceRoot":"","sources":["../../../src/__internal__/components/image-input.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AASvD,KAAK,eAAe,GAAG;IACrB,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC5B,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAE/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAE9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACzC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1D,CAAA;AAED,eAAO,MAAM,UAAU,0SA0LrB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const imageBlockConvertPlugin: import("@jvs-milkdown/utils").$Prose;
2
+ //# sourceMappingURL=convert-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert-plugin.d.ts","sourceRoot":"","sources":["../../src/image-block/convert-plugin.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,uBAAuB,sCAmIlC,CAAA"}
@@ -3,5 +3,7 @@ export * from './schema';
3
3
  export * from './remark-plugin';
4
4
  export * from './config';
5
5
  export * from './view';
6
+ export * from './paste-rule';
7
+ export * from './convert-plugin';
6
8
  export declare const imageBlockComponent: MilkdownPlugin[];
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/image-block/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAOvD,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,UAAU,CAAA;AACxB,cAAc,QAAQ,CAAA;AAEtB,eAAO,MAAM,mBAAmB,EAAE,cAAc,EAKxC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/image-block/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AASvD,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,UAAU,CAAA;AACxB,cAAc,QAAQ,CAAA;AACtB,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAEhC,eAAO,MAAM,mBAAmB,EAAE,cAAc,EAOxC,CAAA"}
@@ -1,30 +1,33 @@
1
- import { $ctx, $remark, $nodeSchema, $view } from '@jvs-milkdown/utils';
2
- import { visit } from 'unist-util-visit';
1
+ import { $ctx, $nodeSchema, $prose, $pasteRule, $remark, $view } from '@jvs-milkdown/utils';
2
+ import { imageSchema, paragraphSchema } from '@jvs-milkdown/preset-commonmark';
3
+ import { PluginKey, Plugin } from '@jvs-milkdown/prose/state';
3
4
  import { expectDomTypeError } from '@jvs-milkdown/exception';
5
+ import { Slice, Fragment as Fragment$1 } from '@jvs-milkdown/prose/model';
6
+ import { visit } from 'unist-util-visit';
4
7
  import DOMPurify from 'dompurify';
5
- import { h, defineComponent, ref, Fragment as Fragment$1, createApp, watchEffect } from 'vue';
8
+ import { h, defineComponent, ref, Fragment as Fragment$2, createApp, watchEffect } from 'vue';
6
9
  import clsx from 'clsx';
7
10
  import { customAlphabet } from 'nanoid';
8
11
 
9
- var __defProp$2 = Object.defineProperty;
10
- var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
11
- var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
12
- var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
13
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
- var __spreadValues$2 = (a, b) => {
12
+ var __defProp$3 = Object.defineProperty;
13
+ var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols;
14
+ var __hasOwnProp$3 = Object.prototype.hasOwnProperty;
15
+ var __propIsEnum$3 = Object.prototype.propertyIsEnumerable;
16
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17
+ var __spreadValues$3 = (a, b) => {
15
18
  for (var prop in b || (b = {}))
16
- if (__hasOwnProp$2.call(b, prop))
17
- __defNormalProp$2(a, prop, b[prop]);
18
- if (__getOwnPropSymbols$2)
19
- for (var prop of __getOwnPropSymbols$2(b)) {
20
- if (__propIsEnum$2.call(b, prop))
21
- __defNormalProp$2(a, prop, b[prop]);
19
+ if (__hasOwnProp$3.call(b, prop))
20
+ __defNormalProp$3(a, prop, b[prop]);
21
+ if (__getOwnPropSymbols$3)
22
+ for (var prop of __getOwnPropSymbols$3(b)) {
23
+ if (__propIsEnum$3.call(b, prop))
24
+ __defNormalProp$3(a, prop, b[prop]);
22
25
  }
23
26
  return a;
24
27
  };
25
28
  function withMeta(plugin, meta) {
26
29
  Object.assign(plugin, {
27
- meta: __spreadValues$2({
30
+ meta: __spreadValues$3({
28
31
  package: "@jvs-milkdown/components"
29
32
  }, meta)
30
33
  });
@@ -49,52 +52,19 @@ withMeta(imageBlockConfig, {
49
52
  group: "ImageBlock"
50
53
  });
51
54
 
52
- function visitImage(ast) {
53
- return visit(
54
- ast,
55
- "paragraph",
56
- (node, index, parent) => {
57
- var _a, _b;
58
- if (((_a = node.children) == null ? void 0 : _a.length) !== 1) return;
59
- const firstChild = (_b = node.children) == null ? void 0 : _b[0];
60
- if (!firstChild || firstChild.type !== "image") return;
61
- const { url, alt, title } = firstChild;
62
- const newNode = {
63
- type: "image-block",
64
- url,
65
- alt,
66
- title
67
- };
68
- parent.children.splice(index, 1, newNode);
69
- }
70
- );
71
- }
72
- const remarkImageBlockPlugin = $remark(
73
- "remark-image-block",
74
- () => () => visitImage
75
- );
76
- withMeta(remarkImageBlockPlugin.plugin, {
77
- displayName: "Remark<remarkImageBlock>",
78
- group: "ImageBlock"
79
- });
80
- withMeta(remarkImageBlockPlugin.options, {
81
- displayName: "RemarkConfig<remarkImageBlock>",
82
- group: "ImageBlock"
83
- });
84
-
85
- var __defProp$1 = Object.defineProperty;
86
- var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
87
- var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
88
- var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
89
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
90
- var __spreadValues$1 = (a, b) => {
55
+ var __defProp$2 = Object.defineProperty;
56
+ var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
57
+ var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
58
+ var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
59
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
60
+ var __spreadValues$2 = (a, b) => {
91
61
  for (var prop in b || (b = {}))
92
- if (__hasOwnProp$1.call(b, prop))
93
- __defNormalProp$1(a, prop, b[prop]);
94
- if (__getOwnPropSymbols$1)
95
- for (var prop of __getOwnPropSymbols$1(b)) {
96
- if (__propIsEnum$1.call(b, prop))
97
- __defNormalProp$1(a, prop, b[prop]);
62
+ if (__hasOwnProp$2.call(b, prop))
63
+ __defNormalProp$2(a, prop, b[prop]);
64
+ if (__getOwnPropSymbols$2)
65
+ for (var prop of __getOwnPropSymbols$2(b)) {
66
+ if (__propIsEnum$2.call(b, prop))
67
+ __defNormalProp$2(a, prop, b[prop]);
98
68
  }
99
69
  return a;
100
70
  };
@@ -112,7 +82,8 @@ const imageBlockSchema = $nodeSchema("image-block", () => {
112
82
  attrs: {
113
83
  src: { default: "", validate: "string" },
114
84
  caption: { default: "", validate: "string" },
115
- ratio: { default: 1, validate: "number" }
85
+ ratio: { default: 1, validate: "number" },
86
+ align: { default: null }
116
87
  },
117
88
  parseDOM: [
118
89
  {
@@ -123,12 +94,25 @@ const imageBlockSchema = $nodeSchema("image-block", () => {
123
94
  return {
124
95
  src: dom.getAttribute("src") || "",
125
96
  caption: dom.getAttribute("caption") || "",
126
- ratio: Number((_a = dom.getAttribute("ratio")) != null ? _a : 1)
97
+ ratio: Number((_a = dom.getAttribute("ratio")) != null ? _a : 1),
98
+ align: dom.getAttribute("align") || null
99
+ };
100
+ }
101
+ },
102
+ {
103
+ tag: "img[src]",
104
+ getAttrs: (dom) => {
105
+ if (!(dom instanceof HTMLElement)) throw expectDomTypeError(dom);
106
+ if (dom.getAttribute("data-type") === IMAGE_DATA_TYPE) return false;
107
+ return {
108
+ src: dom.getAttribute("src") || "",
109
+ caption: dom.getAttribute("alt") || dom.getAttribute("title") || "",
110
+ ratio: 1
127
111
  };
128
112
  }
129
113
  }
130
114
  ],
131
- toDOM: (node) => ["img", __spreadValues$1({ "data-type": IMAGE_DATA_TYPE }, node.attrs)],
115
+ toDOM: (node) => ["img", __spreadValues$2({ "data-type": IMAGE_DATA_TYPE }, node.attrs)],
132
116
  parseMarkdown: {
133
117
  match: ({ type }) => type === "image-block",
134
118
  runner: (state, node, type) => {
@@ -162,6 +146,253 @@ withMeta(imageBlockSchema.node, {
162
146
  group: "ImageBlock"
163
147
  });
164
148
 
149
+ var __defProp$1 = Object.defineProperty;
150
+ var __defProps = Object.defineProperties;
151
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
152
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
153
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
154
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
155
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
156
+ var __spreadValues$1 = (a, b) => {
157
+ for (var prop in b || (b = {}))
158
+ if (__hasOwnProp$1.call(b, prop))
159
+ __defNormalProp$1(a, prop, b[prop]);
160
+ if (__getOwnPropSymbols$1)
161
+ for (var prop of __getOwnPropSymbols$1(b)) {
162
+ if (__propIsEnum$1.call(b, prop))
163
+ __defNormalProp$1(a, prop, b[prop]);
164
+ }
165
+ return a;
166
+ };
167
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
168
+ var __async = (__this, __arguments, generator) => {
169
+ return new Promise((resolve, reject) => {
170
+ var fulfilled = (value) => {
171
+ try {
172
+ step(generator.next(value));
173
+ } catch (e) {
174
+ reject(e);
175
+ }
176
+ };
177
+ var rejected = (value) => {
178
+ try {
179
+ step(generator.throw(value));
180
+ } catch (e) {
181
+ reject(e);
182
+ }
183
+ };
184
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
185
+ step((generator = generator.apply(__this, __arguments)).next());
186
+ });
187
+ };
188
+ const imageBlockConvertPlugin = $prose((ctx) => {
189
+ const imageType = imageSchema.type(ctx);
190
+ const imageBlockType = imageBlockSchema.type(ctx);
191
+ const paragraphType = paragraphSchema.type(ctx);
192
+ const pluginKey = new PluginKey("MILKDOWN_IMAGE_BLOCK_CONVERT");
193
+ let uploading = false;
194
+ return new Plugin({
195
+ key: pluginKey,
196
+ appendTransaction(transactions, _oldState, newState) {
197
+ if (!transactions.some((tr2) => tr2.docChanged)) return null;
198
+ const replacements = [];
199
+ newState.doc.descendants((node, pos) => {
200
+ if (node.type === imageType) ;
201
+ });
202
+ newState.doc.descendants((node, pos) => {
203
+ var _a;
204
+ if (node.type !== paragraphType) return;
205
+ const images = [];
206
+ let hasOtherContent = false;
207
+ for (let i = 0; i < node.childCount; i++) {
208
+ const child = node.child(i);
209
+ if (child.type === imageType) {
210
+ images.push(child);
211
+ } else if (child.type.name === "hardbreak") {
212
+ continue;
213
+ } else if (child.isText && ((_a = child.text) == null ? void 0 : _a.trim()) === "") {
214
+ continue;
215
+ } else {
216
+ hasOtherContent = true;
217
+ break;
218
+ }
219
+ }
220
+ if (hasOtherContent || images.length === 0) return;
221
+ const blocks = images.map(
222
+ (img) => imageBlockType.create({
223
+ src: img.attrs.src,
224
+ caption: img.attrs.alt || img.attrs.title || "",
225
+ ratio: 1
226
+ })
227
+ ).filter(Boolean);
228
+ if (blocks.length > 0) {
229
+ replacements.push({ from: pos, to: pos + node.nodeSize, blocks });
230
+ }
231
+ });
232
+ if (replacements.length === 0) return null;
233
+ const { tr } = newState;
234
+ for (let i = replacements.length - 1; i >= 0; i--) {
235
+ const r = replacements[i];
236
+ tr.replaceWith(r.from, r.to, r.blocks);
237
+ }
238
+ return tr;
239
+ },
240
+ view() {
241
+ return {
242
+ update(view) {
243
+ if (uploading) return;
244
+ const config = ctx.get(imageBlockConfig.key);
245
+ const imagesToUpload = [];
246
+ view.state.doc.descendants((node, pos) => {
247
+ if (node.type.name !== "image-block") return;
248
+ const src = node.attrs.src;
249
+ if (!src || src.startsWith("data:") || src.startsWith("blob:"))
250
+ return;
251
+ if (!/^https?:\/\//i.test(src)) return;
252
+ imagesToUpload.push({ pos, src });
253
+ });
254
+ if (imagesToUpload.length === 0) return;
255
+ uploading = true;
256
+ void Promise.allSettled(
257
+ imagesToUpload.map((_0) => __async(null, [_0], function* ({ pos, src }) {
258
+ const resp = yield fetch(src);
259
+ const blob = yield resp.blob();
260
+ const ext = blob.type.split("/")[1] || "png";
261
+ const file = new File([blob], `pasted-image.${ext}`, {
262
+ type: blob.type
263
+ });
264
+ const uploadedUrl = yield config.onUpload(file);
265
+ const $pos = view.state.doc.resolve(pos);
266
+ const nodeAtPos = $pos.nodeAfter;
267
+ if (nodeAtPos && nodeAtPos.type.name === "image-block" && nodeAtPos.attrs.src === src) {
268
+ view.dispatch(
269
+ view.state.tr.setNodeMarkup(pos, void 0, __spreadProps(__spreadValues$1({}, nodeAtPos.attrs), {
270
+ src: uploadedUrl
271
+ })).setMeta(pluginKey, { uploaded: true })
272
+ );
273
+ }
274
+ }))
275
+ ).finally(() => {
276
+ uploading = false;
277
+ });
278
+ }
279
+ };
280
+ }
281
+ });
282
+ });
283
+ withMeta(imageBlockConvertPlugin, {
284
+ displayName: "Prose<image-block-convert>",
285
+ group: "ImageBlock"
286
+ });
287
+
288
+ function toImageBlock(imageNode, imageBlockType) {
289
+ return imageBlockType.create({
290
+ src: imageNode.attrs.src,
291
+ caption: imageNode.attrs.alt || imageNode.attrs.title || "",
292
+ ratio: 1
293
+ });
294
+ }
295
+ const imageBlockPasteRule = $pasteRule((ctx) => ({
296
+ priority: 90,
297
+ run: (slice, _view, isPlainText) => {
298
+ if (isPlainText) return slice;
299
+ const paragraphType = paragraphSchema.type(ctx);
300
+ const imageType = imageSchema.type(ctx);
301
+ const imageBlockType = imageBlockSchema.type(ctx);
302
+ function convertFragment(fragment2) {
303
+ const nodes = [];
304
+ let changed = false;
305
+ fragment2.forEach((node) => {
306
+ if (node.type === imageType) {
307
+ const imageBlock = toImageBlock(node, imageBlockType);
308
+ if (imageBlock) {
309
+ nodes.push(imageBlock);
310
+ changed = true;
311
+ return;
312
+ }
313
+ }
314
+ if (node.type === paragraphType) {
315
+ let hasImage = false;
316
+ node.content.forEach((child) => {
317
+ if (child.type === imageType) hasImage = true;
318
+ });
319
+ if (hasImage) {
320
+ let currentParaNodes = [];
321
+ let isFirstInsideParent = nodes.length === 0;
322
+ node.content.forEach((child) => {
323
+ if (child.type === imageType) {
324
+ if (currentParaNodes.length > 0 || isFirstInsideParent) {
325
+ nodes.push(node.copy(Fragment$1.from(currentParaNodes)));
326
+ currentParaNodes = [];
327
+ }
328
+ const imageBlock = toImageBlock(child, imageBlockType);
329
+ if (imageBlock) {
330
+ nodes.push(imageBlock);
331
+ }
332
+ isFirstInsideParent = false;
333
+ } else {
334
+ currentParaNodes.push(child);
335
+ }
336
+ });
337
+ nodes.push(node.copy(Fragment$1.from(currentParaNodes)));
338
+ changed = true;
339
+ return;
340
+ }
341
+ }
342
+ if (node.content.size > 0) {
343
+ const fixedContent = convertFragment(node.content);
344
+ if (fixedContent !== node.content) {
345
+ changed = true;
346
+ nodes.push(node.copy(fixedContent));
347
+ return;
348
+ }
349
+ }
350
+ nodes.push(node);
351
+ });
352
+ return changed ? Fragment$1.from(nodes) : fragment2;
353
+ }
354
+ const fragment = convertFragment(slice.content);
355
+ return new Slice(fragment, slice.openStart, slice.openEnd);
356
+ }
357
+ }));
358
+ withMeta(imageBlockPasteRule, {
359
+ displayName: "PasteRule<image-block>",
360
+ group: "ImageBlock"
361
+ });
362
+
363
+ function visitImage(ast) {
364
+ return visit(
365
+ ast,
366
+ "paragraph",
367
+ (node, index, parent) => {
368
+ var _a, _b;
369
+ if (((_a = node.children) == null ? void 0 : _a.length) !== 1) return;
370
+ const firstChild = (_b = node.children) == null ? void 0 : _b[0];
371
+ if (!firstChild || firstChild.type !== "image") return;
372
+ const { url, alt, title } = firstChild;
373
+ const newNode = {
374
+ type: "image-block",
375
+ url,
376
+ alt,
377
+ title
378
+ };
379
+ parent.children.splice(index, 1, newNode);
380
+ }
381
+ );
382
+ }
383
+ const remarkImageBlockPlugin = $remark(
384
+ "remark-image-block",
385
+ () => () => visitImage
386
+ );
387
+ withMeta(remarkImageBlockPlugin.plugin, {
388
+ displayName: "Remark<remarkImageBlock>",
389
+ group: "ImageBlock"
390
+ });
391
+ withMeta(remarkImageBlockPlugin.options, {
392
+ displayName: "RemarkConfig<remarkImageBlock>",
393
+ group: "ImageBlock"
394
+ });
395
+
165
396
  function keepAlive(..._args) {
166
397
  }
167
398
 
@@ -260,15 +491,28 @@ const ImageInput = defineComponent({
260
491
  hidePlaceholder.value = value.length !== 0;
261
492
  currentLink.value = value;
262
493
  };
494
+ const isValidUrl = (url) => {
495
+ if (!url) return false;
496
+ const trimmedUrl = url.trim();
497
+ return /^(https?:\/\/|\/|\.\.?\/|data:image\/|blob:|[a-zA-Z0-9-]+\.[a-zA-Z]+)/i.test(trimmedUrl);
498
+ };
263
499
  const onKeydown = (e) => {
264
- var _a2, _b2;
500
+ var _a2, _b2, _c;
265
501
  if (e.key === "Enter") {
266
- setLink((_b2 = (_a2 = linkInputRef.value) == null ? void 0 : _a2.value) != null ? _b2 : "");
502
+ const val = (_c = (_b2 = (_a2 = linkInputRef.value) == null ? void 0 : _a2.value) == null ? void 0 : _b2.trim()) != null ? _c : "";
503
+ e.preventDefault();
504
+ e.stopPropagation();
505
+ if (isValidUrl(val)) {
506
+ setLink(val);
507
+ }
267
508
  }
268
509
  };
269
510
  const onConfirmLinkInput = () => {
270
- var _a2, _b2;
271
- setLink((_b2 = (_a2 = linkInputRef.value) == null ? void 0 : _a2.value) != null ? _b2 : "");
511
+ var _a2, _b2, _c;
512
+ const val = (_c = (_b2 = (_a2 = linkInputRef.value) == null ? void 0 : _a2.value) == null ? void 0 : _b2.trim()) != null ? _c : "";
513
+ if (isValidUrl(val)) {
514
+ setLink(val);
515
+ }
272
516
  };
273
517
  const onUploadFile = (e) => {
274
518
  var _a2;
@@ -314,7 +558,7 @@ const ImageInput = defineComponent({
314
558
  ), /* @__PURE__ */ h("label", { class: "uploader", for: uuid.value }, /* @__PURE__ */ h(Icon, { icon: uploadButton })), /* @__PURE__ */ h("span", { class: "text", onClick: () => {
315
559
  var _a2;
316
560
  return (_a2 = linkInputRef.value) == null ? void 0 : _a2.focus();
317
- } }, uploadPlaceholderText))), currentLink.value && /* @__PURE__ */ h(Fragment, null, /* @__PURE__ */ h("div", { class: "image-preview" }, /* @__PURE__ */ h(
561
+ } }, uploadPlaceholderText))), currentLink.value && /* @__PURE__ */ h(Fragment, null, isValidUrl(currentLink.value) && /* @__PURE__ */ h("div", { class: "image-preview" }, /* @__PURE__ */ h(
318
562
  "img",
319
563
  {
320
564
  src: currentLink.value,
@@ -322,12 +566,20 @@ const ImageInput = defineComponent({
322
566
  onError: (e) => Promise.resolve(onImageLoadError == null ? void 0 : onImageLoadError(e)).catch(() => {
323
567
  })
324
568
  }
325
- )), /* @__PURE__ */ h("div", { class: "confirm", onClick: () => onConfirmLinkInput() }, /* @__PURE__ */ h(Icon, { icon: confirmButton }))));
569
+ )), /* @__PURE__ */ h(
570
+ "div",
571
+ {
572
+ class: clsx("confirm", !isValidUrl(currentLink.value) && "disabled"),
573
+ onClick: () => onConfirmLinkInput(),
574
+ style: !isValidUrl(currentLink.value) ? { opacity: 0.5, cursor: "not-allowed" } : void 0
575
+ },
576
+ /* @__PURE__ */ h(Icon, { icon: confirmButton })
577
+ )));
326
578
  };
327
579
  }
328
580
  });
329
581
 
330
- keepAlive(h, Fragment$1);
582
+ keepAlive(h, Fragment$2);
331
583
  const ImageViewer = defineComponent({
332
584
  props: {
333
585
  src: {
@@ -342,6 +594,10 @@ const ImageViewer = defineComponent({
342
594
  type: Object,
343
595
  required: true
344
596
  },
597
+ align: {
598
+ type: Object,
599
+ required: true
600
+ },
345
601
  selected: {
346
602
  type: Object,
347
603
  required: true
@@ -465,7 +721,7 @@ const ImageViewer = defineComponent({
465
721
  window.addEventListener("pointerup", onResizeHandlePointerUp);
466
722
  };
467
723
  return () => {
468
- return /* @__PURE__ */ h(Fragment$1, null, /* @__PURE__ */ h("div", { class: "image-wrapper" }, /* @__PURE__ */ h("div", { class: "operation" }, /* @__PURE__ */ h("div", { class: "operation-item", onPointerdown: onToggleCaption }, /* @__PURE__ */ h(Icon, { icon: config.captionIcon }))), /* @__PURE__ */ h(
724
+ return /* @__PURE__ */ h(Fragment$2, null, /* @__PURE__ */ h("div", { class: "image-wrapper" }, /* @__PURE__ */ h("div", { class: "operation" }, /* @__PURE__ */ h("div", { class: "operation-item", onPointerdown: onToggleCaption }, /* @__PURE__ */ h(Icon, { icon: config.captionIcon }))), /* @__PURE__ */ h(
469
725
  "img",
470
726
  {
471
727
  ref: imageRef,
@@ -538,7 +794,7 @@ var __spreadValues = (a, b) => {
538
794
  }
539
795
  return a;
540
796
  };
541
- keepAlive(h, Fragment$1);
797
+ keepAlive(h, Fragment$2);
542
798
  const MilkdownImageBlock = defineComponent({
543
799
  props: {
544
800
  src: {
@@ -553,6 +809,10 @@ const MilkdownImageBlock = defineComponent({
553
809
  type: Object,
554
810
  required: true
555
811
  },
812
+ align: {
813
+ type: Object,
814
+ required: true
815
+ },
556
816
  selected: {
557
817
  type: Object,
558
818
  required: true
@@ -603,6 +863,7 @@ const imageBlockView = $view(
603
863
  const src = ref(initialNode.attrs.src);
604
864
  const caption = ref(initialNode.attrs.caption);
605
865
  const ratio = ref(initialNode.attrs.ratio);
866
+ const align = ref(initialNode.attrs.align);
606
867
  const selected = ref(false);
607
868
  const readonly = ref(!view.editable);
608
869
  const setAttr = (attr, value) => {
@@ -622,6 +883,7 @@ const imageBlockView = $view(
622
883
  src,
623
884
  caption,
624
885
  ratio,
886
+ align,
625
887
  selected,
626
888
  readonly,
627
889
  setAttr,
@@ -629,6 +891,7 @@ const imageBlockView = $view(
629
891
  });
630
892
  const dom = document.createElement("div");
631
893
  dom.className = "milkdown-image-block";
894
+ dom.dataset.align = initialNode.attrs.align || "center";
632
895
  const disposeSelectedWatcher = watchEffect(() => {
633
896
  const isSelected = selected.value;
634
897
  if (isSelected) {
@@ -637,6 +900,9 @@ const imageBlockView = $view(
637
900
  dom.classList.remove("selected");
638
901
  }
639
902
  });
903
+ const disposeAlignWatcher = watchEffect(() => {
904
+ dom.dataset.align = align.value || "center";
905
+ });
640
906
  const proxyDomURL = config.proxyDomURL;
641
907
  const bindAttrs = (node) => {
642
908
  if (!proxyDomURL) {
@@ -653,6 +919,7 @@ const imageBlockView = $view(
653
919
  }
654
920
  ratio.value = node.attrs.ratio;
655
921
  caption.value = node.attrs.caption;
922
+ align.value = node.attrs.align;
656
923
  readonly.value = !view.editable;
657
924
  };
658
925
  bindAttrs(initialNode);
@@ -676,6 +943,7 @@ const imageBlockView = $view(
676
943
  },
677
944
  destroy: () => {
678
945
  disposeSelectedWatcher();
946
+ disposeAlignWatcher();
679
947
  app.unmount();
680
948
  dom.remove();
681
949
  }
@@ -692,8 +960,10 @@ const imageBlockComponent = [
692
960
  remarkImageBlockPlugin,
693
961
  imageBlockSchema,
694
962
  imageBlockView,
695
- imageBlockConfig
963
+ imageBlockConfig,
964
+ imageBlockPasteRule,
965
+ imageBlockConvertPlugin
696
966
  ].flat();
697
967
 
698
- export { IMAGE_DATA_TYPE, defaultImageBlockConfig, imageBlockComponent, imageBlockConfig, imageBlockSchema, imageBlockView, remarkImageBlockPlugin };
968
+ export { IMAGE_DATA_TYPE, defaultImageBlockConfig, imageBlockComponent, imageBlockConfig, imageBlockConvertPlugin, imageBlockPasteRule, imageBlockSchema, imageBlockView, remarkImageBlockPlugin };
699
969
  //# sourceMappingURL=index.js.map