@meowdown/core 0.67.0 → 0.67.2

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
@@ -319,6 +319,7 @@ interface PositionRange {
319
319
  //#endregion
320
320
  //#region src/extensions/get-link-unit-at.d.ts
321
321
  interface LinkUnitBase {
322
+ state: EditorState;
322
323
  /**
323
324
  * Whole inline link, reference link, or autolink range.
324
325
  */
@@ -382,7 +383,7 @@ export declare function normalizeHref(raw: string): string;
382
383
  /**
383
384
  * Get a link's plain visible text.
384
385
  */
385
- export declare function getLinkText(state: EditorState, link: LinkUnit): string;
386
+ export declare function getLinkText(link: LinkUnit): string;
386
387
  /**
387
388
  * Whether plain visible link text names the same destination as the link.
388
389
  */
package/dist/index.js CHANGED
@@ -190,7 +190,9 @@ function computeRevealDecorations(state, mode) {
190
190
  });
191
191
  }
192
192
  if (ranges.length === 0) return;
193
- const decorations = ranges.map((range) => Decoration.inline(range.from, range.to, { class: "show" }));
193
+ const decorations = ranges.map((range) => {
194
+ return Decoration.inline(range.from, range.to, { class: "show" });
195
+ });
194
196
  return DecorationSet.create(state.doc, decorations);
195
197
  }
196
198
  function defineMarkMode(mode) {
@@ -962,11 +964,13 @@ function headingFromDOM() {
962
964
  4,
963
965
  5,
964
966
  6
965
- ].map((level) => createSourceTextRule(`h${level}`, "heading", (dom) => ({
966
- level,
967
- setextUnderline: parsePositiveInteger(dom.getAttribute("data-setext-underline")) ?? null,
968
- closingHashes: parsePositiveInteger(dom.getAttribute("data-closing-hashes")) ?? null
969
- })));
967
+ ].map((level) => {
968
+ return createSourceTextRule(`h${level}`, "heading", (dom) => ({
969
+ level,
970
+ setextUnderline: parsePositiveInteger(dom.getAttribute("data-setext-underline")) ?? null,
971
+ closingHashes: parsePositiveInteger(dom.getAttribute("data-closing-hashes")) ?? null
972
+ }));
973
+ });
970
974
  }
