@meowdown/core 0.67.2 → 0.68.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/README.md CHANGED
@@ -31,7 +31,7 @@ const markdown = docToMarkdown(editor.state.doc)
31
31
 
32
32
  [CommonMark](https://commonmark.org/) and [GFM](https://github.github.com/gfm/), plus:
33
33
 
34
- - Wikilinks (`[[target]]`, `[[target|alias]]`)
34
+ - Wikilinks (`[[target]]`; alias forms such as `[[target|alias]]` are the host's to split via `resolveWikilink`)
35
35
  - Wiki embeds (`![[path]]`)
36
36
  - Tags (`#tag`)
37
37
  - Highlight (`==highlight==`)
package/dist/index.d.ts CHANGED
@@ -215,7 +215,14 @@ interface MdLinkTextAttrs {
215
215
  href: string;
216
216
  }
217
217
  interface MdWikilinkAttrs {
218
+ /**
219
+ * Target passed to click and hover handlers: the bracketed text unless the
220
+ * host's `resolveWikilink` replaced it.
221
+ */
218
222
  target: string;
223
+ /**
224
+ * Label shown in place of the source, or `''` to show the target.
225
+ */
219
226
  display: string;
220
227
  }
221
228
  /**
@@ -593,6 +600,45 @@ export declare function formatSizedWikiEmbed(target: string, width: number, heig
593
600
  */
594
601
  export declare function wikiEmbedBasename(target: string): string;
595
602
  //#endregion
603
+ //#region src/extensions/wikilink.d.ts
604
+ /**
605
+ * What {@link WikilinkResolver} sees for one `[[...]]` wikilink.
606
+ */
607
+ interface WikilinkPayload {
608
+ /**
609
+ * The text between the brackets, trimmed. Meowdown reads no syntax inside
610
+ * it: an alias form such as `[[target|alias]]` arrives here whole.
611
+ */
612
+ target: string;
613
+ }
614
+ /**
615
+ * A resolved wikilink.
616
+ */
617
+ interface WikilinkResolution {
618
+ /**
619
+ * Target passed to click and hover handlers. Defaults to the bracketed text.
620
+ */
621
+ target?: string;
622
+ /**
623
+ * Label shown in place of the source. Defaults to the target.
624
+ */
625
+ display?: string;
626
+ }
627
+ /**
628
+ * Resolves one `[[...]]` wikilink into the target its handlers receive and
629
+ * the label its chip shows; the Markdown source stays as written. Return
630
+ * `undefined` to use the bracketed text as both. The resolver participates
631
+ * in the parse cache, so it must be pure: the same payload must always
632
+ * return the same result.
633
+ */
634
+ type WikilinkResolver = (link: WikilinkPayload) => WikilinkResolution | undefined;
635
+ /**
636
+ * Host options for wikilink parsing.
637
+ */
638
+ interface WikilinkOptions {
639
+ resolveWikilink?: WikilinkResolver;
640
+ }
641
+ //#endregion
596
642
  //#region src/extensions/inline-text-to-mark-chunks.d.ts
597
643
  /**
598
644
  * What {@link FileLinkResolver} sees for one `[label](url)` link.
@@ -632,7 +678,7 @@ interface FileLinkOptions {
632
678
  /**
633
679
  * Host options that influence source-backed inline atom parsing.
634
680
  */
635
- type InlineMarkOptions = FileLinkOptions & WikiEmbedOptions;
681
+ type InlineMarkOptions = FileLinkOptions & WikiEmbedOptions & WikilinkOptions;
636
682
  interface InlineMarkContext {
637
683
  /**
638
684
  * Effective document-wide definitions, keyed by normalized reference label.
@@ -861,9 +907,9 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
861
907
  type EditorExtension = ReturnType<typeof defineEditorExtensionImpl>;
862
908
  /**
863
909
  * Options for {@link defineEditorExtension}. Creation-time configuration:
864
- * `resolveFileLink` and `resolveWikiEmbed` are baked into the editor's parse
865
- * pipeline, so changing them requires rebuilding the editor; `markMode` is
866
- * only the initial value.
910
+ * `resolveFileLink`, `resolveWikiEmbed`, and `resolveWikilink` are baked into
911
+ * the editor's parse pipeline, so changing them requires rebuilding the
912
+ * editor; `markMode` is only the initial value.
867
913
  */
868
914
  type EditorExtensionOptions = InlineMarkOptions & {
869
915
  /**
@@ -1594,4 +1640,4 @@ export declare function getSelectedText(state: EditorState): string;
1594
1640
  */
1595
1641
  export declare function getVirtualElementFromRange(view: EditorView, range: PositionRange): VirtualElement;
1596
1642
  //#endregion
1597
- export { type AcceptPendingReplacementOptions, type CheckRoundTripOptions, type CodeBlockAttrs, type CodeBlockFenceStyle, type CodeToken, type DocToMarkdownOptions, 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 LinkHoverOptions, type LinkPreview, type LinkPreviewResolver, 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, defineCodeBlockPreviewPlugin, definePlaceholder, defineReadonly, defineSearchStatusHandler, getSearchStatus, isCodeBlockPreviewHiddenDecoration, withPriority };
1643
+ export { type AcceptPendingReplacementOptions, type CheckRoundTripOptions, type CodeBlockAttrs, type CodeBlockFenceStyle, type CodeToken, type DocToMarkdownOptions, 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 LinkHoverOptions, type LinkPreview, type LinkPreviewResolver, 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, type WikilinkOptions, type WikilinkPayload, type WikilinkResolution, type WikilinkResolver, defineCodeBlockPreviewPlugin, definePlaceholder, defineReadonly, defineSearchStatusHandler, getSearchStatus, isCodeBlockPreviewHiddenDecoration, withPriority };
package/dist/index.js CHANGED
@@ -3042,67 +3042,6 @@ function wikiEmbedBasename(target) {
3042
3042
  }
3043
3043
  }
3044
3044
 
3045
- //#endregion
3046
- //#region src/extensions/wikilink.ts
3047
- /**
3048
- * Splits `[[target]]`/`[[target|alias]]` into its target and display label (the alias, or empty).
3049
- */
3050
- function parseWikilink(text) {
3051
- const inner = text.replace(/^\[\[/, "").replace(/\]\]$/, "");
3052
- const pipe = inner.indexOf("|");
3053
- if (pipe < 0) return {
3054
- target: inner.trim(),
3055
- display: ""
3056
- };
3057
- return {
3058
- target: inner.slice(0, pipe).trim(),
3059
- display: inner.slice(pipe + 1).trim()
3060
- };
3061
- }
3062
- /**
3063
- * Render `mdWikilink` as a non-editable label standing in for the raw source.
3064
- * The source stays in `contentDOM` after the label, hidden by `style.css`
3065
- * (`.md-atom-view-content`); the whole wikilink is one caret stop owned by
3066
- * `defineAtomMarkNavigation`.
3067
- */
3068
- function createWikilinkMarkView() {
3069
- return (mark) => {
3070
- const attrs = mark.attrs;
3071
- const dom = document.createElement("span");
3072
- dom.className = "md-wikilink-view md-atom-view";
3073
- const preview = document.createElement("span");
3074
- preview.className = "md-wikilink-view-preview md-atom-view-preview";
3075
- preview.contentEditable = "false";
3076
- preview.dataset.testid = "wikilink";
3077
- dom.appendChild(preview);
3078
- const label = document.createElement("span");
3079
- label.className = "md-wikilink-view-label";
3080
- label.contentEditable = "false";
3081
- label.textContent = attrs.display || attrs.target;
3082
- preview.appendChild(label);
3083
- const contentDOM = document.createElement("span");
3084
- contentDOM.className = "md-wikilink-view-content md-atom-view-content";
3085
- dom.appendChild(contentDOM);
3086
- return {
3087
- dom,
3088
- contentDOM,
3089
- ignoreMutation: (mutation) => !contentDOM.contains(mutation.target)
3090
- };
3091
- };
3092
- }
3093
- /**
3094
- * Render `[[target]]`/`[[target|alias]]` as an immutable inline label (a mark
3095
- * view) standing in for the raw source. The single-caret-stop behavior comes
3096
- * from the shared `defineAtomMarkNavigation` in the editor extension, which
3097
- * treats `mdWikilink` (and `mdImage`) as one unit.
3098
- */
3099
- function defineWikilink() {
3100
- return defineMarkView({
3101
- name: "mdWikilink",
3102
- constructor: createWikilinkMarkView()
3103
- });
3104
- }
3105
-
3106
3045
  //#endregion
3107
3046
  //#region src/extensions/inline-text-to-mark-chunks.ts
3108
3047
  /**
@@ -3225,7 +3164,7 @@ function walkAtomChild(nodes, index, parentMarks, text, marks, out, options, con
3225
3164
  const node = nodes[index];
3226
3165
  switch (node.type) {
3227
3166
  case LEZER_NODE_IDS.Wikilink:
3228
- walkWikilink(node, parentMarks, text, marks, out);
3167
+ walkWikilink(node, parentMarks, text, marks, out, options);
3229
3168
  return node.to;
3230
3169
  case LEZER_NODE_IDS.WikiEmbed:
3231
3170
  walkWikiEmbed(node, parentMarks, text, marks, out, options);
@@ -3581,16 +3520,18 @@ function walkMath(node, parentMarks, text, marks, out) {
3581
3520
  emit(out, markNodes[1].from, node.to, [...base, marks.mdMark.create()]);
3582
3521
  }
3583
3522
  /**
3584
- * Special walker for a wikilink `[[target]]`/`[[target|alias]]`.
3523
+ * Special walker for a wikilink `[[...]]`. The bracketed text is the target
3524
+ * and the label unless the host's `resolveWikilink` replaces either.
3585
3525
  */
3586
- function walkWikilink(node, parentMarks, text, marks, out) {
3587
- const { target, display } = parseWikilink(text.slice(node.from, node.to));
3526
+ function walkWikilink(node, parentMarks, text, marks, out, options) {
3527
+ const source = text.slice(node.from + 2, node.to - 2).trim();
3528
+ const resolution = options?.resolveWikilink?.({ target: source });
3588
3529
  emit(out, node.from, node.to, [
3589
3530
  ...parentMarks,
3590
3531
  createUnitPack(marks, out, parentMarks, node.from, { key: "wikilink" }),
3591
3532
  marks.mdWikilink.create({
3592
- target,
3593
- display
3533
+ target: resolution?.target ?? source,
3534
+ display: resolution?.display ?? ""
3594
3535
  })
3595
3536
  ]);
3596
3537
  }
@@ -4045,7 +3986,7 @@ function defineMdTag() {
4045
3986
  });
4046
3987
  }
4047
3988
  /**
4048
- * Covers the whole `[[target]]`/`[[target|alias]]` source.
3989
+ * Covers the whole `[[...]]` source.
4049
3990
  */
4050
3991
  function defineMdWikilink() {
4051
3992
  return defineMarkSpec({
@@ -6084,6 +6025,52 @@ function defineViewAttributes(attributes) {
6084
6025
  return definePlugin(new Plugin({ props: { attributes } }));
6085
6026
  }
6086
6027
 
6028
+ //#endregion
6029
+ //#region src/extensions/wikilink.ts
6030
+ /**
6031
+ * Render `mdWikilink` as a non-editable label standing in for the raw source.
6032
+ * The source stays in `contentDOM` after the label, hidden by `style.css`
6033
+ * (`.md-atom-view-content`); the whole wikilink is one caret stop owned by
6034
+ * `defineAtomMarkNavigation`.
6035
+ */
6036
+ function createWikilinkMarkView() {
6037
+ return (mark) => {
6038
+ const attrs = mark.attrs;
6039
+ const dom = document.createElement("span");
6040
+ dom.className = "md-wikilink-view md-atom-view";
6041
+ const preview = document.createElement("span");
6042
+ preview.className = "md-wikilink-view-preview md-atom-view-preview";
6043
+ preview.contentEditable = "false";
6044
+ preview.dataset.testid = "wikilink";
6045
+ dom.appendChild(preview);
6046
+ const label = document.createElement("span");
6047
+ label.className = "md-wikilink-view-label";
6048
+ label.contentEditable = "false";
6049
+ label.textContent = attrs.display || attrs.target;
6050
+ preview.appendChild(label);
6051
+ const contentDOM = document.createElement("span");
6052
+ contentDOM.className = "md-wikilink-view-content md-atom-view-content";
6053
+ dom.appendChild(contentDOM);
6054
+ return {
6055
+ dom,
6056
+ contentDOM,
6057
+ ignoreMutation: (mutation) => !contentDOM.contains(mutation.target)
6058
+ };
6059
+ };
6060
+ }
6061
+ /**
6062
+ * Render `[[...]]` as an immutable inline label (a mark
6063
+ * view) standing in for the raw source. The single-caret-stop behavior comes
6064
+ * from the shared `defineAtomMarkNavigation` in the editor extension, which
6065
+ * treats `mdWikilink` (and `mdImage`) as one unit.
6066
+ */
6067
+ function defineWikilink() {
6068
+ return defineMarkView({
6069
+ name: "mdWikilink",
6070
+ constructor: createWikilinkMarkView()
6071
+ });
6072
+ }
6073
+
6087
6074
  //#endregion
6088
6075
  //#region src/extensions/extension.ts
6089
6076
  function defineEditorExtensionImpl(options) {
package/dist/style.css CHANGED
@@ -408,6 +408,11 @@
408
408
  margin-top: .25em;
409
409
  }
410
410
 
411
+ .ProseMirror .prosemirror-flat-list > .list-marker {
412
+ -webkit-user-select: none;
413
+ user-select: none;
414
+ }
415
+
411
416
  .ProseMirror .prosemirror-flat-list[data-list-kind="bullet"] > .list-marker {
412
417
  background: radial-gradient(circle at center,
413
418
  var(--meowdown-bullet) 0 var(--meowdown-bullet-radius),
@@ -558,6 +563,11 @@
558
563
  margin: 1.5em 0;
559
564
  }
560
565
 
566
+ .ProseMirror .prosekit-horizontal-rule {
567
+ -webkit-user-select: none;
568
+ user-select: none;
569
+ }
570
+
561
571
  .ProseMirror table {
562
572
  border-collapse: collapse;
563
573
  table-layout: fixed;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/core",
3
3
  "type": "module",
4
- "version": "0.67.2",
4
+ "version": "0.68.1",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -26,12 +26,12 @@
26
26
  "@floating-ui/dom": "^1.8.0",
27
27
  "@lezer/highlight": "^1.2.3",
28
28
  "@ocavue/utils": "^1.7.0",
29
- "@prosekit/core": "^0.13.1",
30
- "@prosekit/extensions": "^0.18.1",
29
+ "@prosekit/core": "^0.13.2",
30
+ "@prosekit/extensions": "^0.18.2",
31
31
  "@prosekit/pm": "^0.1.19",
32
- "@prosekit/web": "^0.9.1",
32
+ "@prosekit/web": "^0.9.2",
33
33
  "hast-util-to-mdast": "^10.1.2",
34
- "katex": "^0.18.1",
34
+ "katex": "^0.18.5",
35
35
  "mdast-util-to-markdown": "^2.1.2",
36
36
  "micromark-util-decode-string": "^2.0.1",
37
37
  "micromark-util-normalize-identifier": "^2.0.1",
@@ -43,19 +43,19 @@
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.2"
46
+ "@meowdown/markdown": "^0.68.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@ocavue/tsconfig": "^0.7.1",
50
- "@tsdown/css": "^0.23.0-beta.2",
50
+ "@tsdown/css": "^0.23.0-rc.1",
51
51
  "@types/hast": "^3.0.5",
52
52
  "@types/mdast": "^4.0.4",
53
- "@vitest/browser-playwright": "^4.1.11",
53
+ "@vitest/browser-playwright": "^5.0.0",
54
54
  "commonmark.json": "^0.31.0",
55
55
  "dedent": "^1.7.2",
56
56
  "diffable-html-snapshot": "^0.3.0",
57
- "tsdown": "^0.23.0-beta.2",
58
- "vitest": "^4.1.11",
57
+ "tsdown": "^0.23.0-rc.1",
58
+ "vitest": "^5.0.0",
59
59
  "vitest-browser-commands": "^0.4.1",
60
60
  "@meowdown/vitest": "0.0.0"
61
61
  },