@meowdown/core 0.65.0 → 0.65.1

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 CHANGED
@@ -810,7 +810,7 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
810
810
  Commands: {
811
811
  setMarkMode: [mode: MarkMode];
812
812
  };
813
- }>]>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").BaseCommandsExtension, import("@prosekit/core").HistoryExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Extension<{
813
+ }>]>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").BaseCommandsExtension, import("@prosekit/core").HistoryExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Extension<{
814
814
  Commands: {
815
815
  insertMarkdown: [markdown: string];
816
816
  insertTrigger: [text: string];
@@ -1396,6 +1396,9 @@ type NodeName = (typeof NODE_NAMES)[number];
1396
1396
  declare function isNodeOfType(node: ProseMirrorNode, name: NodeName): boolean;
1397
1397
  //#endregion
1398
1398
  //#region src/extensions/spell-check.d.ts
1399
+ /**
1400
+ * @deprecated This will be removed in future versions.
1401
+ */
1399
1402
  declare function defineSpellCheckPlugin(spellCheck: boolean): PlainExtension;
1400
1403
  //#endregion
1401
1404
  //#region src/extensions/substitution.d.ts
package/dist/index.js CHANGED
@@ -2537,7 +2537,7 @@ const emptyBatchSetMarkStep = new BatchSetMarkStep([]);
2537
2537
  //#endregion
2538
2538
  //#region src/extensions/magic-comment.ts
2539
2539
  const MAGIC_COMMENT_RE = /^<!--\s*(\{[^}]*\})\s*-->$/;
2540
- const TRAILING_MAGIC_COMMENT_RE = /<!--\s*\{[^}]*\}\s*-->$/;
2540
+ const TRAILING_MAGIC_COMMENT_RE = /(?:<!--\s*\{[^}]*\}\s*-->)+$/;
2541
2541
  /**
2542
2542
  * Read the metadata out of a `<!-- {...} -->` comment, or `undefined` when the
2543
2543
  * text is not a comment carrying at least one recognized field.
@@ -2570,7 +2570,7 @@ function formatMagicComment(magic) {
2570
2570
  return `<!-- ${JSON.stringify(magic)} -->`;
2571
2571
  }
2572
2572
  /**
2573
- * Drop a trailing magic comment from the source text.
2573
+ * Drop the trailing run of magic comments from the source text.
2574
2574
  */
