@blankdotpage/cake 0.1.56 → 0.1.57
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;
|
|
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;AAibF,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
|
|
50
|
-
while (
|
|
51
|
-
|
|
52
|
-
if (linkStart
|
|
53
|
-
|
|
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
|
|
57
|
-
if (
|
|
58
|
-
|
|
96
|
+
const range = findSimpleLinkRangeFromStart(source, linkStart);
|
|
97
|
+
if (!range) {
|
|
98
|
+
cursor = linkStart + 1;
|
|
59
99
|
continue;
|
|
60
100
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
linkStart = source.lastIndexOf("[", linkStart - 1);
|
|
64
|
-
continue;
|
|
101
|
+
if (range.labelStart <= start && end <= range.labelEnd) {
|
|
102
|
+
return range;
|
|
65
103
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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;
|
|
70
117
|
}
|
|
71
|
-
|
|
118
|
+
const range = findSimpleLinkRangeFromStart(source, linkStart);
|
|
119
|
+
if (range) {
|
|
120
|
+
return range;
|
|
121
|
+
}
|
|
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
|
|
158
|
-
const
|
|
159
|
-
const
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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(
|
|
222
|
+
const label = source.slice(existingLink.labelStart, existingLink.labelEnd);
|
|
181
223
|
// Replace [label](url) with just label
|
|
182
|
-
const nextSource = source.slice(0, linkStart) +
|
|
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
|
|
198
|
-
const
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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) {
|
|
211
|
-
return null;
|
|
212
|
-
}
|
|
213
|
-
// Find the closing )
|
|
214
|
-
const urlClose = source.indexOf(")", labelClose + 2);
|
|
215
|
-
if (urlClose === -1) {
|
|
248
|
+
const existingLink = findEnclosingLinkRange(source, from, to) ??
|
|
249
|
+
findLinkRangeByScanningBackward(source, from);
|
|
250
|
+
if (!existingLink) {
|
|
216
251
|
return null;
|
|
217
252
|
}
|
|
218
|
-
const nextSource = source.slice(0,
|
|
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 =
|
|
224
|
-
const labelEndSource =
|
|
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(
|
|
271
|
+
const endCursor = nextState.map.sourceToCursor(existingLink.labelEnd, "backward");
|
|
237
272
|
return {
|
|
238
273
|
source: nextSource,
|
|
239
274
|
selection: {
|