@type32/codemirror-rich-obsidian-editor 0.0.25 → 0.0.26

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/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@type32/codemirror-rich-obsidian-editor",
3
3
  "configKey": "cmOfmEditor",
4
- "version": "0.0.25",
4
+ "version": "0.0.26",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -2,5 +2,6 @@ type __VLS_Props = {
2
2
  filePath: string;
3
3
  display?: string;
4
4
  };
5
- declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
6
+ declare const _default: typeof __VLS_export;
6
7
  export default _default;
@@ -1,5 +1,6 @@
1
1
  type __VLS_Props = {
2
2
  codeContent?: string;
3
3
  };
4
- declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
4
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
+ declare const _default: typeof __VLS_export;
5
6
  export default _default;
@@ -10,10 +10,11 @@ type __VLS_Props = {
10
10
  debug?: boolean;
11
11
  searchOptions?: SearchOptions;
12
12
  };
13
- type __VLS_PublicProps = __VLS_Props & {
13
+ type __VLS_ModelProps = {
14
14
  modelValue?: string;
15
15
  };
16
- declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {
16
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
17
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
17
18
  view: import("vue").ShallowRef<EditorView | undefined, EditorView | undefined>;
18
19
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
20
  "internal-link-click": (detail: InternalLinkClickDetail) => any;
@@ -24,4 +25,5 @@ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {
24
25
  "onExternal-link-click"?: ((detail: ExternalLinkClickDetail) => any) | undefined;
25
26
  "onUpdate:modelValue"?: ((value: string | undefined) => any) | undefined;
26
27
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
+ declare const _default: typeof __VLS_export;
27
29
  export default _default;
@@ -1,7 +1,5 @@
1
1
  import { useAlfaaz } from "./useAlfaaz.js";
2
- import { markdown } from "@codemirror/lang-markdown";
3
- import { GFM } from "@lezer/markdown";
4
- import { CustomOFM } from "../editor/lezer-parsers/customOFMParsers.js";
2
+ import { parseMarkdownToAST } from "../utils/markdownParser.js";
5
3
  export function useDocumentUtils() {
6
4
  const alfaaz = useAlfaaz();
7
5
  function getWordCount(text) {
@@ -32,9 +30,7 @@ export function useDocumentUtils() {
32
30
  function getTableOfContents(text) {
33
31
  const toc = [];
34
32
  if (!text) return toc;
35
- const tree = markdown({
36
- extensions: [GFM, CustomOFM, { remove: ["SetextHeading"] }]
37
- }).language.parser.parse(text);
33
+ const tree = parseMarkdownToAST(text);
38
34
  tree.iterate({
39
35
  enter: (node) => {
40
36
  if (node.name.startsWith("ATXHeading")) {
@@ -61,9 +57,7 @@ export function useDocumentUtils() {
61
57
  function getAllTags(text) {
62
58
  const tags = [];
63
59
  if (!text) return tags;
64
- const tree = markdown({
65
- extensions: [GFM, CustomOFM, { remove: ["SetextHeading"] }]
66
- }).language.parser.parse(text);
60
+ const tree = parseMarkdownToAST(text);
67
61
  let frontmatterEnd = 0;
68
62
  const frontmatterNode = tree.topNode.firstChild;
69
63
  if (frontmatterNode && frontmatterNode.name === "Frontmatter") {
@@ -1,5 +1,6 @@
1
- import { load, dump } from "js-yaml";
1
+ import { dump } from "js-yaml";
2
2
  import { useEditorUtils } from "./useEditorUtils.js";
3
+ import { parseFrontmatter } from "../utils/frontmatter.js";
3
4
  export function useEditorFrontmatter(editor) {
4
5
  const editorUtils = useEditorUtils(editor);
5
6
  function getFrontmatter() {
@@ -7,25 +8,7 @@ export function useEditorFrontmatter(editor) {
7
8
  if (!doc) {
8
9
  return {};
9
10
  }
10
- const ast = editorUtils.parseMarkdownToAST(doc);
11
- const firstNode = ast.topNode.firstChild;
12
- if (!firstNode || firstNode.name !== "YAMLFrontMatter") {
13
- return {};
14
- }
15
- const contentNode = firstNode.getChild("YAMLContent");
16
- const yamlContent = contentNode ? doc.slice(contentNode.from, contentNode.to) : "";
17
- try {
18
- const data = load(yamlContent);
19
- if (data === null || data === void 0) {
20
- return { data: {} };
21
- }
22
- if (typeof data === "object") {
23
- return { data };
24
- }
25
- return { error: new Error("Frontmatter is not a valid object.") };
26
- } catch (e) {
27
- return { error: e };
28
- }
11
+ return parseFrontmatter(doc);
29
12
  }
30
13
  function setFrontmatterProperties(properties) {
31
14
  const doc = editorUtils.getDoc() || "";
@@ -1,6 +1,7 @@
1
1
  import type { SyntaxNode, Tree } from '@lezer/common';
2
2
  import type { Ref } from 'vue';
3
3
  import type { TransactionSpec } from '@codemirror/state';
4
+ import { parseMarkdownToAST } from '../utils/markdownParser.js';
4
5
  import type { SearchMatch, SearchOptions } from '../editor/types/editor-types.js';
5
6
  export declare function useEditorUtils(editor: Ref<any>): {
6
7
  getDoc: () => string | undefined;
@@ -8,7 +9,7 @@ export declare function useEditorUtils(editor: Ref<any>): {
8
9
  getSelection: () => any;
9
10
  replaceSelection: (text: string) => void;
10
11
  dispatch: (...specs: TransactionSpec[]) => void;
11
- parseMarkdownToAST: (markdownText: string) => Tree;
12
+ parseMarkdownToAST: typeof parseMarkdownToAST;
12
13
  getDocAst: () => Tree;
13
14
  findNodesByType: (tree: Tree, nodeTypeName: string) => SyntaxNode[];
14
15
  getDocNodesByType: (nodeTypeName: string) => SyntaxNode[];
@@ -1,8 +1,6 @@
1
1
  import { computed, ref, unref } from "vue";
2
2
  import { EditorView } from "@codemirror/view";
3
- import { markdown } from "@codemirror/lang-markdown";
4
- import { CustomOFM } from "../../runtime/editor/lezer-parsers/customOFMParsers";
5
- import { GFM } from "@lezer/markdown";
3
+ import { parseMarkdownToAST } from "../utils/markdownParser.js";
6
4
  export function useEditorUtils(editor) {
7
5
  const view = computed(() => {
8
6
  const instance = unref(editor);
@@ -12,6 +10,18 @@ export function useEditorUtils(editor) {
12
10
  const searchResults = ref([]);
13
11
  const currentMatchIndex = ref(-1);
14
12
  const searchQuery = ref(null);
13
+ function createSearchRegex(options) {
14
+ return new RegExp(options.query, options.caseSensitive ? "g" : "gi");
15
+ }
16
+ function findAllMatches(doc, options) {
17
+ const matches = [];
18
+ const regex = createSearchRegex(options);
19
+ let match;
20
+ while ((match = regex.exec(doc)) !== null) {
21
+ matches.push({ from: match.index, to: match.index + match[0].length });
22
+ }
23
+ return matches;
24
+ }
15
25
  function getDoc() {
16
26
  return unref(view)?.state.doc.toString();
17
27
  }
@@ -29,15 +39,6 @@ export function useEditorUtils(editor) {
29
39
  function dispatch(...specs) {
30
40
  unref(view)?.dispatch(...specs);
31
41
  }
32
- function parseMarkdownToAST(markdownText) {
33
- return markdown({
34
- extensions: [
35
- GFM,
36
- CustomOFM,
37
- { remove: ["SetextHeading"] }
38
- ]
39
- }).language.parser.parse(markdownText);
40
- }
41
42
  function getDocAst() {
42
43
  return parseMarkdownToAST(getDoc() || "");
43
44
  }
@@ -69,13 +70,7 @@ export function useEditorUtils(editor) {
69
70
  currentMatchIndex.value = -1;
70
71
  return;
71
72
  }
72
- const matches = [];
73
- const regex = new RegExp(options.query, options.caseSensitive ? "g" : "gi");
74
- let match;
75
- while ((match = regex.exec(doc)) !== null) {
76
- matches.push({ from: match.index, to: match.index + match[0].length });
77
- }
78
- searchResults.value = matches;
73
+ searchResults.value = findAllMatches(doc, options);
79
74
  currentMatchIndex.value = -1;
80
75
  }
81
76
  function selectAndScrollToMatch(match) {
@@ -125,12 +120,7 @@ export function useEditorUtils(editor) {
125
120
  if (!searchQuery.value || !searchQuery.value.query) return;
126
121
  const doc = getDoc();
127
122
  if (!doc) return;
128
- const matches = [];
129
- const regex = new RegExp(searchQuery.value.query, searchQuery.value.caseSensitive ? "g" : "gi");
130
- let match;
131
- while ((match = regex.exec(doc)) !== null) {
132
- matches.push({ from: match.index, to: match.index + match[0].length });
133
- }
123
+ const matches = findAllMatches(doc, searchQuery.value);
134
124
  if (matches.length === 0) return;
135
125
  const changes = matches.map((m) => ({
136
126
  from: m.from,
@@ -155,6 +145,7 @@ export function useEditorUtils(editor) {
155
145
  replaceSelection,
156
146
  dispatch,
157
147
  parseMarkdownToAST,
148
+ // Re-exported from utils for convenience
158
149
  getDocAst,
159
150
  findNodesByType,
160
151
  getDocNodesByType,
@@ -0,0 +1,53 @@
1
+ import { Decoration, type DecorationSet } from '@codemirror/view';
2
+ import { StateField } from '@codemirror/state';
3
+ import type { EditorState, Range as EditorRange } from '@codemirror/state';
4
+ /**
5
+ * Configuration options for creating a prose plugin
6
+ */
7
+ export interface ProsePluginConfig {
8
+ /**
9
+ * Function to build decorations from the editor state
10
+ */
11
+ buildDecorations: (state: EditorState) => EditorRange<Decoration>[];
12
+ /**
13
+ * Whether to rebuild decorations on document changes (default: true)
14
+ */
15
+ rebuildOnDocChange?: boolean;
16
+ /**
17
+ * Whether to rebuild decorations on selection changes (default: false)
18
+ */
19
+ rebuildOnSelection?: boolean;
20
+ /**
21
+ * Whether to sort the decorations (default: true)
22
+ */
23
+ sortDecorations?: boolean;
24
+ }
25
+ /**
26
+ * Creates a CodeMirror StateField plugin for prose decorations with the standard pattern.
27
+ * This reduces boilerplate for simple prose plugins that follow the common pattern:
28
+ * - Build decorations from syntax tree
29
+ * - Update on document/selection changes
30
+ * - Provide decorations to editor view
31
+ *
32
+ * @param config Configuration object for the plugin
33
+ * @returns A CodeMirror StateField that can be added to the editor
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * export const myPlugin = createProsePlugin({
38
+ * buildDecorations: (state) => {
39
+ * const decorations: EditorRange<Decoration>[] = []
40
+ * syntaxTree(state).iterate({
41
+ * enter(node) {
42
+ * if (node.name === 'MyNode') {
43
+ * decorations.push(myDecoration.range(node.from, node.to))
44
+ * }
45
+ * }
46
+ * })
47
+ * return decorations
48
+ * },
49
+ * rebuildOnSelection: true
50
+ * })
51
+ * ```
52
+ */
53
+ export declare function createProsePlugin(config: ProsePluginConfig): StateField<DecorationSet>;
@@ -0,0 +1,23 @@
1
+ import { EditorView } from "@codemirror/view";
2
+ import { StateField, RangeSet } from "@codemirror/state";
3
+ export function createProsePlugin(config) {
4
+ const {
5
+ buildDecorations,
6
+ rebuildOnDocChange = true,
7
+ rebuildOnSelection = false,
8
+ sortDecorations = true
9
+ } = config;
10
+ return StateField.define({
11
+ create(state) {
12
+ return RangeSet.of(buildDecorations(state), sortDecorations);
13
+ },
14
+ update(value, tr) {
15
+ const shouldRebuild = rebuildOnDocChange && tr.docChanged || rebuildOnSelection && tr.selection;
16
+ if (shouldRebuild) {
17
+ return RangeSet.of(buildDecorations(tr.state), sortDecorations);
18
+ }
19
+ return value.map(tr.changes);
20
+ },
21
+ provide: (f) => EditorView.decorations.from(f)
22
+ });
23
+ }
@@ -1,3 +1 @@
1
- import { type DecorationSet } from '@codemirror/view';
2
- import { StateField } from '@codemirror/state';
3
- export declare const proseHashtagCodemirrorViewPlugin: StateField<DecorationSet>;
1
+ export declare const proseHashtagCodemirrorViewPlugin: import("@codemirror/state").StateField<import("@codemirror/view").DecorationSet>;
@@ -1,7 +1,6 @@
1
- import { EditorView } from "@codemirror/view";
2
- import { StateField, RangeSet } from "@codemirror/state";
3
1
  import { syntaxTree } from "@codemirror/language";
4
2
  import { decorationProseHashtag } from "../../utility/decorations.js";
3
+ import { createProsePlugin } from "./createProsePlugin.js";
5
4
  function buildHashtagWrappers(state) {
6
5
  const decorations = [];
7
6
  syntaxTree(state).iterate({
@@ -13,15 +12,8 @@ function buildHashtagWrappers(state) {
13
12
  });
14
13
  return decorations;
15
14
  }
16
- export const proseHashtagCodemirrorViewPlugin = StateField.define({
17
- create(state) {
18
- return RangeSet.of(buildHashtagWrappers(state));
19
- },
20
- update(value, tr) {
21
- if (tr.docChanged) {
22
- return RangeSet.of(buildHashtagWrappers(tr.state));
23
- }
24
- return value.map(tr.changes);
25
- },
26
- provide: (f) => EditorView.decorations.from(f)
15
+ export const proseHashtagCodemirrorViewPlugin = createProsePlugin({
16
+ buildDecorations: buildHashtagWrappers,
17
+ rebuildOnDocChange: true,
18
+ rebuildOnSelection: false
27
19
  });
@@ -1,6 +1,3 @@
1
1
  import { type DecorationSet } from '@codemirror/view';
2
2
  import { StateField } from '@codemirror/state';
3
- import type { EditorState } from '@codemirror/state';
4
- declare function isNodeRangeActive(state: EditorState, nodeFrom: number, nodeTo: number): boolean;
5
- export { isNodeRangeActive };
6
3
  export declare const proseInternalLinkCodemirrorViewPlugin: StateField<DecorationSet>;
@@ -3,15 +3,7 @@ import { StateField, RangeSet } from "@codemirror/state";
3
3
  import { syntaxTree } from "@codemirror/language";
4
4
  import { internalLinkMapFacet } from "../linkMappingConfig.js";
5
5
  import { ProseVueComponentEmbedWidget } from "../codemirror-widgets/proseVueComponentEmbedWidget.js";
6
- import { cursorSelectionCoveredNode, toCursorNodePositions } from "../../utility/tools.js";
7
- function isNodeRangeActive(state, nodeFrom, nodeTo) {
8
- const cursor = state.selection.main;
9
- if (cursor.empty) {
10
- return cursor.from >= nodeFrom && cursor.from <= nodeTo;
11
- } else {
12
- return Math.max(nodeFrom, cursor.from) < Math.min(nodeTo, cursor.to);
13
- }
14
- }
6
+ import { cursorSelectionCoveredNode, toCursorNodePositions, isNodeRangeActive } from "../../utility/tools.js";
15
7
  function buildInternalLinkDecorations(state) {
16
8
  const decorations = [];
17
9
  const linkMap = state.facet(internalLinkMapFacet);
@@ -102,7 +94,6 @@ function buildInternalLinkDecorations(state) {
102
94
  });
103
95
  return [...decorations, ...widgets];
104
96
  }
105
- export { isNodeRangeActive };
106
97
  export const proseInternalLinkCodemirrorViewPlugin = StateField.define({
107
98
  create(state) {
108
99
  return RangeSet.of(buildInternalLinkDecorations(state), true);
@@ -47,16 +47,20 @@ export default class RichEditPlugin {
47
47
  }
48
48
  update(update) {
49
49
  if (update.docChanged) {
50
- let decorations = this.decorations.map(update.changes);
51
- update.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
52
- const newWidgets = this.processRange(update.view, fromB, toB);
53
- decorations = decorations.update({
54
- filter: (f, t) => f < fromB || t > toB,
55
- add: newWidgets,
56
- sort: true
50
+ if (update.selectionSet) {
51
+ this.decorations = this.process(update.view);
52
+ } else {
53
+ let decorations = this.decorations.map(update.changes);
54
+ update.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
55
+ const newWidgets = this.processRange(update.view, fromB, toB);
56
+ decorations = decorations.update({
57
+ filter: (f, t) => f < fromB || t > toB,
58
+ add: newWidgets,
59
+ sort: true
60
+ });
57
61
  });
58
- });
59
- this.decorations = decorations;
62
+ this.decorations = decorations;
63
+ }
60
64
  } else if (update.viewportChanged || update.selectionSet) {
61
65
  this.decorations = this.process(update.view);
62
66
  }
@@ -71,35 +75,33 @@ export default class RichEditPlugin {
71
75
  processRange(view, from, to) {
72
76
  const widgets = [];
73
77
  const [cursor] = view.state.selection.ranges;
74
- for (let { from: from2, to: to2 } of view.visibleRanges) {
75
- syntaxTree(view.state).iterate({
76
- from: from2,
77
- to: to2,
78
- enter(node) {
79
- const nodeName = node.name;
80
- const nodeFrom = node.from;
81
- const nodeTo = node.to;
82
- if (nodeName === "HorizontalRule") {
83
- if (cursorInNode(cursor?.from, cursor?.to, nodeFrom, nodeTo)) {
84
- return;
85
- }
86
- const line = view.state.doc.lineAt(nodeFrom);
87
- widgets.push(decorationHidden.range(nodeFrom, nodeTo));
88
- widgets.push(Decoration.line({ attributes: { class: "hr" } }).range(line.from));
78
+ syntaxTree(view.state).iterate({
79
+ from,
80
+ to,
81
+ enter(node) {
82
+ const nodeName = node.name;
83
+ const nodeFrom = node.from;
84
+ const nodeTo = node.to;
85
+ if (nodeName === "HorizontalRule") {
86
+ if (cursorInNode(cursor?.from, cursor?.to, nodeFrom, nodeTo)) {
89
87
  return;
90
88
  }
91
- if ((nodeName.startsWith("ATXHeading") || revealComponentMarkTokensOnCursor.includes(nodeName)) && cursorInNode(cursor?.from, cursor?.to, nodeFrom, nodeTo)) {
92
- return false;
93
- }
94
- if (nodeName === "ListMark" && node.matchContext(["BulletList", "ListItem"]) && cursor?.from != nodeFrom && cursor?.from != nodeFrom + 1)
95
- widgets.push(decorationBullet.range(nodeFrom, nodeTo));
96
- if (hideComponentMarkTokens.includes(node.name))
97
- widgets.push(decorationHidden.range(nodeFrom, nodeTo));
98
- if (nodeName === "HeaderMark")
99
- widgets.push(decorationHidden.range(nodeFrom, nodeTo + 1));
89
+ const line = view.state.doc.lineAt(nodeFrom);
90
+ widgets.push(decorationHidden.range(nodeFrom, nodeTo));
91
+ widgets.push(Decoration.line({ attributes: { class: "hr" } }).range(line.from));
92
+ return;
100
93
  }
101
- });
102
- }
94
+ if ((nodeName.startsWith("ATXHeading") || revealComponentMarkTokensOnCursor.includes(nodeName)) && cursorInNode(cursor?.from, cursor?.to, nodeFrom, nodeTo)) {
95
+ return false;
96
+ }
97
+ if (nodeName === "ListMark" && node.matchContext(["BulletList", "ListItem"]) && cursor?.from != nodeFrom && cursor?.from != nodeFrom + 1)
98
+ widgets.push(decorationBullet.range(nodeFrom, nodeTo));
99
+ if (hideComponentMarkTokens.includes(node.name))
100
+ widgets.push(decorationHidden.range(nodeFrom, nodeTo));
101
+ if (nodeName === "HeaderMark")
102
+ widgets.push(decorationHidden.range(nodeFrom, nodeTo + 1));
103
+ }
104
+ });
103
105
  return widgets;
104
106
  }
105
107
  }
@@ -1,14 +1,10 @@
1
1
  import { load } from "js-yaml";
2
- import { markdown } from "@codemirror/lang-markdown";
3
- import { GFM } from "@lezer/markdown";
4
- import { CustomOFM } from "../editor/lezer-parsers/customOFMParsers.js";
2
+ import { parseMarkdownToAST } from "./markdownParser.js";
5
3
  export function parseFrontmatter(markdownText) {
6
4
  if (!markdownText) {
7
5
  return {};
8
6
  }
9
- const tree = markdown({
10
- extensions: [GFM, CustomOFM, { remove: ["SetextHeading"] }]
11
- }).language.parser.parse(markdownText);
7
+ const tree = parseMarkdownToAST(markdownText);
12
8
  const firstNode = tree.topNode.firstChild;
13
9
  if (!firstNode || firstNode.name !== "YAMLFrontMatter") {
14
10
  return {};
@@ -1,11 +1,7 @@
1
- import { markdown } from "@codemirror/lang-markdown";
2
- import { GFM } from "@lezer/markdown";
3
- import { CustomOFM } from "../editor/lezer-parsers/customOFMParsers.js";
1
+ import { parseMarkdownToAST } from "./markdownParser.js";
4
2
  export function getInternalLinks(markdownText) {
5
3
  const links = [];
6
- const tree = markdown({
7
- extensions: [GFM, CustomOFM, { remove: ["SetextHeading"] }]
8
- }).language.parser.parse(markdownText);
4
+ const tree = parseMarkdownToAST(markdownText);
9
5
  tree.iterate({
10
6
  enter: (node) => {
11
7
  if (node.name === "InternalLink") {
@@ -0,0 +1,12 @@
1
+ import type { Tree } from '@lezer/common';
2
+ /**
3
+ * Creates a markdown parser with standard OFM extensions
4
+ * This configuration is used consistently across the codebase
5
+ */
6
+ export declare function createMarkdownParser(): import("@codemirror/language").LanguageSupport;
7
+ /**
8
+ * Parses markdown text to AST using the standard OFM parser configuration
9
+ * @param markdownText The markdown text to parse
10
+ * @returns The parsed syntax tree
11
+ */
12
+ export declare function parseMarkdownToAST(markdownText: string): Tree;
@@ -0,0 +1,11 @@
1
+ import { markdown } from "@codemirror/lang-markdown";
2
+ import { GFM } from "@lezer/markdown";
3
+ import { CustomOFM } from "../editor/lezer-parsers/customOFMParsers.js";
4
+ export function createMarkdownParser() {
5
+ return markdown({
6
+ extensions: [GFM, CustomOFM, { remove: ["SetextHeading"] }]
7
+ });
8
+ }
9
+ export function parseMarkdownToAST(markdownText) {
10
+ return createMarkdownParser().language.parser.parse(markdownText);
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@type32/codemirror-rich-obsidian-editor",
3
- "version": "0.0.25",
3
+ "version": "0.0.26",
4
4
  "description": "OFM Editor Component for Nuxt.",
5
5
  "repository": "Type-32/codemirror-rich-obsidian",
6
6
  "license": "MIT",
@@ -35,45 +35,44 @@
35
35
  "test:types": "bunx vue-tsc --noEmit && cd playground && bunx vue-tsc --noEmit"
36
36
  },
37
37
  "dependencies": {
38
- "@codemirror/autocomplete": "^6.18.7",
38
+ "@codemirror/autocomplete": "^6.19.0",
39
39
  "@codemirror/lang-json": "^6.0.2",
40
- "@codemirror/lang-markdown": "^6.3.4",
40
+ "@codemirror/lang-markdown": "^6.4.0",
41
41
  "@codemirror/lang-yaml": "^6.1.2",
42
42
  "@codemirror/language": "^6.11.3",
43
43
  "@codemirror/language-data": "^6.5.1",
44
44
  "@hsorby/vue3-katex": "0.6.0-rc.7",
45
45
  "@lezer/markdown": "^1.4.3",
46
46
  "@nuxt/image": "1.10.0",
47
- "@nuxt/kit": "^4.1.2",
48
- "@nuxt/ui": "^4.0.0",
47
+ "@nuxt/kit": "^4.1.3",
48
+ "@nuxt/ui": "^4.0.1",
49
49
  "alfaaz": "^1.1.0",
50
50
  "codemirror": "^6.0.2",
51
51
  "js-yaml": "^4.1.0",
52
- "katex": "^0.16.22",
52
+ "katex": "^0.16.23",
53
53
  "lezer-markdown-obsidian": "^0.0.3",
54
54
  "markdown-it": "^14.1.0",
55
55
  "markdown-it-obsidian-callouts": "^0.3.2",
56
56
  "vue-codemirror6": "^1.3.22"
57
57
  },
58
58
  "devDependencies": {
59
- "@iconify-json/lucide": "^1.2.68",
60
- "@iconify-json/simple-icons": "^1.2.53",
59
+ "@iconify-json/lucide": "^1.2.69",
60
+ "@iconify-json/simple-icons": "^1.2.54",
61
61
  "@nuxt/devtools": "^2.6.5",
62
62
  "@nuxt/eslint-config": "^1.9.0",
63
63
  "@nuxt/fonts": "0.11.4",
64
64
  "@nuxt/icon": "1.15.0",
65
65
  "@nuxt/module-builder": "^1.0.2",
66
- "@nuxt/schema": "^4.1.2",
66
+ "@nuxt/schema": "^4.1.3",
67
67
  "@nuxt/test-utils": "^3.19.2",
68
68
  "@types/js-yaml": "^4.0.9",
69
69
  "@types/node": "latest",
70
70
  "changelogen": "^0.6.2",
71
- "eslint": "^9.36.0",
72
- "nuxt": "^4.1.2",
73
- "typescript": "~5.9.2",
71
+ "eslint": "^9.37.0",
72
+ "nuxt": "^4.1.3",
73
+ "typescript": "~5.9.3",
74
74
  "vitest": "^3.2.4",
75
- "vue-tsc": "^3.0.8",
76
- "alfaaz": "^1.1.0"
75
+ "vue-tsc": "^3.1.1"
77
76
  },
78
77
  "trustedDependencies": [
79
78
  "@parcel/watcher",