@meowdown/core 0.64.2 → 0.65.0
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 +116 -50
- package/dist/index.js +340 -246
- 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
|
|
@@ -1032,6 +1055,11 @@ interface FileClickPayload {
|
|
|
1032
1055
|
* pill. Read modifier keys or position a popover from it.
|
|
1033
1056
|
*/
|
|
1034
1057
|
event: MouseEvent | KeyboardEvent;
|
|
1058
|
+
/**
|
|
1059
|
+
* Whether the platform's mod key (`Command` on Apple, `Ctrl` elsewhere) was held
|
|
1060
|
+
* beyond the gesture that triggered the activation.
|
|
1061
|
+
*/
|
|
1062
|
+
mod: boolean;
|
|
1035
1063
|
}
|
|
1036
1064
|
type FileClickHandler = (payload: FileClickPayload) => void;
|
|
1037
1065
|
/**
|
|
@@ -1117,6 +1145,45 @@ declare function getFileKind(href: string): string;
|
|
|
1117
1145
|
*/
|
|
1118
1146
|
declare function defineFileView(options?: FileViewOptions): PlainExtension;
|
|
1119
1147
|
//#endregion
|
|
1148
|
+
//#region src/extensions/image-click.d.ts
|
|
1149
|
+
/**
|
|
1150
|
+
* Payload for {@link ImageClickHandler}.
|
|
1151
|
+
*/
|
|
1152
|
+
interface ImageClickPayload {
|
|
1153
|
+
/**
|
|
1154
|
+
* The resolved source from `` or a claimed `![[target]]`.
|
|
1155
|
+
*/
|
|
1156
|
+
src: string;
|
|
1157
|
+
/**
|
|
1158
|
+
* The image alt text.
|
|
1159
|
+
*/
|
|
1160
|
+
alt: string;
|
|
1161
|
+
/**
|
|
1162
|
+
* The originating click or touch tap, or the `Enter`/`Mod-Enter` key press
|
|
1163
|
+
* that followed the selected image. Read the target or position a popover
|
|
1164
|
+
* from it; a touch surface delivers the `touchend` instead of a click.
|
|
1165
|
+
*/
|
|
1166
|
+
event: MouseEvent | TouchEvent | KeyboardEvent;
|
|
1167
|
+
/**
|
|
1168
|
+
* Whether the platform's mod key (`Command` on Apple, `Ctrl` elsewhere) was held
|
|
1169
|
+
* beyond the gesture that triggered the activation.
|
|
1170
|
+
*/
|
|
1171
|
+
mod: boolean;
|
|
1172
|
+
}
|
|
1173
|
+
type ImageClickHandler = (payload: ImageClickPayload) => void;
|
|
1174
|
+
/**
|
|
1175
|
+
* Call `onClick` when the user clicks or taps a rendered image preview, with
|
|
1176
|
+
* the image's markdown `src`, `alt`, and the originating event.
|
|
1177
|
+
*
|
|
1178
|
+
* Touch taps are handled from `touchend` rather than the synthetic click:
|
|
1179
|
+
* previews live inside the editor contenteditable, and iOS WebKit's
|
|
1180
|
+
* tap-to-focus is a native gesture default action that only cancelling the
|
|
1181
|
+
* `touchend` can suppress — otherwise a tap briefly focuses the editor and
|
|
1182
|
+
* raises the software keyboard before the handler opens its own surface
|
|
1183
|
+
* (such as a lightbox).
|
|
1184
|
+
*/
|
|
1185
|
+
declare function defineImageClickHandler(onClick: ImageClickHandler): PlainExtension;
|
|
1186
|
+
//#endregion
|
|
1120
1187
|
//#region src/extensions/link-click.d.ts
|
|
1121
1188
|
interface LinkClickPayload {
|
|
1122
1189
|
href: string;
|
|
@@ -1124,6 +1191,11 @@ interface LinkClickPayload {
|
|
|
1124
1191
|
* The originating click, or the `Enter`/`Mod-Enter` key press that followed the link.
|
|
1125
1192
|
*/
|
|
1126
1193
|
event: MouseEvent | KeyboardEvent;
|
|
1194
|
+
/**
|
|
1195
|
+
* Whether the platform's mod key (`Command` on Apple, `Ctrl` elsewhere) was held
|
|
1196
|
+
* beyond the gesture that triggered the activation.
|
|
1197
|
+
*/
|
|
1198
|
+
mod: boolean;
|
|
1127
1199
|
}
|
|
1128
1200
|
type LinkClickHandler = (payload: LinkClickPayload) => void;
|
|
1129
1201
|
interface LinkCopyPayload {
|
|
@@ -1148,6 +1220,11 @@ interface TagClickPayload {
|
|
|
1148
1220
|
* Read modifier keys or position a popover from it.
|
|
1149
1221
|
*/
|
|
1150
1222
|
event: MouseEvent | KeyboardEvent;
|
|
1223
|
+
/**
|
|
1224
|
+
* Whether the platform's mod key (`Command` on Apple, `Ctrl` elsewhere) was held
|
|
1225
|
+
* beyond the gesture that triggered the activation.
|
|
1226
|
+
*/
|
|
1227
|
+
mod: boolean;
|
|
1151
1228
|
}
|
|
1152
1229
|
type TagClickHandler = (payload: TagClickPayload) => void;
|
|
1153
1230
|
/**
|
|
@@ -1169,6 +1246,11 @@ interface WikilinkClickPayload {
|
|
|
1169
1246
|
* The originating click, or the `Enter`/`Mod-Enter` key press that followed the link.
|
|
1170
1247
|
*/
|
|
1171
1248
|
event: MouseEvent | KeyboardEvent;
|
|
1249
|
+
/**
|
|
1250
|
+
* Whether the platform's mod key (`Command` on Apple, `Ctrl` elsewhere) was held
|
|
1251
|
+
* beyond the gesture that triggered the activation.
|
|
1252
|
+
*/
|
|
1253
|
+
mod: boolean;
|
|
1172
1254
|
}
|
|
1173
1255
|
type WikilinkClickHandler = (payload: WikilinkClickPayload) => void;
|
|
1174
1256
|
/**
|
|
@@ -1184,49 +1266,24 @@ interface FollowLinkHandlers {
|
|
|
1184
1266
|
onTagClick?: TagClickHandler;
|
|
1185
1267
|
onFileClick?: FileClickHandler;
|
|
1186
1268
|
onLinkClick?: LinkClickHandler;
|
|
1269
|
+
onImageClick?: ImageClickHandler;
|
|
1187
1270
|
}
|
|
1188
1271
|
/**
|
|
1189
1272
|
* Binds `Mod-Enter` to follow the wikilink, tag, file pill, or Markdown link
|
|
1190
|
-
* under the caret, and plain `Enter` to follow a selected atom unit
|
|
1191
|
-
* the same handlers a click does.
|
|
1192
|
-
* the
|
|
1193
|
-
*
|
|
1194
|
-
* keymap
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
//#endregion
|
|
1198
|
-
//#region src/extensions/image-click.d.ts
|
|
1199
|
-
/**
|
|
1200
|
-
* Payload for {@link ImageClickHandler}.
|
|
1201
|
-
*/
|
|
1202
|
-
interface ImageClickPayload {
|
|
1203
|
-
/**
|
|
1204
|
-
* The resolved source from `` or a claimed `![[target]]`.
|
|
1205
|
-
*/
|
|
1206
|
-
src: string;
|
|
1207
|
-
/**
|
|
1208
|
-
* The image alt text.
|
|
1209
|
-
*/
|
|
1210
|
-
alt: string;
|
|
1211
|
-
/**
|
|
1212
|
-
* The originating click or touch tap. Read the target or position a popover
|
|
1213
|
-
* from it; a touch surface delivers the `touchend` instead of a click.
|
|
1214
|
-
*/
|
|
1215
|
-
event: MouseEvent | TouchEvent;
|
|
1216
|
-
}
|
|
1217
|
-
type ImageClickHandler = (payload: ImageClickPayload) => void;
|
|
1218
|
-
/**
|
|
1219
|
-
* Call `onClick` when the user clicks or taps a rendered image preview, with
|
|
1220
|
-
* the image's markdown `src`, `alt`, and the originating event.
|
|
1273
|
+
* under the caret, and plain `Enter` to follow a selected atom unit (a
|
|
1274
|
+
* wikilink, file pill, or image), firing the same handlers a click does.
|
|
1275
|
+
* "Under the caret" means strictly inside the unit: a caret merely touching
|
|
1276
|
+
* a unit's edge is next to it, not on it.
|
|
1277
|
+
* Off a link, `Mod-Enter` falls through so the list keymap keeps cycling
|
|
1278
|
+
* checkbox tasks; off a selected unit, `Enter` falls through to the regular
|
|
1279
|
+
* split. High priority puts this ahead of every keymap binding.
|
|
1221
1280
|
*
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
1225
|
-
*
|
|
1226
|
-
* raises the software keyboard before the handler opens its own surface
|
|
1227
|
-
* (such as a lightbox).
|
|
1281
|
+
* A selected-unit follow reports `mod: true` when the platform's mod key
|
|
1282
|
+
* (`⌘` on Apple, `Ctrl` elsewhere) was held beyond its plain-`Enter` trigger;
|
|
1283
|
+
* a caret follow always reports `mod: false`, its mod key being the trigger
|
|
1284
|
+
* itself.
|
|
1228
1285
|
*/
|
|
1229
|
-
declare function
|
|
1286
|
+
declare function defineFollowLinkHandler(handlers: FollowLinkHandlers): PlainExtension;
|
|
1230
1287
|
//#endregion
|
|
1231
1288
|
//#region src/extensions/image.d.ts
|
|
1232
1289
|
type ImageUrlResolver = (src: string) => string | undefined;
|
|
@@ -1432,6 +1489,15 @@ declare function getTextblockDisplayText(textblock: ProseMirrorNode): string;
|
|
|
1432
1489
|
*/
|
|
1433
1490
|
declare function formatFileSize(bytes: number): string;
|
|
1434
1491
|
//#endregion
|
|
1492
|
+
//#region src/utils/is-mod-event.d.ts
|
|
1493
|
+
/**
|
|
1494
|
+
* Whether the platform's mod key is held on `event`: `Command` on Apple, `Ctrl` elsewhere.
|
|
1495
|
+
*/
|
|
1496
|
+
declare function isModEvent(event: MouseEvent | KeyboardEvent | TouchEvent | {
|
|
1497
|
+
metaKey: boolean;
|
|
1498
|
+
ctrlKey: boolean;
|
|
1499
|
+
}): boolean;
|
|
1500
|
+
//#endregion
|
|
1435
1501
|
//#region src/utils/katex-chunk.d.ts
|
|
1436
1502
|
type KaTeXRender = typeof render;
|
|
1437
1503
|
//#endregion
|
|
@@ -1469,4 +1535,4 @@ declare function getSelectedText(state: EditorState): string;
|
|
|
1469
1535
|
*/
|
|
1470
1536
|
declare function getVirtualElementFromRange(view: EditorView, range: PositionRange): VirtualElement;
|
|
1471
1537
|
//#endregion
|
|
1472
|
-
export { type AcceptPendingReplacementOptions, type CheckRoundTripOptions, type CodeBlockAttrs, type CodeBlockFenceStyle, type CodeToken, type DocToMarkdownOptions, EDITOR_KEY_BINDINGS, type EditorExtension, type EditorExtensionOptions, type EmbedDescriptor, type ExitBoundaryHandler, type ExitBoundaryOptions, type FileClickHandler, type FileClickPayload, type FileInfo, type FileInfoResolver, type FileLinkOptions, type FileLinkPayload, type FileLinkResolver, type FilePasteHandler, type FilePasteOptions, type FileSaveErrorHandler, type FileViewOptions, type FollowLinkHandlers, type ImageClickHandler, type ImageClickPayload, type ImageOptions, type InlineMarkContext, type InlineMarkOptions, type KaTeXRender, type LanguageItem, type LinkAttrs, type LinkClickHandler, type LinkClickPayload, type LinkCopyHandler, type LinkCopyPayload, type LinkEditHandler, type LinkEditOptions, type LinkHoverHandler, type LinkUnit, type ListMarker, type MarkChunk, type MarkMode, type MarkName, type MarkdownToDocOptions, type MdFileAttrs, type MdImageAttrs, type MdLinkTextAttrs, type MdMathAttrs, type MdWikilinkAttrs, type MeowdownCodeBlockAttrs, type MeowdownHTMLCommentAttrs, type MeowdownListAttrs, type MeowdownTableCellAttrs, type NodeName, type ParsedWikiEmbed, type PendingReplacement, type PendingReplacementEvent, type PendingReplacementHandler, type PendingReplacementMode, type PendingReplacementOutcome, type PlaceholderOptions, type PositionRange, Priority, type ReferenceDefinition, type ReferenceDefinitionIndex, type ReferenceDefinitions, type RoundTripFidelity, type SearchStatus, type SearchStatusHandler, type StartPendingReplacementOptions, type TableColumnAlign, type TagClickHandler, type TagClickPayload, type TypedEditor, type TypedMarkBuilders, type VirtualElement, type WikiEmbedOptions, type WikiEmbedResolution, type WikiEmbedResolver, type WikilinkClickHandler, type WikilinkClickPayload, type WikilinkHoverHandler, type WikilinkHoverHit, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSpellCheckPlugin, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getFileKind, getIsComposing, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isMarkOfType, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, parseWikiEmbed, removeLink, renderMathInto, updateLink, wikiEmbedBasename, withPriority };
|
|
1538
|
+
export { type AcceptPendingReplacementOptions, type CheckRoundTripOptions, type CodeBlockAttrs, type CodeBlockFenceStyle, type CodeToken, type DocToMarkdownOptions, EDITOR_KEY_BINDINGS, type EditorExtension, type EditorExtensionOptions, type EmbedDescriptor, type ExitBoundaryHandler, type ExitBoundaryOptions, type FileClickHandler, type FileClickPayload, type FileInfo, type FileInfoResolver, type FileLinkOptions, type FileLinkPayload, type FileLinkResolver, type FilePasteHandler, type FilePasteOptions, type FileSaveErrorHandler, type FileViewOptions, type FollowLinkHandlers, type ImageClickHandler, type ImageClickPayload, type ImageOptions, type InlineMarkContext, type InlineMarkOptions, type KaTeXRender, type LanguageItem, type LinkAttrs, type LinkClickHandler, type LinkClickPayload, type LinkCopyHandler, type LinkCopyPayload, type LinkEditHandler, type LinkEditOptions, type LinkHoverHandler, type LinkUnit, type ListMarker, type MarkChunk, type MarkMode, type MarkName, type MarkdownToDocOptions, type MdFileAttrs, type MdImageAttrs, type MdLinkTextAttrs, type MdMathAttrs, type MdWikilinkAttrs, type MeowdownCodeBlockAttrs, type MeowdownHTMLCommentAttrs, type MeowdownListAttrs, type MeowdownTableCellAttrs, type NodeName, type ParsedWikiEmbed, type PendingReplacement, type PendingReplacementEvent, type PendingReplacementHandler, type PendingReplacementMode, type PendingReplacementOutcome, type PlaceholderOptions, type PositionRange, Priority, type ReferenceDefinition, type ReferenceDefinitionIndex, type ReferenceDefinitions, type RoundTripFidelity, type SearchStatus, type SearchStatusHandler, type StartPendingReplacementOptions, type TableColumnAlign, type TagClickHandler, type TagClickPayload, type TypedEditor, type TypedMarkBuilders, type VirtualElement, type WikiEmbedOptions, type WikiEmbedResolution, type WikiEmbedResolver, type WikilinkClickHandler, type WikilinkClickPayload, type WikilinkHoverHandler, type WikilinkHoverHit, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSpellCheckPlugin, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getFileKind, getIsComposing, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isMarkOfType, isModEvent, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, parseWikiEmbed, removeLink, renderMathInto, updateLink, wikiEmbedBasename, withPriority };
|
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());
|
|
@@ -4384,11 +4428,13 @@ function defineMeowdownListSerializer() {
|
|
|
4384
4428
|
return (...args) => {
|
|
4385
4429
|
return {
|
|
4386
4430
|
...nodesFromSchema(...args),
|
|
4387
|
-
list: (node) =>
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4431
|
+
list: (node) => {
|
|
4432
|
+
return listToDOM({
|
|
4433
|
+
node,
|
|
4434
|
+
nativeList: true,
|
|
4435
|
+
getAttributes: getListClipboardAttributes
|
|
4436
|
+
});
|
|
4437
|
+
}
|
|
4392
4438
|
};
|
|
4393
4439
|
};
|
|
4394
4440
|
}
|
|
@@ -6386,6 +6432,15 @@ function defineExitBoundaryHandler(onExitBoundary) {
|
|
|
6386
6432
|
return withPriority$1(definePlugin(createExitBoundaryPlugin(onExitBoundary)), Priority$1.low);
|
|
6387
6433
|
}
|
|
6388
6434
|
|
|
6435
|
+
//#endregion
|
|
6436
|
+
//#region src/utils/is-mod-event.ts
|
|
6437
|
+
/**
|
|
6438
|
+
* Whether the platform's mod key is held on `event`: `Command` on Apple, `Ctrl` elsewhere.
|
|
6439
|
+
*/
|
|
6440
|
+
function isModEvent(event) {
|
|
6441
|
+
return isApple ? event.metaKey : event.ctrlKey;
|
|
6442
|
+
}
|
|
6443
|
+
|
|
6389
6444
|
//#endregion
|
|
6390
6445
|
//#region src/extensions/file-click.ts
|
|
6391
6446
|
const fileClickKey = new PluginKey("meowdown-file-click");
|
|
@@ -6394,6 +6449,8 @@ function findFileAt(state, pos) {
|
|
|
6394
6449
|
if (!range) return;
|
|
6395
6450
|
const { href, name } = range.mark.attrs;
|
|
6396
6451
|
return {
|
|
6452
|
+
from: range.from,
|
|
6453
|
+
to: range.to,
|
|
6397
6454
|
href,
|
|
6398
6455
|
name
|
|
6399
6456
|
};
|
|
@@ -6416,7 +6473,8 @@ function defineFileClickHandler(onClick) {
|
|
|
6416
6473
|
onClick({
|
|
6417
6474
|
href: hit.href,
|
|
6418
6475
|
name: hit.name,
|
|
6419
|
-
event
|
|
6476
|
+
event,
|
|
6477
|
+
mod: isModEvent(event)
|
|
6420
6478
|
});
|
|
6421
6479
|
return true;
|
|
6422
6480
|
} }
|
|
@@ -6704,6 +6762,126 @@ function defineFileView(options = {}) {
|
|
|
6704
6762
|
});
|
|
6705
6763
|
}
|
|
6706
6764
|
|
|
6765
|
+
//#endregion
|
|
6766
|
+
//#region src/extensions/image-click.ts
|
|
6767
|
+
const imageClickKey = new PluginKey("meowdown-image-click");
|
|
6768
|
+
function getClosestImagePreview(target) {
|
|
6769
|
+
return target instanceof HTMLElement && target.closest(".md-image-view-preview");
|
|
6770
|
+
}
|
|
6771
|
+
function findImageAt(state, pos) {
|
|
6772
|
+
const range = getMarkRangeAt(state, pos, "mdImage");
|
|
6773
|
+
if (!range) return;
|
|
6774
|
+
const { src, alt } = range.mark.attrs;
|
|
6775
|
+
return {
|
|
6776
|
+
from: range.from,
|
|
6777
|
+
to: range.to,
|
|
6778
|
+
src,
|
|
6779
|
+
alt
|
|
6780
|
+
};
|
|
6781
|
+
}
|
|
6782
|
+
/**
|
|
6783
|
+
* Resolve the image hit for a preview element via its content holder, not the
|
|
6784
|
+
* event's document position: an event on the non-editable preview lands on the
|
|
6785
|
+
* run boundary, where `getMarkRange` would pick the next adjacent image.
|
|
6786
|
+
*/
|
|
6787
|
+
function findImageForPreview(view, preview) {
|
|
6788
|
+
const content = preview.closest(".md-image-view")?.querySelector(".md-image-view-content");
|
|
6789
|
+
if (!content) return;
|
|
6790
|
+
return findImageAt(view.state, view.posAtDOM(content, 0));
|
|
6791
|
+
}
|
|
6792
|
+
/**
|
|
6793
|
+
* Fingers wander a little during a tap; past this it is a scroll or a drag.
|
|
6794
|
+
*/
|
|
6795
|
+
const TAP_MOVE_TOLERANCE = 10;
|
|
6796
|
+
function findTouch(touches, identifier) {
|
|
6797
|
+
return Array.from(touches).find((touch) => touch.identifier === identifier);
|
|
6798
|
+
}
|
|
6799
|
+
function isWithinTapTolerance(pending, touch) {
|
|
6800
|
+
return Math.abs(touch.clientX - pending.clientX) <= TAP_MOVE_TOLERANCE && Math.abs(touch.clientY - pending.clientY) <= TAP_MOVE_TOLERANCE;
|
|
6801
|
+
}
|
|
6802
|
+
/**
|
|
6803
|
+
* Call `onClick` when the user clicks or taps a rendered image preview, with
|
|
6804
|
+
* the image's markdown `src`, `alt`, and the originating event.
|
|
6805
|
+
*
|
|
6806
|
+
* Touch taps are handled from `touchend` rather than the synthetic click:
|
|
6807
|
+
* previews live inside the editor contenteditable, and iOS WebKit's
|
|
6808
|
+
* tap-to-focus is a native gesture default action that only cancelling the
|
|
6809
|
+
* `touchend` can suppress — otherwise a tap briefly focuses the editor and
|
|
6810
|
+
* raises the software keyboard before the handler opens its own surface
|
|
6811
|
+
* (such as a lightbox).
|
|
6812
|
+
*/
|
|
6813
|
+
function defineImageClickHandler(onClick) {
|
|
6814
|
+
const pendingTaps = /* @__PURE__ */ new WeakMap();
|
|
6815
|
+
const handleTouchEnd = (view, event) => {
|
|
6816
|
+
const pending = pendingTaps.get(view);
|
|
6817
|
+
pendingTaps.delete(view);
|
|
6818
|
+
if (!pending || event.touches.length > 0) return false;
|
|
6819
|
+
const touch = findTouch(event.changedTouches, pending.identifier);
|
|
6820
|
+
if (!touch || !isWithinTapTolerance(pending, touch)) return false;
|
|
6821
|
+
const preview = getClosestImagePreview(event.target);
|
|
6822
|
+
if (!preview) return false;
|
|
6823
|
+
event.preventDefault();
|
|
6824
|
+
const hit = findImageForPreview(view, preview);
|
|
6825
|
+
if (hit) onClick({
|
|
6826
|
+
src: hit.src,
|
|
6827
|
+
alt: hit.alt,
|
|
6828
|
+
event,
|
|
6829
|
+
mod: isModEvent(event)
|
|
6830
|
+
});
|
|
6831
|
+
return true;
|
|
6832
|
+
};
|
|
6833
|
+
return definePlugin(new Plugin({
|
|
6834
|
+
key: imageClickKey,
|
|
6835
|
+
props: {
|
|
6836
|
+
handleDOMEvents: {
|
|
6837
|
+
pointerdown: (view, event) => {
|
|
6838
|
+
if (getClosestImagePreview(event.target) && event.pointerType !== "mouse") event.preventDefault();
|
|
6839
|
+
return false;
|
|
6840
|
+
},
|
|
6841
|
+
touchstart: (view, event) => {
|
|
6842
|
+
pendingTaps.delete(view);
|
|
6843
|
+
if (event.touches.length !== 1) return false;
|
|
6844
|
+
if (!getClosestImagePreview(event.target)) return false;
|
|
6845
|
+
if (event.target instanceof HTMLElement && event.target.closest(".md-image-resize-handle")) return false;
|
|
6846
|
+
const touch = event.changedTouches[0];
|
|
6847
|
+
if (!touch) return false;
|
|
6848
|
+
pendingTaps.set(view, {
|
|
6849
|
+
identifier: touch.identifier,
|
|
6850
|
+
clientX: touch.clientX,
|
|
6851
|
+
clientY: touch.clientY
|
|
6852
|
+
});
|
|
6853
|
+
return false;
|
|
6854
|
+
},
|
|
6855
|
+
touchmove: (view, event) => {
|
|
6856
|
+
const pending = pendingTaps.get(view);
|
|
6857
|
+
if (!pending) return false;
|
|
6858
|
+
const touch = findTouch(event.changedTouches, pending.identifier);
|
|
6859
|
+
if (touch && !isWithinTapTolerance(pending, touch)) pendingTaps.delete(view);
|
|
6860
|
+
return false;
|
|
6861
|
+
},
|
|
6862
|
+
touchcancel: (view) => {
|
|
6863
|
+
pendingTaps.delete(view);
|
|
6864
|
+
return false;
|
|
6865
|
+
},
|
|
6866
|
+
touchend: handleTouchEnd
|
|
6867
|
+
},
|
|
6868
|
+
handleClick: (view, _pos, event) => {
|
|
6869
|
+
const preview = getClosestImagePreview(event.target);
|
|
6870
|
+
if (!preview) return false;
|
|
6871
|
+
const hit = findImageForPreview(view, preview);
|
|
6872
|
+
if (!hit) return false;
|
|
6873
|
+
onClick({
|
|
6874
|
+
src: hit.src,
|
|
6875
|
+
alt: hit.alt,
|
|
6876
|
+
event,
|
|
6877
|
+
mod: isModEvent(event)
|
|
6878
|
+
});
|
|
6879
|
+
return true;
|
|
6880
|
+
}
|
|
6881
|
+
}
|
|
6882
|
+
}));
|
|
6883
|
+
}
|
|
6884
|
+
|
|
6707
6885
|
//#endregion
|
|
6708
6886
|
//#region src/extensions/mark-click.ts
|
|
6709
6887
|
/**
|
|
@@ -6757,7 +6935,8 @@ function defineTagClickHandler(onClick) {
|
|
|
6757
6935
|
findPayloadAt: (state, pos) => findTagAt(state, pos)?.tag,
|
|
6758
6936
|
onClick: (tag, event) => onClick({
|
|
6759
6937
|
tag,
|
|
6760
|
-
event
|
|
6938
|
+
event,
|
|
6939
|
+
mod: isModEvent(event)
|
|
6761
6940
|
})
|
|
6762
6941
|
});
|
|
6763
6942
|
}
|
|
@@ -6804,7 +6983,8 @@ function defineWikilinkClickHandler(onClick) {
|
|
|
6804
6983
|
findPayloadForElement: (view, element) => findWikilinkForElement(view, element)?.target,
|
|
6805
6984
|
onClick: (target, event) => onClick({
|
|
6806
6985
|
target,
|
|
6807
|
-
event
|
|
6986
|
+
event,
|
|
6987
|
+
mod: isModEvent(event)
|
|
6808
6988
|
})
|
|
6809
6989
|
});
|
|
6810
6990
|
}
|
|
@@ -6819,173 +6999,86 @@ function createFollowLinkPlugin(handlers) {
|
|
|
6819
6999
|
if (getIsComposing() || event.key !== "Enter" || event.shiftKey) return false;
|
|
6820
7000
|
const { state } = view;
|
|
6821
7001
|
const selectedAtom = getSelectedAtomRange(state);
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
if (
|
|
6826
|
-
handlers.onWikilinkClick?.({
|
|
6827
|
-
target: wikilink.target,
|
|
6828
|
-
event
|
|
6829
|
-
});
|
|
6830
|
-
return true;
|
|
6831
|
-
}
|
|
6832
|
-
const tag = handlers.onTagClick && findTagAt(state, pos);
|
|
6833
|
-
if (tag) {
|
|
6834
|
-
handlers.onTagClick?.({
|
|
6835
|
-
tag: tag.tag,
|
|
6836
|
-
event
|
|
6837
|
-
});
|
|
6838
|
-
return true;
|
|
6839
|
-
}
|
|
6840
|
-
const file = handlers.onFileClick && findFileAt(state, pos);
|
|
6841
|
-
if (file) {
|
|
6842
|
-
handlers.onFileClick?.({
|
|
6843
|
-
href: file.href,
|
|
6844
|
-
name: file.name,
|
|
6845
|
-
event
|
|
6846
|
-
});
|
|
6847
|
-
return true;
|
|
6848
|
-
}
|
|
6849
|
-
const link = handlers.onLinkClick && getLinkUnitAt(state, pos);
|
|
6850
|
-
if (link) {
|
|
6851
|
-
handlers.onLinkClick?.({
|
|
6852
|
-
href: link.href,
|
|
6853
|
-
event
|
|
6854
|
-
});
|
|
6855
|
-
return true;
|
|
6856
|
-
}
|
|
7002
|
+
const mod = isModEvent(event);
|
|
7003
|
+
if (!selectedAtom && !mod) return;
|
|
7004
|
+
if (selectedAtom && handlerAtomMarkTrigger(state, event, handlers, mod, selectedAtom)) return true;
|
|
7005
|
+
if (handlerTextMarkTrigger(state, event, handlers, mod)) return true;
|
|
6857
7006
|
return false;
|
|
6858
7007
|
} }
|
|
6859
7008
|
});
|
|
6860
7009
|
}
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
* run boundary, where `getMarkRange` would pick the next adjacent image.
|
|
6894
|
-
*/
|
|
6895
|
-
function findImageForPreview(view, preview) {
|
|
6896
|
-
const content = preview.closest(".md-image-view")?.querySelector(".md-image-view-content");
|
|
6897
|
-
if (!content) return;
|
|
6898
|
-
return findImageAt(view.state, view.posAtDOM(content, 0));
|
|
6899
|
-
}
|
|
6900
|
-
/**
|
|
6901
|
-
* Fingers wander a little during a tap; past this it is a scroll or a drag.
|
|
6902
|
-
*/
|
|
6903
|
-
const TAP_MOVE_TOLERANCE = 10;
|
|
6904
|
-
function findTouch(touches, identifier) {
|
|
6905
|
-
return Array.from(touches).find((touch) => touch.identifier === identifier);
|
|
7010
|
+
function handlerAtomMarkTrigger(state, event, handlers, mod, selectedAtom) {
|
|
7011
|
+
const pos = selectedAtom.from + 1;
|
|
7012
|
+
const { onWikilinkClick, onFileClick, onImageClick } = handlers;
|
|
7013
|
+
const wikilink = onWikilinkClick && findWikilinkAt(state, pos);
|
|
7014
|
+
if (wikilink) {
|
|
7015
|
+
onWikilinkClick({
|
|
7016
|
+
target: wikilink.target,
|
|
7017
|
+
event,
|
|
7018
|
+
mod
|
|
7019
|
+
});
|
|
7020
|
+
return true;
|
|
7021
|
+
}
|
|
7022
|
+
const file = onFileClick && findFileAt(state, pos);
|
|
7023
|
+
if (file) {
|
|
7024
|
+
onFileClick({
|
|
7025
|
+
href: file.href,
|
|
7026
|
+
name: file.name,
|
|
7027
|
+
event,
|
|
7028
|
+
mod
|
|
7029
|
+
});
|
|
7030
|
+
return true;
|
|
7031
|
+
}
|
|
7032
|
+
const image = onImageClick && findImageAt(state, pos);
|
|
7033
|
+
if (image) {
|
|
7034
|
+
onImageClick({
|
|
7035
|
+
src: image.src,
|
|
7036
|
+
alt: image.alt,
|
|
7037
|
+
event,
|
|
7038
|
+
mod
|
|
7039
|
+
});
|
|
7040
|
+
return true;
|
|
7041
|
+
}
|
|
6906
7042
|
}
|
|
6907
|
-
function
|
|
6908
|
-
|
|
7043
|
+
function handlerTextMarkTrigger(state, event, handlers, mod) {
|
|
7044
|
+
const pos = state.selection.head;
|
|
7045
|
+
const { onTagClick, onLinkClick } = handlers;
|
|
7046
|
+
const tag = onTagClick && findTagAt(state, pos);
|
|
7047
|
+
if (tag && tag.from < pos && pos < tag.to) {
|
|
7048
|
+
onTagClick({
|
|
7049
|
+
tag: tag.tag,
|
|
7050
|
+
event,
|
|
7051
|
+
mod
|
|
7052
|
+
});
|
|
7053
|
+
return true;
|
|
7054
|
+
}
|
|
7055
|
+
const link = onLinkClick && getLinkUnitAt(state, pos);
|
|
7056
|
+
if (link && link.unit.from < pos && pos < link.unit.to) {
|
|
7057
|
+
onLinkClick({
|
|
7058
|
+
href: link.href,
|
|
7059
|
+
event,
|
|
7060
|
+
mod
|
|
7061
|
+
});
|
|
7062
|
+
return true;
|
|
7063
|
+
}
|
|
6909
7064
|
}
|
|
6910
7065
|
/**
|
|
6911
|
-
*
|
|
6912
|
-
* the
|
|
7066
|
+
* Binds `Mod-Enter` to follow the wikilink, tag, file pill, or Markdown link
|
|
7067
|
+
* under the caret, and plain `Enter` to follow a selected atom unit (a
|
|
7068
|
+
* wikilink, file pill, or image), firing the same handlers a click does.
|
|
7069
|
+
* "Under the caret" means strictly inside the unit: a caret merely touching
|
|
7070
|
+
* a unit's edge is next to it, not on it.
|
|
7071
|
+
* Off a link, `Mod-Enter` falls through so the list keymap keeps cycling
|
|
7072
|
+
* checkbox tasks; off a selected unit, `Enter` falls through to the regular
|
|
7073
|
+
* split. High priority puts this ahead of every keymap binding.
|
|
6913
7074
|
*
|
|
6914
|
-
*
|
|
6915
|
-
*
|
|
6916
|
-
*
|
|
6917
|
-
*
|
|
6918
|
-
* raises the software keyboard before the handler opens its own surface
|
|
6919
|
-
* (such as a lightbox).
|
|
7075
|
+
* A selected-unit follow reports `mod: true` when the platform's mod key
|
|
7076
|
+
* (`⌘` on Apple, `Ctrl` elsewhere) was held beyond its plain-`Enter` trigger;
|
|
7077
|
+
* a caret follow always reports `mod: false`, its mod key being the trigger
|
|
7078
|
+
* itself.
|
|
6920
7079
|
*/
|
|
6921
|
-
function
|
|
6922
|
-
|
|
6923
|
-
const handleTouchEnd = (view, event) => {
|
|
6924
|
-
const pending = pendingTaps.get(view);
|
|
6925
|
-
pendingTaps.delete(view);
|
|
6926
|
-
if (!pending || event.touches.length > 0) return false;
|
|
6927
|
-
const touch = findTouch(event.changedTouches, pending.identifier);
|
|
6928
|
-
if (!touch || !isWithinTapTolerance(pending, touch)) return false;
|
|
6929
|
-
const preview = getClosestImagePreview(event.target);
|
|
6930
|
-
if (!preview) return false;
|
|
6931
|
-
event.preventDefault();
|
|
6932
|
-
const hit = findImageForPreview(view, preview);
|
|
6933
|
-
if (hit) onClick({
|
|
6934
|
-
src: hit.src,
|
|
6935
|
-
alt: hit.alt,
|
|
6936
|
-
event
|
|
6937
|
-
});
|
|
6938
|
-
return true;
|
|
6939
|
-
};
|
|
6940
|
-
return definePlugin(new Plugin({
|
|
6941
|
-
key: imageClickKey,
|
|
6942
|
-
props: {
|
|
6943
|
-
handleDOMEvents: {
|
|
6944
|
-
pointerdown: (view, event) => {
|
|
6945
|
-
if (getClosestImagePreview(event.target) && event.pointerType !== "mouse") event.preventDefault();
|
|
6946
|
-
return false;
|
|
6947
|
-
},
|
|
6948
|
-
touchstart: (view, event) => {
|
|
6949
|
-
pendingTaps.delete(view);
|
|
6950
|
-
if (event.touches.length !== 1) return false;
|
|
6951
|
-
if (!getClosestImagePreview(event.target)) return false;
|
|
6952
|
-
if (event.target instanceof HTMLElement && event.target.closest(".md-image-resize-handle")) return false;
|
|
6953
|
-
const touch = event.changedTouches[0];
|
|
6954
|
-
if (!touch) return false;
|
|
6955
|
-
pendingTaps.set(view, {
|
|
6956
|
-
identifier: touch.identifier,
|
|
6957
|
-
clientX: touch.clientX,
|
|
6958
|
-
clientY: touch.clientY
|
|
6959
|
-
});
|
|
6960
|
-
return false;
|
|
6961
|
-
},
|
|
6962
|
-
touchmove: (view, event) => {
|
|
6963
|
-
const pending = pendingTaps.get(view);
|
|
6964
|
-
if (!pending) return false;
|
|
6965
|
-
const touch = findTouch(event.changedTouches, pending.identifier);
|
|
6966
|
-
if (touch && !isWithinTapTolerance(pending, touch)) pendingTaps.delete(view);
|
|
6967
|
-
return false;
|
|
6968
|
-
},
|
|
6969
|
-
touchcancel: (view) => {
|
|
6970
|
-
pendingTaps.delete(view);
|
|
6971
|
-
return false;
|
|
6972
|
-
},
|
|
6973
|
-
touchend: handleTouchEnd
|
|
6974
|
-
},
|
|
6975
|
-
handleClick: (view, _pos, event) => {
|
|
6976
|
-
const preview = getClosestImagePreview(event.target);
|
|
6977
|
-
if (!preview) return false;
|
|
6978
|
-
const hit = findImageForPreview(view, preview);
|
|
6979
|
-
if (!hit) return false;
|
|
6980
|
-
onClick({
|
|
6981
|
-
src: hit.src,
|
|
6982
|
-
alt: hit.alt,
|
|
6983
|
-
event
|
|
6984
|
-
});
|
|
6985
|
-
return true;
|
|
6986
|
-
}
|
|
6987
|
-
}
|
|
6988
|
-
}));
|
|
7080
|
+
function defineFollowLinkHandler(handlers) {
|
|
7081
|
+
return withPriority$1(definePlugin(createFollowLinkPlugin(handlers)), Priority$1.high);
|
|
6989
7082
|
}
|
|
6990
7083
|
|
|
6991
7084
|
//#endregion
|
|
@@ -7315,7 +7408,8 @@ function defineLinkClickHandler(onClick) {
|
|
|
7315
7408
|
findPayloadAt: (state, pos) => getLinkUnitAt(state, pos)?.href,
|
|
7316
7409
|
onClick: (href, event) => onClick({
|
|
7317
7410
|
href,
|
|
7318
|
-
event
|
|
7411
|
+
event,
|
|
7412
|
+
mod: isModEvent(event)
|
|
7319
7413
|
})
|
|
7320
7414
|
});
|
|
7321
7415
|
}
|
|
@@ -8043,4 +8137,4 @@ function getVirtualElementFromRange(view, range) {
|
|
|
8043
8137
|
}
|
|
8044
8138
|
|
|
8045
8139
|
//#endregion
|
|
8046
|
-
export { EDITOR_KEY_BINDINGS, Priority, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSpellCheckPlugin, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getFileKind, getIsComposing, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isMarkOfType, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, parseWikiEmbed, removeLink, renderMathInto, updateLink, wikiEmbedBasename, withPriority };
|
|
8140
|
+
export { EDITOR_KEY_BINDINGS, Priority, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSpellCheckPlugin, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getFileKind, getIsComposing, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isMarkOfType, isModEvent, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, parseWikiEmbed, removeLink, renderMathInto, updateLink, wikiEmbedBasename, withPriority };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meowdown/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.65.0",
|
|
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.
|
|
46
|
+
"@meowdown/markdown": "^0.65.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@ocavue/tsconfig": "^0.7.1",
|