2575
2575
  function stripMagicComment(source) {
2576
2576
  return source.replace(TRAILING_MAGIC_COMMENT_RE, "");
@@ -2889,12 +2889,11 @@ function walk(nodes, parentMarks, rangeStart, rangeEnd, text, marks, out, option
2889
2889
  let pos = rangeStart;
2890
2890
  for (let index = 0; index < nodes.length; index++) {
2891
2891
  const node = nodes[index];
2892
+ if (node.to <= pos) continue;
2892
2893
  if (node.from > pos) emit(out, pos, node.from, parentMarks);
2893
- if (node.type === LEZER_NODE_IDS.Image) {
2894
- const trailing = takeMagicComment(node, nodes[index + 1], text);
2895
- walkImage(node, parentMarks, text, marks, out, options, context, trailing);
2896
- if (trailing) index++;
2897
- pos = trailing ? trailing.to : node.to;
2894
+ const atomEnd = walkAtomChild(nodes, index, parentMarks, text, marks, out, options, context);
2895
+ if (atomEnd != null) {
2896
+ pos = atomEnd;
2898
2897
  continue;
2899
2898
  }
2900
2899
  walkNode(node, parentMarks, text, marks, out, options, context);
@@ -2905,8 +2904,6 @@ function walk(nodes, parentMarks, rangeStart, rangeEnd, text, marks, out, option
2905
2904
  function walkNode(node, parentMarks, text, marks, out, options, context) {
2906
2905
  switch (node.type) {
2907
2906
  case LEZER_NODE_IDS.Link: return walkLink(node, parentMarks, text, marks, out, options, context);
2908
- case LEZER_NODE_IDS.Wikilink: return walkWikilink(node, parentMarks, text, marks, out);
2909
- case LEZER_NODE_IDS.WikiEmbed: return walkWikiEmbed(node, parentMarks, text, marks, out, options);
2910
2907
  case LEZER_NODE_IDS.InlineMath: return walkMath(node, parentMarks, text, marks, out);
2911
2908
  case LEZER_NODE_IDS.Autolink: return walkAutolink(node, parentMarks, text, marks, out);
2912
2909
  case LEZER_NODE_IDS.URL: return walkURL(node, parentMarks, text, marks, out);
@@ -2914,6 +2911,31 @@ function walkNode(node, parentMarks, text, marks, out, options, context) {
2914
2911
  }
2915
2912
  }
2916
2913
  /**
2914
+ * Walk `nodes[index]` when it is a source-backed atom (wikilink, wiki embed,
2915
+ * or image); returns the source position after everything the atom consumed,
2916
+ * or undefined for any other node type. An image also consumes the magic
2917
+ * comments chained behind it, so callers must skip children ending at or
2918
+ * before the returned position. Shared by `walk` and `walkResolvedLink` so an
2919
+ * atom behaves the same at the top level and inside a link label.
2920
+ */
2921
+ function walkAtomChild(nodes, index, parentMarks, text, marks, out, options, context) {
2922
+ const node = nodes[index];
2923
+ switch (node.type) {
2924
+ case LEZER_NODE_IDS.Wikilink:
2925
+ walkWikilink(node, parentMarks, text, marks, out);
2926
+ return node.to;
2927
+ case LEZER_NODE_IDS.WikiEmbed:
2928
+ walkWikiEmbed(node, parentMarks, text, marks, out, options);
2929
+ return node.to;
2930
+ case LEZER_NODE_IDS.Image: {
2931
+ const trailing = takeMagicComments(nodes, index, text);
2932
+ walkImage(node, parentMarks, text, marks, out, options, context, trailing);
2933
+ return trailing ? trailing.to : node.to;
2934
+ }
2935
+ default: return;
2936
+ }
2937
+ }
2938
+ /**
2917
2939
  * A node with no source-backed atom of its own: it contributes its `mdPack` and
2918
2940
  * syntax marks, then recurses into its children.
2919
2941
  */
@@ -3131,25 +3153,17 @@ function walkResolvedLink(node, parts, resolution, parentMarks, text, marks, out
3131
3153
  });
3132
3154
  const base = [...parentMarks, pack];
3133
3155
  let pos = node.from;
3134
- for (const child of node.children) {
3156
+ for (let index = 0; index < node.children.length; index++) {
3157
+ const child = node.children[index];
3158
+ if (child.to <= pos) continue;
3135
3159
  if (child.from > pos) {
3136
3160
  const childMarks = inLabel(pos) ? [...base, linkTextMark] : base;
3137
3161
  emit(out, pos, child.from, childMarks);
3138
3162
  }
3139
3163
  const baseForChild = inLabel(child.from) ? [...base, linkTextMark] : base;
3140
- if (child.type === LEZER_NODE_IDS.Wikilink) {
3141
- walkWikilink(child, baseForChild, text, marks, out);
3142
- pos = child.to;
3143
- continue;
3144
- }
3145
- if (child.type === LEZER_NODE_IDS.WikiEmbed) {
3146
- walkWikiEmbed(child, baseForChild, text, marks, out, options);
3147
- pos = child.to;
3148
- continue;
3149
- }
3150
- if (child.type === LEZER_NODE_IDS.Image) {
3151
- walkImage(child, baseForChild, text, marks, out, options, context);
3152
- pos = child.to;
3164
+ const atomEnd = walkAtomChild(node.children, index, baseForChild, text, marks, out, options, context);
3165
+ if (atomEnd != null) {
3166
+ pos = atomEnd;
3153
3167
  continue;
3154
3168
  }
3155
3169
  if (isReference && child.type === LEZER_NODE_IDS.LinkLabel) {
@@ -3170,19 +3184,33 @@ function walkResolvedLink(node, parts, resolution, parentMarks, text, marks, out
3170
3184
  }
3171
3185
  if (pos < node.to) emit(out, pos, node.to, base);
3172
3186
  }
3173
- function takeMagicComment(image, next, text) {
3174
- if (!next || next.type !== LEZER_NODE_IDS.Comment || next.from !== image.to) return void 0;
3175
- const magic = parseMagicComment(text.slice(next.from, next.to));
3187
+ /**
3188
+ * The run of magic comments chained immediately behind `nodes[index]` (an
3189
+ * image), or undefined when no magic comment directly abuts it. The first
3190
+ * comment's data wins: a rewrite of an unfolded image inserted the fresh
3191
+ * comment right at the image's end, so in a stacked run left is newest.
3192
+ */
3193
+ function takeMagicComments(nodes, index, text) {
3194
+ let magic;
3195
+ let to = nodes[index].to;
3196
+ for (let i = index + 1; i < nodes.length; i++) {
3197
+ const next = nodes[i];
3198
+ if (next.type !== LEZER_NODE_IDS.Comment || next.from !== to) break;
3199
+ const parsed = parseMagicComment(text.slice(next.from, next.to));
3200
+ if (!parsed) break;
3201
+ magic ??= parsed;
3202
+ to = next.to;
3203
+ }
3176
3204
  if (!magic) return void 0;
3177
3205
  return {
3178
3206
  magic,
3179
- to: next.to
3207
+ to
3180
3208
  };
3181
3209
  }
3182
3210
  /**
3183
3211
  * Special walker for a direct image `![alt](url)`.
3184
3212
  *
3185
- * A `trailing` magic comment immediately after the image (e.g.
3213
+ * A `trailing` run of magic comments immediately after the image (e.g.
3186
3214
  * `<!-- {"width":320} -->`) is folded into the mark range so it round-trips as
3187
3215
  * source while supplying the image's `width`.
3188
3216
  */
@@ -5543,6 +5571,33 @@ function defineSelectDocBoundary() {
5543
5571
  });
5544
5572
  }
5545
5573
 
5574
+ //#endregion
5575
+ //#region src/extensions/system-substitution-guard.ts
5576
+ const EM_DASH = "—";
5577
+ /**
5578
+ * Block the macOS "smart dashes" rewrite. With the `spellcheck` attribute on,
5579
+ * WebKit rewrites already-typed `--` near the caret into an em dash and
5580
+ * delivers the rewrite as a cancelable `beforeinput` with
5581
+ * `inputType: 'insertReplacementText'`. That corrupts Markdown such as the
5582
+ * `-->` closing an image sizing comment, so cancel any replacement that
5583
+ * inserts an em dash; word-level autocorrect passes through.
5584
+ */
5585
+ function defineSystemSubstitutionGuard() {
5586
+ const plugin = new Plugin({ props: { handleDOMEvents: { beforeinput: (view, event) => {
5587
+ if (event.inputType !== "insertReplacementText") return false;
5588
+ if (!(event.dataTransfer?.getData("text/plain") || event.data || "").includes(EM_DASH)) return false;
5589
+ event.preventDefault();
5590
+ const { doc, selection } = view.state;
5591
+ requestAnimationFrame(() => {
5592
+ const { state } = view;
5593
+ if (view.isDestroyed || state.doc !== doc || state.selection.eq(selection)) return;
5594
+ view.dispatch(state.tr.setSelection(selection));
5595
+ });
5596
+ return true;
5597
+ } } } });
5598
+ return withPriority$1(definePlugin(plugin), Priority$1.highest);
5599
+ }
5600
+
5546
5601
  //#endregion
5547
5602
  //#region src/extensions/view-attributes.ts
5548
5603
  /**
@@ -5557,7 +5612,7 @@ function defineViewAttributes(attributes) {
5557
5612
  //#endregion
5558
5613
  //#region src/extensions/extension.ts
5559
5614
  function defineEditorExtensionImpl(options) {
5560
- return union(defineMeowdownParagraph(), defineDoc(), defineDocFrontmatterAttr(), defineText(), defineBlockquote(), defineMeowdownList(), defineHeading(), defineTable(), defineCodeBlock$1(), defineMeowdownHorizontalRule(), defineHTMLComment(), defineInlineMarks(), defineViewAttributes({ class: "meowdown-content" }), defineCodeBlockSyntaxHighlight(), defineCrossEditorDrag(), defineEscapeCollapse(), defineMoveBlock(), defineSelectDocBoundary(), defineInlineMarkPlugin(options), defineInlineToggle(), defineLinkCommands(), defineWikilink(), defineMath(), defineMarkMode(options.markMode ?? "focus"), defineClipboard(), defineScrollToSelection(), defineHiddenRunCaret(), defineAtomMarkNavigation({ marks: ATOM_SOURCE_MARK_NAMES.map((name) => ({
5615
+ return union(defineMeowdownParagraph(), defineDoc(), defineDocFrontmatterAttr(), defineText(), defineBlockquote(), defineMeowdownList(), defineHeading(), defineTable(), defineCodeBlock$1(), defineMeowdownHorizontalRule(), defineHTMLComment(), defineInlineMarks(), defineViewAttributes({ class: "meowdown-content" }), defineCodeBlockSyntaxHighlight(), defineCrossEditorDrag(), defineEscapeCollapse(), defineMoveBlock(), defineSelectDocBoundary(), defineInlineMarkPlugin(options), defineInlineToggle(), defineLinkCommands(), defineWikilink(), defineMath(), defineMarkMode(options.markMode ?? "focus"), defineClipboard(), defineScrollToSelection(), defineHiddenRunCaret(), defineSystemSubstitutionGuard(), defineAtomMarkNavigation({ marks: ATOM_SOURCE_MARK_NAMES.map((name) => ({
5561
5616
  name,
5562
5617
  modes: [
5563
5618
  "hide",
@@ -7632,6 +7687,9 @@ function createSpellCheckPlugin(spellCheck) {
7632
7687
  }
7633
7688
  });
7634
7689
  }
7690
+ /**
7691
+ * @deprecated This will be removed in future versions.
7692
+ */
7635
7693
  function defineSpellCheckPlugin(spellCheck) {
7636
7694
  return definePlugin(createSpellCheckPlugin(spellCheck));
7637
7695
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/core",
3
3
  "type": "module",
4
- "version": "0.65.0",
4
+ "version": "0.65.1",
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.65.0"
46
+ "@meowdown/markdown": "^0.65.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@ocavue/tsconfig": "^0.7.1",