@meowdown/core 0.64.2 → 0.64.3
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/index.d.ts +34 -11
- package/dist/index.js +122 -78
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -260,7 +260,7 @@ interface MdMathAttrs {
|
|
|
260
260
|
* source reveals around the caret.
|
|
261
261
|
*/
|
|
262
262
|
type MdPackAttrs = {
|
|
263
|
-
key: 'italic' | 'bold' | 'code' | 'del' | 'highlight'
|
|
263
|
+
key: 'italic' | 'bold' | 'code' | 'del' | 'highlight';
|
|
264
264
|
data?: null;
|
|
265
265
|
slot?: 1 | null;
|
|
266
266
|
revealInFocus: true;
|
|
@@ -268,13 +268,25 @@ type MdPackAttrs = {
|
|
|
268
268
|
} | {
|
|
269
269
|
key: 'link';
|
|
270
270
|
data: {
|
|
271
|
+
form: 'inline' | 'reference';
|
|
271
272
|
href: string;
|
|
272
273
|
title: string;
|
|
273
|
-
|
|
274
|
+
} | {
|
|
275
|
+
form: 'angle';
|
|
276
|
+
href: string;
|
|
274
277
|
};
|
|
275
278
|
slot?: 1 | null;
|
|
276
279
|
revealInFocus: true;
|
|
277
280
|
revealInHide?: null;
|
|
281
|
+
} | {
|
|
282
|
+
key: 'link';
|
|
283
|
+
data: {
|
|
284
|
+
form: 'bare';
|
|
285
|
+
href: string;
|
|
286
|
+
};
|
|
287
|
+
slot?: 1 | null;
|
|
288
|
+
revealInFocus?: null;
|
|
289
|
+
revealInHide?: null;
|
|
278
290
|
} | {
|
|
279
291
|
key: 'math';
|
|
280
292
|
data?: null;
|
|
@@ -296,7 +308,7 @@ interface PositionRange {
|
|
|
296
308
|
}
|
|
297
309
|
//#endregion
|
|
298
310
|
//#region src/extensions/get-link-unit-at.d.ts
|
|
299
|
-
interface
|
|
311
|
+
interface LinkUnitBase {
|
|
300
312
|
/**
|
|
301
313
|
* Whole inline link, reference link, or autolink range.
|
|
302
314
|
*/
|
|
@@ -308,14 +320,6 @@ interface LinkUnit {
|
|
|
308
320
|
* whose collapsed glyphs measure at bogus coordinates.
|
|
309
321
|
*/
|
|
310
322
|
text: PositionRange;
|
|
311
|
-
/**
|
|
312
|
-
* Interior of `[ ]`. Absent for an autolink.
|
|
313
|
-
*/
|
|
314
|
-
label?: PositionRange;
|
|
315
|
-
/**
|
|
316
|
-
* Interior of `( )`. What `updateLink` rewrites. Absent for an autolink.
|
|
317
|
-
*/
|
|
318
|
-
dest?: PositionRange;
|
|
319
323
|
/**
|
|
320
324
|
* The link URL. Could be an empty string.
|
|
321
325
|
*/
|
|
@@ -325,6 +329,25 @@ interface LinkUnit {
|
|
|
325
329
|
*/
|
|
326
330
|
title: string;
|
|
327
331
|
}
|
|
332
|
+
type LinkUnit = (LinkUnitBase & {
|
|
333
|
+
form: 'inline';
|
|
334
|
+
/**
|
|
335
|
+
* Interior of `[ ]`.
|
|
336
|
+
*/
|
|
337
|
+
label: PositionRange;
|
|
338
|
+
/**
|
|
339
|
+
* Interior of `( )`. What `updateLink` rewrites.
|
|
340
|
+
*/
|
|
341
|
+
dest: PositionRange;
|
|
342
|
+
}) | (LinkUnitBase & {
|
|
343
|
+
/**
|
|
344
|
+
* A reference link or autolink resolves an href but has no editable
|
|
345
|
+
* label/dest.
|
|
346
|
+
*/
|
|
347
|
+
form: 'reference' | 'angle' | 'bare';
|
|
348
|
+
label?: undefined;
|
|
349
|
+
dest?: undefined;
|
|
350
|
+
});
|
|
328
351
|
/**
|
|
329
352
|
* The link covering `pos`, with its sub-ranges (`label`, `dest`) and parsed
|
|
330
353
|
* `href`/`title`. The single query the commands and the hover/click handlers
|
package/dist/index.js
CHANGED
|
@@ -347,19 +347,14 @@ function resolvePosition(state, pos) {
|
|
|
347
347
|
return $pos;
|
|
348
348
|
}
|
|
349
349
|
/**
|
|
350
|
-
* Returns the run of the
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
* mark.
|
|
350
|
+
* Returns the run of the mark covering `pos`, or `undefined` when none covers
|
|
351
|
+
* it. `attrs` narrows the match to marks whose attributes contain it, which
|
|
352
|
+
* is how a caller picks one level out of a nested stack of the same mark.
|
|
354
353
|
*/
|
|
355
354
|
function getMarkRangeAt(state, pos, markName, attrs) {
|
|
356
355
|
const $pos = resolvePosition(state, pos);
|
|
357
356
|
if (!$pos) return;
|
|
358
|
-
|
|
359
|
-
for (const name of markNames) {
|
|
360
|
-
const range = ATOM_MARK_NAMES.includes(name) ? getAtomUnitRange(state, $pos, name) : getMarkRange($pos, name, attrs);
|
|
361
|
-
if (range) return range;
|
|
362
|
-
}
|
|
357
|
+
return ATOM_MARK_NAMES.includes(markName) ? getAtomUnitRange(state, $pos, markName) : getMarkRange($pos, markName, attrs);
|
|
363
358
|
}
|
|
364
359
|
/**
|
|
365
360
|
* The range of the atom unit touching `$pos`, preferring the child to the
|
|
@@ -2848,7 +2843,6 @@ function getGenericPackKey(type) {
|
|
|
2848
2843
|
case LEZER_NODE_IDS.InlineCode: return "code";
|
|
2849
2844
|
case LEZER_NODE_IDS.Strikethrough: return "del";
|
|
2850
2845
|
case LEZER_NODE_IDS.Highlight: return "highlight";
|
|
2851
|
-
case LEZER_NODE_IDS.Autolink: return "autolink";
|
|
2852
2846
|
default: return;
|
|
2853
2847
|
}
|
|
2854
2848
|
}
|
|
@@ -2914,6 +2908,7 @@ function walkNode(node, parentMarks, text, marks, out, options, context) {
|
|
|
2914
2908
|
case LEZER_NODE_IDS.Wikilink: return walkWikilink(node, parentMarks, text, marks, out);
|
|
2915
2909
|
case LEZER_NODE_IDS.WikiEmbed: return walkWikiEmbed(node, parentMarks, text, marks, out, options);
|
|
2916
2910
|
case LEZER_NODE_IDS.InlineMath: return walkMath(node, parentMarks, text, marks, out);
|
|
2911
|
+
case LEZER_NODE_IDS.Autolink: return walkAutolink(node, parentMarks, text, marks, out);
|
|
2917
2912
|
case LEZER_NODE_IDS.URL: return walkURL(node, parentMarks, text, marks, out);
|
|
2918
2913
|
default: return walkGenericNode(node, parentMarks, text, marks, out, options, context);
|
|
2919
2914
|
}
|
|
@@ -2935,14 +2930,55 @@ function walkGenericNode(node, parentMarks, text, marks, out, options, context)
|
|
|
2935
2930
|
else walk(node.children, childMarks, node.from, node.to, text, marks, out, options, context);
|
|
2936
2931
|
}
|
|
2937
2932
|
/**
|
|
2938
|
-
*
|
|
2939
|
-
*
|
|
2940
|
-
*
|
|
2933
|
+
* Special walker for an angle autolink `<url>`. The unit's `href` lives on
|
|
2934
|
+
* its pack, computed from the `URL` child (`''` when the address is not
|
|
2935
|
+
* linkable, in which case the URL keeps the muted `mdLinkUri`). The children
|
|
2936
|
+
* are only the `<`/`>` marks and the `URL`, consumed right here: the `URL`
|
|
2937
|
+
* is a component of this unit, never a unit of its own.
|
|
2938
|
+
*/
|
|
2939
|
+
function walkAutolink(node, parentMarks, text, marks, out) {
|
|
2940
|
+
const urlNode = node.children.find((child) => child.type === LEZER_NODE_IDS.URL);
|
|
2941
|
+
const href = urlNode ? getAutolinkHref(text.slice(urlNode.from, urlNode.to)) ?? "" : "";
|
|
2942
|
+
const base = [...parentMarks, createUnitPack(marks, out, parentMarks, node.from, {
|
|
2943
|
+
key: "link",
|
|
2944
|
+
data: {
|
|
2945
|
+
form: "angle",
|
|
2946
|
+
href
|
|
2947
|
+
},
|
|
2948
|
+
revealInFocus: true
|
|
2949
|
+
})];
|
|
2950
|
+
let pos = node.from;
|
|
2951
|
+
for (const child of node.children) {
|
|
2952
|
+
if (child.from > pos) emit(out, pos, child.from, base);
|
|
2953
|
+
const childMark = child.type === LEZER_NODE_IDS.URL ? href ? marks.mdLinkText.create({ href }) : marks.mdLinkUri.create() : marks.mdMark.create();
|
|
2954
|
+
emit(out, child.from, child.to, [...base, childMark]);
|
|
2955
|
+
pos = child.to;
|
|
2956
|
+
}
|
|
2957
|
+
if (pos < node.to) emit(out, pos, node.to, base);
|
|
2958
|
+
}
|
|
2959
|
+
/**
|
|
2960
|
+
* A `URL` node reaching this walker is a standalone GFM autolink: the address
|
|
2961
|
+
* part of a `[text](url)` link is consumed by `walkResolvedLink`, and an
|
|
2962
|
+
* angle autolink's URL by `walkAutolink`. Linkify the shapes we recognize,
|
|
2963
|
+
* packing each as its own unit; anything else keeps the muted `mdLinkUri`.
|
|
2941
2964
|
*/
|
|
2942
2965
|
function walkURL(node, parentMarks, text, marks, out) {
|
|
2943
2966
|
const href = getAutolinkHref(text.slice(node.from, node.to));
|
|
2944
|
-
|
|
2945
|
-
|
|
2967
|
+
if (!href) {
|
|
2968
|
+
emit(out, node.from, node.to, [...parentMarks, marks.mdLinkUri.create()]);
|
|
2969
|
+
return;
|
|
2970
|
+
}
|
|
2971
|
+
emit(out, node.from, node.to, [
|
|
2972
|
+
...parentMarks,
|
|
2973
|
+
createUnitPack(marks, out, parentMarks, node.from, {
|
|
2974
|
+
key: "link",
|
|
2975
|
+
data: {
|
|
2976
|
+
form: "bare",
|
|
2977
|
+
href
|
|
2978
|
+
}
|
|
2979
|
+
}),
|
|
2980
|
+
marks.mdLinkText.create({ href })
|
|
2981
|
+
]);
|
|
2946
2982
|
}
|
|
2947
2983
|
function walkLink(node, parentMarks, text, marks, out, options, context) {
|
|
2948
2984
|
const parts = scanLinkParts(node);
|
|
@@ -2966,6 +3002,9 @@ function walkLink(node, parentMarks, text, marks, out, options, context) {
|
|
|
2966
3002
|
* Locate the pieces of a `Link` node in Lezer's flat child list:
|
|
2967
3003
|
* LinkMark `[`, [label children], LinkMark `]`, LinkMark `(`, URL,
|
|
2968
3004
|
* optional LinkTitle, LinkMark `)`.
|
|
3005
|
+
*
|
|
3006
|
+
* An autolink inside the label also emits a `URL` child, so only a `URL`
|
|
3007
|
+
* after the second `LinkMark` (the `]` closing the label) is the destination.
|
|
2969
3008
|
*/
|
|
2970
3009
|
function scanLinkParts(node) {
|
|
2971
3010
|
let labelFrom = -1;
|
|
@@ -2982,7 +3021,7 @@ function scanLinkParts(node) {
|
|
|
2982
3021
|
bracketCount++;
|
|
2983
3022
|
if (bracketCount === 1) labelFrom = child.to;
|
|
2984
3023
|
if (bracketCount === 2) labelTo = child.from;
|
|
2985
|
-
} else if (urlNode == null && childType === LEZER_NODE_IDS.URL) urlNode = child;
|
|
3024
|
+
} else if (urlNode == null && bracketCount >= 2 && childType === LEZER_NODE_IDS.URL) urlNode = child;
|
|
2986
3025
|
else if (titleNode == null && childType === LEZER_NODE_IDS.LinkTitle) titleNode = child;
|
|
2987
3026
|
else if (referenceLabelNode == null && childType === LEZER_NODE_IDS.LinkLabel) referenceLabelNode = child;
|
|
2988
3027
|
}
|
|
@@ -3084,9 +3123,9 @@ function walkResolvedLink(node, parts, resolution, parentMarks, text, marks, out
|
|
|
3084
3123
|
const pack = createUnitPack(marks, out, parentMarks, node.from, {
|
|
3085
3124
|
key: "link",
|
|
3086
3125
|
data: {
|
|
3126
|
+
form: isReference ? "reference" : "inline",
|
|
3087
3127
|
href,
|
|
3088
|
-
title
|
|
3089
|
-
isReference
|
|
3128
|
+
title
|
|
3090
3129
|
},
|
|
3091
3130
|
revealInFocus: true
|
|
3092
3131
|
});
|
|
@@ -3118,6 +3157,11 @@ function walkResolvedLink(node, parts, resolution, parentMarks, text, marks, out
|
|
|
3118
3157
|
pos = child.to;
|
|
3119
3158
|
continue;
|
|
3120
3159
|
}
|
|
3160
|
+
if (child.type === LEZER_NODE_IDS.URL && inLabel(child.from)) {
|
|
3161
|
+
emit(out, child.from, child.to, baseForChild);
|
|
3162
|
+
pos = child.to;
|
|
3163
|
+
continue;
|
|
3164
|
+
}
|
|
3121
3165
|
const maybeMarkName = MARK_NAME_BY_TYPE_ID.get(child.type);
|
|
3122
3166
|
const childMarks = maybeMarkName ? [...baseForChild, marks[maybeMarkName].create()] : baseForChild;
|
|
3123
3167
|
if (child.children.length === 0) emit(out, child.from, child.to, childMarks);
|
|
@@ -3709,10 +3753,11 @@ function defineMdMath() {
|
|
|
3709
3753
|
}
|
|
3710
3754
|
/**
|
|
3711
3755
|
* Wraps a whole inline unit. For a revealable unit (emphasis, strong, code,
|
|
3712
|
-
* strikethrough, link,
|
|
3713
|
-
* range lookup instead of stitching its punctuation back together;
|
|
3714
|
-
* unit (wikilink, image, file) carries
|
|
3715
|
-
* `excludes: ''` lets nested units carry two of these
|
|
3756
|
+
* strikethrough, inline and angle link, math) focus mode reveals the unit
|
|
3757
|
+
* with one range lookup instead of stitching its punctuation back together;
|
|
3758
|
+
* a unit that never reveals (wikilink, image, file, bare autolink) carries
|
|
3759
|
+
* it as unit identity. `excludes: ''` lets nested units carry two of these
|
|
3760
|
+
* marks at once.
|
|
3716
3761
|
*/
|
|
3717
3762
|
function defineMdPack() {
|
|
3718
3763
|
return defineMarkSpec({
|
|
@@ -4106,67 +4151,66 @@ function lastMarkRunIn(state, range, markName) {
|
|
|
4106
4151
|
* the `mdLinkUri` run locates the `( )` body.
|
|
4107
4152
|
*/
|
|
4108
4153
|
function getLinkUnitAt(state, pos) {
|
|
4109
|
-
const
|
|
4110
|
-
const pack = getMarkRangeAt(state, pos, "mdPack", { key: "link" }) ?? getMarkRangeAt(state, pos, "mdPack", { key: "autolink" });
|
|
4111
|
-
const unit = pack ?? linkText;
|
|
4154
|
+
const unit = getMarkRangeAt(state, pos, "mdPack", { key: "link" });
|
|
4112
4155
|
if (!unit) return;
|
|
4113
|
-
const
|
|
4114
|
-
const
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4156
|
+
const { data } = unit.mark.attrs;
|
|
4157
|
+
const unitRange = {
|
|
4158
|
+
from: unit.from,
|
|
4159
|
+
to: unit.to
|
|
4160
|
+
};
|
|
4161
|
+
switch (data.form) {
|
|
4162
|
+
case "bare": return {
|
|
4163
|
+
form: "bare",
|
|
4164
|
+
unit: unitRange,
|
|
4165
|
+
text: unitRange,
|
|
4166
|
+
href: data.href,
|
|
4167
|
+
title: ""
|
|
4119
4168
|
};
|
|
4120
|
-
return {
|
|
4169
|
+
case "angle": return {
|
|
4170
|
+
form: "angle",
|
|
4121
4171
|
unit: unitRange,
|
|
4122
|
-
text:
|
|
4172
|
+
text: {
|
|
4123
4173
|
from: unit.from + 1,
|
|
4124
4174
|
to: unit.to - 1
|
|
4125
|
-
} : unitRange,
|
|
4126
|
-
href,
|
|
4127
|
-
title: ""
|
|
4128
|
-
};
|
|
4129
|
-
}
|
|
4130
|
-
const linkData = packAttrs.data;
|
|
4131
|
-
if (linkData.isReference) {
|
|
4132
|
-
const text = linkText == null ? {
|
|
4133
|
-
from: unit.from,
|
|
4134
|
-
to: unit.to
|
|
4135
|
-
} : {
|
|
4136
|
-
from: linkText.from + 1,
|
|
4137
|
-
to: linkText.to
|
|
4138
|
-
};
|
|
4139
|
-
return {
|
|
4140
|
-
unit: {
|
|
4141
|
-
from: unit.from,
|
|
4142
|
-
to: unit.to
|
|
4143
4175
|
},
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
title: linkData.title
|
|
4176
|
+
href: data.href,
|
|
4177
|
+
title: ""
|
|
4147
4178
|
};
|
|
4179
|
+
case "reference": {
|
|
4180
|
+
const linkText = getMarkRangeAt(state, pos, "mdLinkText");
|
|
4181
|
+
return {
|
|
4182
|
+
form: "reference",
|
|
4183
|
+
unit: unitRange,
|
|
4184
|
+
text: linkText == null ? unitRange : {
|
|
4185
|
+
from: linkText.from + 1,
|
|
4186
|
+
to: linkText.to
|
|
4187
|
+
},
|
|
4188
|
+
href: data.href,
|
|
4189
|
+
title: data.title
|
|
4190
|
+
};
|
|
4191
|
+
}
|
|
4192
|
+
case "inline": {
|
|
4193
|
+
const uri = lastMarkRunIn(state, unitRange, "mdLinkUri");
|
|
4194
|
+
const closeBracket = uri ? uri.from - 2 : unit.to - 3;
|
|
4195
|
+
const destFrom = uri ? uri.from : unit.to - 1;
|
|
4196
|
+
const label = {
|
|
4197
|
+
from: unit.from + 1,
|
|
4198
|
+
to: closeBracket
|
|
4199
|
+
};
|
|
4200
|
+
return {
|
|
4201
|
+
form: "inline",
|
|
4202
|
+
unit: unitRange,
|
|
4203
|
+
text: label,
|
|
4204
|
+
label,
|
|
4205
|
+
dest: {
|
|
4206
|
+
from: destFrom,
|
|
4207
|
+
to: unit.to - 1
|
|
4208
|
+
},
|
|
4209
|
+
href: data.href,
|
|
4210
|
+
title: data.title
|
|
4211
|
+
};
|
|
4212
|
+
}
|
|
4148
4213
|
}
|
|
4149
|
-
const uri = lastMarkRunIn(state, unit, "mdLinkUri");
|
|
4150
|
-
const closeBracket = uri ? uri.from - 2 : unit.to - 3;
|
|
4151
|
-
const destFrom = uri ? uri.from : unit.to - 1;
|
|
4152
|
-
const label = {
|
|
4153
|
-
from: unit.from + 1,
|
|
4154
|
-
to: closeBracket
|
|
4155
|
-
};
|
|
4156
|
-
return {
|
|
4157
|
-
unit: {
|
|
4158
|
-
from: unit.from,
|
|
4159
|
-
to: unit.to
|
|
4160
|
-
},
|
|
4161
|
-
text: label,
|
|
4162
|
-
label,
|
|
4163
|
-
dest: {
|
|
4164
|
-
from: destFrom,
|
|
4165
|
-
to: unit.to - 1
|
|
4166
|
-
},
|
|
4167
|
-
href: linkData.href,
|
|
4168
|
-
title: linkData.title
|
|
4169
|
-
};
|
|
4170
4214
|
}
|
|
4171
4215
|
|
|
4172
4216
|
//#endregion
|
|
@@ -4226,7 +4270,7 @@ function insertLink({ href, title, wrapText = true } = {}) {
|
|
|
4226
4270
|
function updateLink(attrs) {
|
|
4227
4271
|
return (state, dispatch) => {
|
|
4228
4272
|
const link = getLinkUnitAt(state, state.selection.from);
|
|
4229
|
-
if (
|
|
4273
|
+
if (link?.form !== "inline") return false;
|
|
4230
4274
|
const dest = destText(normalizeHref(attrs.href ?? link.href), attrs.title ?? link.title);
|
|
4231
4275
|
if (dispatch) dispatch(state.tr.insertText(dest, link.dest.from, link.dest.to).scrollIntoView());
|
|
4232
4276
|
return true;
|
|
@@ -4238,7 +4282,7 @@ function updateLink(attrs) {
|
|
|
4238
4282
|
function removeLink() {
|
|
4239
4283
|
return (state, dispatch) => {
|
|
4240
4284
|
const link = getLinkUnitAt(state, state.selection.from);
|
|
4241
|
-
if (
|
|
4285
|
+
if (link?.form !== "inline") return false;
|
|
4242
4286
|
if (dispatch) dispatch(state.tr.delete(link.label.to, link.unit.to).delete(link.unit.from, link.label.from).scrollIntoView());
|
|
4243
4287
|
return true;
|
|
4244
4288
|
};
|
|
@@ -4254,7 +4298,7 @@ function openLinkEdit(onLinkEdit) {
|
|
|
4254
4298
|
return (state, dispatch, view) => {
|
|
4255
4299
|
const link = getLinkUnitAt(state, state.selection.from);
|
|
4256
4300
|
if (link) {
|
|
4257
|
-
if (link.
|
|
4301
|
+
if (link.form !== "inline") return false;
|
|
4258
4302
|
if (dispatch && view) {
|
|
4259
4303
|
const { unit: { from, to } } = link;
|
|
4260
4304
|
dispatch(state.tr.setSelection(TextSelection.create(state.doc, from, to)).scrollIntoView());
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meowdown/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.64.
|
|
4
|
+
"version": "0.64.3",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"remark-stringify": "^11.0.0",
|
|
44
44
|
"unicode-by-name": "^0.2.0",
|
|
45
45
|
"unified": "^11.0.5",
|
|
46
|
-
"@meowdown/markdown": "^0.64.
|
|
46
|
+
"@meowdown/markdown": "^0.64.3"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@ocavue/tsconfig": "^0.7.1",
|