@blankdotpage/cake 0.1.56 → 0.1.58

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":"link.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/link/link.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AA2F3D,8CAA8C;AAC9C,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,wCAAwC;AACxC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,qDAAqD;AACrD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,kCAAkC;AAClC,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAE9E,MAAM,MAAM,kBAAkB,GAAG,CAC/B,MAAM,EAAE,UAAU,KACf,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAAC;AAEnD,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B,CAAC;AAkcF,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AACvE,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,aAAa,CAAC"}
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/link/link.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAwJ3D,8CAA8C;AAC9C,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,wCAAwC;AACxC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,qDAAqD;AACrD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,kCAAkC;AAClC,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAE9E,MAAM,MAAM,kBAAkB,GAAG,CAC/B,MAAM,EAAE,UAAU,KACf,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAAC;AAEnD,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B,CAAC;AAmaF,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AACvE,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,aAAa,CAAC"}
@@ -37,6 +37,47 @@ function countBoundaryWrappers(fragment) {
37
37
  }
38
38
  return count;
39
39
  }
40
+ function findSimpleLinkRangeFromStart(source, linkStart) {
41
+ if (source[linkStart] !== "[") {
42
+ return null;
43
+ }
44
+ // Don't match image syntax ![...](...)
45
+ if (linkStart > 0 && source[linkStart - 1] === "!") {
46
+ return null;
47
+ }
48
+ let labelClose = -1;
49
+ for (let i = linkStart + 1; i < source.length; i += 1) {
50
+ const char = source[i];
51
+ if (char === "\\") {
52
+ i += 1;
53
+ continue;
54
+ }
55
+ // Nested labels are not supported by this parser.
56
+ if (char === "[") {
57
+ return null;
58
+ }
59
+ if (char === "]") {
60
+ labelClose = i;
61
+ break;
62
+ }
63
+ }
64
+ if (labelClose === -1) {
65
+ return null;
66
+ }
67
+ if (source[labelClose + 1] !== "(") {
68
+ return null;
69
+ }
70
+ const urlClose = source.indexOf(")", labelClose + 2);
71
+ if (urlClose === -1) {
72
+ return null;
73
+ }
74
+ return {
75
+ linkStart,
76
+ labelStart: linkStart + 1,
77
+ labelEnd: labelClose,
78
+ urlClose,
79
+ };
80
+ }
40
81
  function findEnclosingLinkRange(source, from, to) {
41
82
  if (source.length === 0) {
42
83
  return null;
@@ -46,29 +87,39 @@ function findEnclosingLinkRange(source, from, to) {
46
87
  if (start >= end) {
47
88
  return null;
48
89
  }
49
- let linkStart = source.lastIndexOf("[", start);
50
- while (linkStart !== -1) {
51
- // Skip image syntax ![...](...)
52
- if (linkStart > 0 && source[linkStart - 1] === "!") {
53
- linkStart = source.lastIndexOf("[", linkStart - 1);
54
- continue;
90
+ let cursor = 0;
91
+ while (cursor < source.length) {
92
+ const linkStart = source.indexOf("[", cursor);
93
+ if (linkStart === -1) {
94
+ break;
55
95
  }
56
- const labelClose = source.indexOf("](", linkStart + 1);
57
- if (labelClose === -1) {
58
- linkStart = source.lastIndexOf("[", linkStart - 1);
96
+ const range = findSimpleLinkRangeFromStart(source, linkStart);
97
+ if (!range) {
98
+ cursor = linkStart + 1;
59
99
  continue;
60
100
  }
61
- const urlClose = source.indexOf(")", labelClose + 2);
62
- if (urlClose === -1) {
63
- linkStart = source.lastIndexOf("[", linkStart - 1);
64
- continue;
101
+ if (range.labelStart <= start && end <= range.labelEnd) {
102
+ return range;
103
+ }
104
+ cursor = range.urlClose + 1;
105
+ }
106
+ return null;
107
+ }
108
+ function findLinkRangeByScanningBackward(source, startPos) {
109
+ if (source.length === 0) {
110
+ return null;
111
+ }
112
+ let searchFrom = Math.min(Math.max(0, startPos), source.length - 1);
113
+ while (searchFrom >= 0) {
114
+ const linkStart = source.lastIndexOf("[", searchFrom);
115
+ if (linkStart === -1) {
116
+ return null;
65
117
  }
66
- const labelStart = linkStart + 1;
67
- const labelEnd = labelClose;
68
- if (labelStart <= start && end <= labelEnd) {
69
- return { linkStart, labelStart, labelEnd, urlClose };
118
+ const range = findSimpleLinkRangeFromStart(source, linkStart);
119
+ if (range) {
120
+ return range;
70
121
  }
71
- linkStart = source.lastIndexOf("[", linkStart - 1);
122
+ searchFrom = linkStart - 1;
72
123
  }
73
124
  return null;
74
125
  }
@@ -154,35 +205,28 @@ function installLinkExtension(editor, options) {
154
205
  ]));
155
206
  disposers.push(editor.registerOnEdit((command, state) => {
156
207
  if (command.type === "unlink") {
157
- // Find the link at the given cursor position and remove the link markup
158
- const cursorPos = command.start;
159
- const sourcePos = state.map.cursorToSource(cursorPos, "forward");
208
+ // Find the link around the given selection and remove link markup.
209
+ const cursorStart = Math.min(command.start, command.end);
210
+ const cursorEnd = Math.max(command.start, command.end);
211
+ const sourceStart = state.map.cursorToSource(cursorStart, "forward");
212
+ const sourceEnd = state.map.cursorToSource(cursorEnd, "backward");
213
+ const from = Math.min(sourceStart, sourceEnd);
214
+ const to = Math.max(from + 1, sourceEnd);
160
215
  const source = state.source;
161
- // Search backwards for the opening bracket
162
- let linkStart = sourcePos;
163
- while (linkStart > 0 && source[linkStart] !== "[") {
164
- linkStart--;
165
- }
166
- if (source[linkStart] !== "[") {
167
- return null;
168
- }
169
- // Find the ]( separator
170
- const labelClose = source.indexOf("](", linkStart + 1);
171
- if (labelClose === -1) {
172
- return null;
173
- }
174
- // Find the closing )
175
- const urlClose = source.indexOf(")", labelClose + 2);
176
- if (urlClose === -1) {
216
+ const existingLink = findEnclosingLinkRange(source, from, to) ??
217
+ findLinkRangeByScanningBackward(source, from);
218
+ if (!existingLink) {
177
219
  return null;
178
220
  }
179
221
  // Extract the label (text between [ and ]( )
180
- const label = source.slice(linkStart + 1, labelClose);
222
+ const label = source.slice(existingLink.labelStart, existingLink.labelEnd);
181
223
  // Replace [label](url) with just label
182
- const nextSource = source.slice(0, linkStart) + label + source.slice(urlClose + 1);
224
+ const nextSource = source.slice(0, existingLink.linkStart) +
225
+ label +
226
+ source.slice(existingLink.urlClose + 1);
183
227
  // Calculate new cursor position - place it at the end of the label
184
228
  const newState = state.runtime.createState(nextSource);
185
- const labelEndSource = linkStart + label.length;
229
+ const labelEndSource = existingLink.linkStart + label.length;
186
230
  const newCursor = newState.map.sourceToCursor(labelEndSource, "forward");
187
231
  return {
188
232
  source: nextSource,
@@ -194,34 +238,25 @@ function installLinkExtension(editor, options) {
194
238
  };
195
239
  }
196
240
  if (command.type === "set-link-url") {
197
- const cursorPos = Math.min(command.start, command.end);
198
- const sourcePos = state.map.cursorToSource(cursorPos, "forward");
241
+ const cursorStart = Math.min(command.start, command.end);
242
+ const cursorEnd = Math.max(command.start, command.end);
243
+ const sourceStart = state.map.cursorToSource(cursorStart, "forward");
244
+ const sourceEnd = state.map.cursorToSource(cursorEnd, "backward");
245
+ const from = Math.min(sourceStart, sourceEnd);
246
+ const to = Math.max(from + 1, sourceEnd);
199
247
  const source = state.source;
200
- // Search backwards for the opening bracket
201
- let linkStart = sourcePos;
202
- while (linkStart > 0 && source[linkStart] !== "[") {
203
- linkStart--;
204
- }
205
- if (source[linkStart] !== "[") {
206
- return null;
207
- }
208
- // Find the ]( separator
209
- const labelClose = source.indexOf("](", linkStart + 1);
210
- if (labelClose === -1) {
248
+ const existingLink = findEnclosingLinkRange(source, from, to) ??
249
+ findLinkRangeByScanningBackward(source, from);
250
+ if (!existingLink) {
211
251
  return null;
212
252
  }
213
- // Find the closing )
214
- const urlClose = source.indexOf(")", labelClose + 2);
215
- if (urlClose === -1) {
216
- return null;
217
- }
218
- const nextSource = source.slice(0, labelClose + 2) +
253
+ const nextSource = source.slice(0, existingLink.labelEnd + 2) +
219
254
  command.url +
220
- source.slice(urlClose);
255
+ source.slice(existingLink.urlClose);
221
256
  const nextState = state.runtime.createState(nextSource);
222
257
  if (command.selectLabel) {
223
- const labelStartSource = linkStart + 1;
224
- const labelEndSource = labelClose;
258
+ const labelStartSource = existingLink.labelStart;
259
+ const labelEndSource = existingLink.labelEnd;
225
260
  const startCursor = nextState.map.sourceToCursor(labelStartSource, "forward");
226
261
  const endCursor = nextState.map.sourceToCursor(labelEndSource, "backward");
227
262
  return {
@@ -233,7 +268,7 @@ function installLinkExtension(editor, options) {
233
268
  },
234
269
  };
235
270
  }
236
- const endCursor = nextState.map.sourceToCursor(labelClose, "backward");
271
+ const endCursor = nextState.map.sourceToCursor(existingLink.labelEnd, "backward");
237
272
  return {
238
273
  source: nextSource,
239
274
  selection: {
@@ -333,25 +368,14 @@ function installLinkExtension(editor, options) {
333
368
  return { type: "insert", text: linkMarkdown };
334
369
  }));
335
370
  disposers.push(editor.registerParseInline((source, start, end, context) => {
336
- if (source[start] !== "[") {
337
- return null;
338
- }
339
- // Don't match image syntax ![...](...)
340
- if (start > 0 && source[start - 1] === "!") {
341
- return null;
342
- }
343
- const labelClose = source.indexOf("](", start + 1);
344
- if (labelClose === -1 || labelClose >= end) {
345
- return null;
346
- }
347
- const urlClose = source.indexOf(")", labelClose + 2);
348
- if (urlClose === -1 || urlClose >= end) {
371
+ const range = findSimpleLinkRangeFromStart(source, start);
372
+ if (!range || range.urlClose >= end) {
349
373
  return null;
350
374
  }
351
- const labelStart = start + 1;
352
- const labelEnd = labelClose;
353
- const urlStart = labelClose + 2;
354
- const urlEnd = urlClose;
375
+ const labelStart = range.labelStart;
376
+ const labelEnd = range.labelEnd;
377
+ const urlStart = range.labelEnd + 2;
378
+ const urlEnd = range.urlClose;
355
379
  const children = context.parseInline(source, labelStart, labelEnd);
356
380
  const url = source.slice(urlStart, urlEnd);
357
381
  return {
@@ -361,7 +385,7 @@ function installLinkExtension(editor, options) {
361
385
  children,
362
386
  data: { url },
363
387
  },
364
- nextPos: urlClose + 1,
388
+ nextPos: range.urlClose + 1,
365
389
  };
366
390
  }));
367
391
  disposers.push(editor.registerSerializeInline((inline, context) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blankdotpage/cake",
3
- "version": "0.1.56",
3
+ "version": "0.1.58",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",