vuewrite 0.0.26 → 0.0.28

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/dist/markdown.js CHANGED
@@ -1,11 +1,74 @@
1
1
  let _counter = 0;
2
2
  const uid = () => (++_counter).toString();
3
- function markdownToBlocks(markdown) {
3
+ function blockContentKey(block) {
4
+ const { id: _id, ...rest } = block;
5
+ return JSON.stringify(rest);
6
+ }
7
+ function lcsIndices(oldKeys, newKeys) {
8
+ const m = oldKeys.length;
9
+ const n = newKeys.length;
10
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
11
+ for (let i2 = 1; i2 <= m; i2++) {
12
+ for (let j2 = 1; j2 <= n; j2++) {
13
+ dp[i2][j2] = oldKeys[i2 - 1] === newKeys[j2 - 1] ? dp[i2 - 1][j2 - 1] + 1 : Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
14
+ }
15
+ }
16
+ const pairs = [];
17
+ let i = m;
18
+ let j = n;
19
+ while (i > 0 && j > 0) {
20
+ if (oldKeys[i - 1] === newKeys[j - 1]) {
21
+ pairs.unshift([i - 1, j - 1]);
22
+ i--;
23
+ j--;
24
+ } else if (dp[i - 1][j] >= dp[i][j - 1]) {
25
+ i--;
26
+ } else {
27
+ j--;
28
+ }
29
+ }
30
+ return pairs;
31
+ }
32
+ function markdownToBlocks(markdown, previousBlocks = []) {
4
33
  const lines = markdown.split("\n");
5
34
  const blocks = [];
6
35
  let i = 0;
7
36
  while (i < lines.length) {
8
37
  const line = lines[i];
38
+ const customFenceMatch = line.match(/^:::\s*(\S+)/);
39
+ if (customFenceMatch) {
40
+ const type = customFenceMatch[1];
41
+ const bodyLines = [];
42
+ i++;
43
+ while (i < lines.length && lines[i].trim() !== ":::") {
44
+ bodyLines.push(lines[i]);
45
+ i++;
46
+ }
47
+ const { text: text2, styles: styles2 } = parseInline(bodyLines.join("\n"));
48
+ const block2 = { id: uid(), text: text2, type };
49
+ if (styles2.length > 0) block2.styles = styles2;
50
+ blocks.push(block2);
51
+ i++;
52
+ continue;
53
+ }
54
+ const xmlPairedMatch = line.match(/^<(\w[\w-]*)(\s[^>]*)?>(.+)<\/\1>$/);
55
+ if (xmlPairedMatch) {
56
+ const attrs = parseAttributes(xmlPairedMatch[2] ?? "");
57
+ const { text: text2, styles: styles2 } = parseInline(xmlPairedMatch[3]);
58
+ const block2 = { id: uid(), text: text2, type: xmlPairedMatch[1], ...attrs };
59
+ if (styles2.length > 0) block2.styles = styles2;
60
+ blocks.push(block2);
61
+ i++;
62
+ continue;
63
+ }
64
+ const xmlSelfMatch = line.match(/^<(\w[\w-]*)(\s[^>]*)?\s*\/?>$/);
65
+ if (xmlSelfMatch) {
66
+ const attrs = parseAttributes(xmlSelfMatch[2] ?? "");
67
+ const block2 = { id: uid(), text: "", type: xmlSelfMatch[1], editable: false, ...attrs };
68
+ blocks.push(block2);
69
+ i++;
70
+ continue;
71
+ }
9
72
  if (line.startsWith("```")) {
10
73
  const codeLines = [];
11
74
  i++;
@@ -62,7 +125,24 @@ function markdownToBlocks(markdown) {
62
125
  if (blocks.length === 0) {
63
126
  blocks.push({ id: uid(), text: "" });
64
127
  }
65
- return blocks;
128
+ if (previousBlocks.length === 0) return blocks;
129
+ const oldKeys = previousBlocks.map(blockContentKey);
130
+ const newKeys = blocks.map(blockContentKey);
131
+ const pairs = lcsIndices(oldKeys, newKeys);
132
+ const oldIdByNewIndex = new Map(pairs.map(([i2, j]) => [j, previousBlocks[i2].id]));
133
+ return blocks.map((block, j) => {
134
+ const oldId = oldIdByNewIndex.get(j);
135
+ return oldId !== void 0 ? { ...block, id: oldId } : block;
136
+ });
137
+ }
138
+ function parseAttributes(attrStr) {
139
+ const result = {};
140
+ const re = /(\w[\w-]*)(?:=(?:"([^"]*)"|'([^']*)'|(\S+)))?/g;
141
+ let m;
142
+ while ((m = re.exec(attrStr)) !== null) {
143
+ result[m[1]] = m[2] ?? m[3] ?? m[4] ?? true;
144
+ }
145
+ return result;
66
146
  }
67
147
  function parseInline(md) {
68
148
  let plainText = "";
@@ -142,6 +222,7 @@ const MARKERS = {
142
222
  underline: { open: "__", close: "__" },
143
223
  code: { open: "`", close: "`" }
144
224
  };
225
+ const STANDARD_FIELDS = /* @__PURE__ */ new Set(["id", "text", "type", "styles", "editable"]);
145
226
  function blocksToMarkdown(blocks) {
146
227
  const lines = [];
147
228
  let olCounter = 0;
@@ -153,6 +234,21 @@ function blocksToMarkdown(blocks) {
153
234
  olCounter = 0;
154
235
  continue;
155
236
  }
237
+ const extraKeys = Object.keys(block).filter((k) => !STANDARD_FIELDS.has(k));
238
+ if (block.type && extraKeys.length > 0) {
239
+ const attrStr = extraKeys.map((k) => {
240
+ const v = block[k];
241
+ return v === true ? k : `${k}="${v}"`;
242
+ }).join(" ");
243
+ const prefix = attrStr ? ` ${attrStr}` : "";
244
+ if (block.editable === false || !block.text) {
245
+ lines.push(`<${block.type}${prefix}/>`);
246
+ } else {
247
+ lines.push(`<${block.type}${prefix}>${renderInline(block.text, block.styles ?? [])}</${block.type}>`);
248
+ }
249
+ olCounter = 0;
250
+ continue;
251
+ }
156
252
  const inline = renderInline(block.text, block.styles ?? []);
157
253
  switch (block.type) {
158
254
  case "h1":
@@ -175,7 +271,13 @@ function blocksToMarkdown(blocks) {
175
271
  lines.push(`${++olCounter}. ${inline}`);
176
272
  break;
177
273
  default:
178
- lines.push(inline);
274
+ if (block.type) {
275
+ lines.push(`:::${block.type}`);
276
+ lines.push(inline);
277
+ lines.push(":::");
278
+ } else {
279
+ lines.push(inline);
280
+ }
179
281
  olCounter = 0;
180
282
  break;
181
283
  }
@@ -64,6 +64,7 @@ decorator?: Decorator;
64
64
  renderer?: Renderer;
65
65
  single?: boolean;
66
66
  modelValue?: {
67
+ id?: string;
67
68
  text: string;
68
69
  styles?: Style[];
69
70
  type?: string;
@@ -121,6 +122,7 @@ decorator?: Decorator;
121
122
  renderer?: Renderer;
122
123
  single?: boolean;
123
124
  modelValue?: {
125
+ id?: string;
124
126
  text: string;
125
127
  styles?: Style[];
126
128
  type?: string;
package/dist/vuewrite.js CHANGED
@@ -783,7 +783,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
783
783
  }
784
784
  store.blocks.length = newValue.length;
785
785
  for (let i = 0; i < newValue.length; i++) {
786
- store.blocks[i] = { ...newValue[i], id: uid() };
786
+ store.blocks[i] = { ...newValue[i], id: newValue[i].id ?? uid() };
787
787
  }
788
788
  }
789
789
  }, { immediate: true });
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "vuewrite",
3
3
  "description": "Rich Text Editor based on Vue3 reactivity",
4
4
  "private": false,
5
- "version": "0.0.26",
5
+ "version": "0.0.28",
6
6
  "type": "module",
7
7
  "license": "MIT",
8
8
  "author": "den59k",
@@ -27,8 +27,7 @@
27
27
  "dev": "vite build --watch"
28
28
  },
29
29
  "dependencies": {
30
- "vue": "^3",
31
- "vuewrite-markdown": "0.0.1"
30
+ "vue": "^3"
32
31
  },
33
32
  "devDependencies": {
34
33
  "@vitejs/plugin-vue": "^5.0.4",
@@ -36,6 +35,7 @@
36
35
  "vite": "^5.2.0",
37
36
  "vite-plugin-dts": "^3.9.1",
38
37
  "vuesix": "^1.0.12",
38
+ "vuewrite-markdown": "0.0.1",
39
39
  "vue-tsc": "^2.0.6"
40
40
  },
41
41
  "files": ["dist"]