971
975
  function defineSetextUnderlineAttr() {
972
976
  return defineNodeAttr({
@@ -4428,11 +4432,13 @@ function toggleInline(spec) {
4428
4432
  return false;
4429
4433
  });
4430
4434
  const remove = segments.length > 0 && segments.every((segment) => segment.active);
4431
- const edits = segments.filter((segment) => remove || !segment.active).flatMap((segment) => toggleInlineEdits(segment.text, segment.from, segment.to, spec, remove).map((edit) => ({
4432
- from: edit.from + segment.base,
4433
- to: edit.to + segment.base,
4434
- insert: edit.insert
4435
- })));
4435
+ const edits = segments.filter((segment) => remove || !segment.active).flatMap((segment) => {
4436
+ return toggleInlineEdits(segment.text, segment.from, segment.to, spec, remove).map((edit) => ({
4437
+ from: edit.from + segment.base,
4438
+ to: edit.to + segment.base,
4439
+ insert: edit.insert
4440
+ }));
4441
+ });
4436
4442
  if (edits.length === 0) return false;
4437
4443
  if (dispatch) {
4438
4444
  const tr = state.tr;
@@ -4513,7 +4519,9 @@ function lastMarkRunIn(state, range, markName) {
4513
4519
  * the `mdLinkUri` run locates the `( )` body.
4514
4520
  */
4515
4521
  function getLinkUnitAt(state, pos) {
4516
- const unit = getMarkRangeAt(state, pos, "mdPack", (mark) => mark.attrs.key.startsWith("link-"));
4522
+ const unit = getMarkRangeAt(state, pos, "mdPack", (mark) => {
4523
+ return mark.attrs.key.startsWith("link-");
4524
+ });
4517
4525
  if (!unit) return;
4518
4526
  const attrs = unit.mark.attrs;
4519
4527
  const unitRange = {
@@ -4522,6 +4530,7 @@ function getLinkUnitAt(state, pos) {
4522
4530
  };
4523
4531
  switch (attrs.key) {
4524
4532
  case "link-bare": return {
4533
+ state,
4525
4534
  form: "bare",
4526
4535
  unit: unitRange,
4527
4536
  text: unitRange,
@@ -4529,6 +4538,7 @@ function getLinkUnitAt(state, pos) {
4529
4538
  title: ""
4530
4539
  };
4531
4540
  case "link-angle": return {
4541
+ state,
4532
4542
  form: "angle",
4533
4543
  unit: unitRange,
4534
4544
  text: {
@@ -4541,6 +4551,7 @@ function getLinkUnitAt(state, pos) {
4541
4551
  case "link-reference": {
4542
4552
  const linkText = getMarkRangeAt(state, pos, "mdLinkText");
4543
4553
  return {
4554
+ state,
4544
4555
  form: "reference",
4545
4556
  unit: unitRange,
4546
4557
  text: linkText == null ? unitRange : {
@@ -4560,6 +4571,7 @@ function getLinkUnitAt(state, pos) {
4560
4571
  to: closeBracket
4561
4572
  };
4562
4573
  return {
4574
+ state,
4563
4575
  form: "inline",
4564
4576
  unit: unitRange,
4565
4577
  text: label,
@@ -4613,8 +4625,8 @@ function getVisibleText(state, range) {
4613
4625
  /**
4614
4626
  * Get a link's plain visible text.
4615
4627
  */
4616
- function getLinkText(state, link) {
4617
- return getVisibleText(state, link.text);
4628
+ function getLinkText(link) {
4629
+ return getVisibleText(link.state, link.text);
4618
4630
  }
4619
4631
  /**
4620
4632
  * Whether plain visible link text names the same destination as the link.
@@ -4677,7 +4689,7 @@ function updateLink(attrs) {
4677
4689
  if (!link || link.form === "reference") return false;
4678
4690
  const href = normalizeHref(attrs.href ?? link.href);
4679
4691
  const title = attrs.title ?? link.title;
4680
- const text = attrs.text ?? getLinkText(state, link);
4692
+ const text = attrs.text ?? getLinkText(link);
4681
4693
  const replacingUnit = attrs.text !== void 0 || link.form !== "inline";
4682
4694
  if (dispatch) dispatch((replacingUnit ? state.tr.insertText(`[${linkLabelText(text)}](${destText(href, title)})`, link.unit.from, link.unit.to) : state.tr.insertText(destText(href, title), link.dest.from, link.dest.to)).scrollIntoView());
4683
4695
  return true;
@@ -4691,7 +4703,7 @@ function removeLink() {
4691
4703
  const link = getLinkUnitAt(state, state.selection.from);
4692
4704
  if (!link || link.form === "reference") return false;
4693
4705
  if (dispatch) {
4694
- const text = getLinkText(state, link);
4706
+ const text = getLinkText(link);
4695
4707
  dispatch((link.form === "inline" && !getAutolinkHref(text) ? state.tr.delete(link.label.to, link.unit.to).delete(link.unit.from, link.label.from) : state.tr.insertText(text + formatMagicComment({ noLink: true }), link.unit.from, link.unit.to)).scrollIntoView());
4696
4708
  }
4697
4709
  return true;
@@ -4717,7 +4729,7 @@ function openLinkEdit(onLinkEdit) {
4717
4729
  from,
4718
4730
  to,
4719
4731
  link,
4720
- text: getLinkText(state, link)
4732
+ text: getLinkText(link)
4721
4733
  });
4722
4734
  }
4723
4735
  return true;
@@ -5733,7 +5745,8 @@ function tryCoordsAtPos(view, pos, side) {
5733
5745
  let coords;
5734
5746
  try {
5735
5747
  coords = view.coordsAtPos(pos, side);
5736
- } catch {
5748
+ } catch (error) {
5749
+ console.warn(`[meowdown] Failed to get caret coords at pos ${pos}:`, error);
5737
5750
  return;
5738
5751
  }
5739
5752
  return isPointRect(coords) ? void 0 : coords;
@@ -5754,9 +5767,12 @@ function findNativeCaretRect(view) {
5754
5767
  if (!view.dom.contains(selection.anchorNode)) return void 0;
5755
5768
  const range = selection.getRangeAt(0).cloneRange();
5756
5769
  range.collapse(true);
5770
+ return findLastRangeRect(range);
5771
+ }
5772
+ function findLastRangeRect(range) {
5757
5773
  const rects = Array.from(range.getClientRects()).filter((rect) => rect.height > 0);
5758
- if (rects.length === 0) return void 0;
5759
5774
  const rect = rects[rects.length - 1];
5775
+ if (rect == null) return void 0;
5760
5776
  return {
5761
5777
  left: rect.left,
5762
5778
  top: rect.top,
@@ -5769,18 +5785,35 @@ function findCoordsCaretRect(view) {
5769
5785
  const runBefore = getHiddenRunBefore(state, head);
5770
5786
  const runAfter = getHiddenRunAfter(state, head);
5771
5787
  const afterLineBreak = isAfterLineBreak($head);
5772
- const preferredBeforeSide = runBefore == null && !afterLineBreak;
5773
- const probes = [[head, preferredBeforeSide], [head, !preferredBeforeSide]];
5788
+ const previousLineTop = afterLineBreak ? tryCoordsAtPos(view, head, -1)?.top : void 0;
5789
+ const probes = afterLineBreak ? [[head, false]] : [[head, runBefore == null], [head, runBefore != null]];
5774
5790
  if (runBefore != null) probes.push([runBefore.from, true]);
5775
5791
  if (runAfter != null) probes.push([runAfter.to, false]);
5776
5792
  for (const [pos, beforeSide] of probes) {
5777
5793
  const coords = tryCoordsAtPos(view, pos, beforeSide ? -1 : 1);
5778
- if (coords != null && coords.bottom > coords.top) return {
5794
+ if (coords == null || coords.bottom <= coords.top) continue;
5795
+ if (pos === head && previousLineTop != null && coords.top <= previousLineTop) continue;
5796
+ return {
5779
5797
  left: coords.left,
5780
5798
  top: coords.top,
5781
5799
  height: coords.bottom - coords.top
5782
5800
  };
5783
5801
  }
5802
+ if (previousLineTop != null) {
5803
+ const collapsed = findCollapsedRangeRect(view, head);
5804
+ if (collapsed != null && collapsed.top > previousLineTop) return collapsed;
5805
+ }
5806
+ }
5807
+ function findCollapsedRangeRect(view, pos) {
5808
+ try {
5809
+ const { node, offset } = view.domAtPos(pos, 0);
5810
+ const range = view.dom.ownerDocument.createRange();
5811
+ range.setStart(node, offset);
5812
+ range.collapse(true);
5813
+ return findLastRangeRect(range);
5814
+ } catch {
5815
+ return;
5816
+ }
5784
5817
  }
5785
5818
  function findAtomCaretRect(view) {
5786
5819
  const state = view.state;
package/dist/style.css CHANGED
@@ -691,6 +691,10 @@
691
691
  display: contents;
692
692
  }
693
693
 
694
+ .ProseMirror .md-pack[data-key="noLink"] {
695
+ display: inline;
696
+ }
697
+
694
698
  .ProseMirror[data-mark-mode="hide"], .ProseMirror[data-mark-mode="focus"] {
695
699
  & .md-mark, & .md-link-uri, & .md-link-title {
696
700
  letter-spacing: 0;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/core",
3
3
  "type": "module",
4
- "version": "0.67.0",
4
+ "version": "0.67.2",
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.67.0"
46
+ "@meowdown/markdown": "^0.67.2"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@ocavue/tsconfig": "^0.7.1",
@@ -54,9 +54,9 @@
54
54
  "commonmark.json": "^0.31.0",
55
55
  "dedent": "^1.7.2",
56
56
  "diffable-html-snapshot": "^0.3.0",
57
- "fast-check": "^4.9.0",
58
57
  "tsdown": "^0.23.0-beta.2",
59
58
  "vitest": "^4.1.11",
59
+ "vitest-browser-commands": "^0.4.1",
60
60
  "@meowdown/vitest": "0.0.0"
61
61
  },
62
62
  "publishConfig": {