draftly 0.1.0-alpha.1 → 1.0.7

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.
Files changed (68) hide show
  1. package/dist/chunk-2B3A3VSQ.cjs +3382 -0
  2. package/dist/chunk-2B3A3VSQ.cjs.map +1 -0
  3. package/dist/{chunk-ZDSZRRUY.cjs → chunk-72ZYRGRT.cjs} +48 -104
  4. package/dist/chunk-72ZYRGRT.cjs.map +1 -0
  5. package/dist/{chunk-MOG6E2LY.js → chunk-CG4M4TC7.js} +46 -103
  6. package/dist/chunk-CG4M4TC7.js.map +1 -0
  7. package/dist/{chunk-LCQALOEI.js → chunk-DFQYXFOP.js} +36 -3
  8. package/dist/chunk-DFQYXFOP.js.map +1 -0
  9. package/dist/{chunk-6LQ2VR4I.js → chunk-HPSMS2WB.js} +38 -22
  10. package/dist/chunk-HPSMS2WB.js.map +1 -0
  11. package/dist/{chunk-7Z3SRTPZ.cjs → chunk-KBQDZ5IW.cjs} +38 -22
  12. package/dist/chunk-KBQDZ5IW.cjs.map +1 -0
  13. package/dist/{chunk-RV2SYFA6.cjs → chunk-KDEDLC3D.cjs} +36 -2
  14. package/dist/chunk-KDEDLC3D.cjs.map +1 -0
  15. package/dist/chunk-N3WL3XPB.js +3360 -0
  16. package/dist/chunk-N3WL3XPB.js.map +1 -0
  17. package/dist/{draftly-Bxu_H4nw.d.ts → draftly-BLnx3uGX.d.cts} +12 -6
  18. package/dist/{draftly-Bxu_H4nw.d.cts → draftly-BLnx3uGX.d.ts} +12 -6
  19. package/dist/editor/index.cjs +20 -12
  20. package/dist/editor/index.d.cts +3 -2
  21. package/dist/editor/index.d.ts +3 -2
  22. package/dist/editor/index.js +2 -2
  23. package/dist/index.cjs +59 -27
  24. package/dist/index.d.cts +3 -3
  25. package/dist/index.d.ts +3 -3
  26. package/dist/index.js +4 -4
  27. package/dist/plugins/index.cjs +35 -11
  28. package/dist/plugins/index.d.cts +321 -3
  29. package/dist/plugins/index.d.ts +321 -3
  30. package/dist/plugins/index.js +3 -3
  31. package/dist/preview/index.cjs +7 -7
  32. package/dist/preview/index.d.cts +9 -4
  33. package/dist/preview/index.d.ts +9 -4
  34. package/dist/preview/index.js +2 -2
  35. package/package.json +2 -1
  36. package/src/editor/draftly.ts +9 -13
  37. package/src/editor/plugin.ts +4 -1
  38. package/src/editor/theme.ts +34 -1
  39. package/src/editor/utils.ts +49 -0
  40. package/src/editor/view-plugin.ts +6 -131
  41. package/src/plugins/code-plugin.ts +1119 -0
  42. package/src/plugins/heading-plugin.ts +23 -11
  43. package/src/plugins/hr-plugin.ts +102 -0
  44. package/src/plugins/image-plugin.ts +96 -2
  45. package/src/plugins/index.ts +57 -39
  46. package/src/plugins/inline-plugin.ts +125 -6
  47. package/src/plugins/link-plugin.ts +509 -0
  48. package/src/plugins/list-plugin.ts +116 -2
  49. package/src/plugins/math-plugin.ts +5 -1
  50. package/src/plugins/mermaid-plugin.ts +500 -0
  51. package/src/plugins/paragraph-plugin.ts +38 -0
  52. package/src/plugins/quote-plugin.ts +146 -0
  53. package/src/preview/context.ts +1 -1
  54. package/src/preview/css-generator.ts +3 -1
  55. package/src/preview/default-renderers.ts +0 -5
  56. package/src/preview/preview.ts +2 -2
  57. package/src/preview/renderer.ts +34 -12
  58. package/src/preview/types.ts +1 -1
  59. package/dist/chunk-6LQ2VR4I.js.map +0 -1
  60. package/dist/chunk-7Z3SRTPZ.cjs.map +0 -1
  61. package/dist/chunk-GA6NYY77.cjs +0 -1400
  62. package/dist/chunk-GA6NYY77.cjs.map +0 -1
  63. package/dist/chunk-LCQALOEI.js.map +0 -1
  64. package/dist/chunk-MOG6E2LY.js.map +0 -1
  65. package/dist/chunk-RV2SYFA6.cjs.map +0 -1
  66. package/dist/chunk-TKZNKWGF.js +0 -1385
  67. package/dist/chunk-TKZNKWGF.js.map +0 -1
  68. package/dist/chunk-ZDSZRRUY.cjs.map +0 -1
@@ -12,7 +12,9 @@ export const draftlyBaseTheme = EditorView.theme({
12
12
  },
13
13
 
14
14
  "&.cm-draftly .cm-content": {
15
+ width: "100%",
15
16
  maxWidth: "48rem",
17
+ padding: "0 0.5rem",
16
18
  margin: "0 auto",
17
19
  fontFamily: "var(--font-sans, sans-serif)",
18
20
  fontSize: "16px",
@@ -20,10 +22,41 @@ export const draftlyBaseTheme = EditorView.theme({
20
22
  },
21
23
 
22
24
  "&.cm-draftly .cm-content .cm-line": {
23
- padding: 0,
25
+ paddingInline: 0,
24
26
  },
25
27
 
26
28
  "&.cm-draftly .cm-content .cm-widgetBuffer": {
27
29
  display: "none !important",
28
30
  },
29
31
  });
32
+
33
+ import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
34
+ import { tags as t } from "@lezer/highlight";
35
+
36
+ /**
37
+ * Reset syntax highlighting for markdown elements
38
+ * Used to disable theme colors for markdown syntax
39
+ */
40
+ const markdownResetStyle = HighlightStyle.define([
41
+ {
42
+ tag: [
43
+ t.heading,
44
+ t.strong,
45
+ t.emphasis,
46
+ t.strikethrough,
47
+ t.link,
48
+ t.url,
49
+ t.quote,
50
+ t.list,
51
+ t.meta,
52
+ t.contentSeparator,
53
+ t.labelName,
54
+ ],
55
+ color: "inherit",
56
+ fontWeight: "inherit",
57
+ fontStyle: "inherit",
58
+ textDecoration: "none",
59
+ },
60
+ ]);
61
+
62
+ export const markdownResetExtension = syntaxHighlighting(markdownResetStyle, { fallback: false });
@@ -92,3 +92,52 @@ export function selectionOverlapsRange(view: EditorView, from: number, to: numbe
92
92
  }
93
93
  return false;
94
94
  }
95
+
96
+ /**
97
+ * Toggle markdown style on selection or insert markers at cursor
98
+ * @param marker - The markdown marker (e.g., "**" for bold, "*" for italic)
99
+ * @returns Command function for EditorView
100
+ */
101
+ export function toggleMarkdownStyle(marker: string): (view: EditorView) => boolean {
102
+ return (view: EditorView) => {
103
+ const { state } = view;
104
+ const { from, to, empty } = state.selection.main;
105
+
106
+ // Get selected text
107
+ const selectedText = state.sliceDoc(from, to);
108
+
109
+ // Check if already wrapped with markers
110
+ const markerLen = marker.length;
111
+ const beforeFrom = Math.max(0, from - markerLen);
112
+ const afterTo = Math.min(state.doc.length, to + markerLen);
113
+ const textBefore = state.sliceDoc(beforeFrom, from);
114
+ const textAfter = state.sliceDoc(to, afterTo);
115
+
116
+ const isWrapped = textBefore === marker && textAfter === marker;
117
+
118
+ if (isWrapped) {
119
+ // Remove markers
120
+ view.dispatch({
121
+ changes: [
122
+ { from: beforeFrom, to: from, insert: "" },
123
+ { from: to, to: afterTo, insert: "" },
124
+ ],
125
+ selection: { anchor: beforeFrom, head: beforeFrom + selectedText.length },
126
+ });
127
+ } else if (empty) {
128
+ // No selection - insert markers and place cursor between them
129
+ view.dispatch({
130
+ changes: { from, to, insert: marker + marker },
131
+ selection: { anchor: from + markerLen },
132
+ });
133
+ } else {
134
+ // Wrap selection with markers
135
+ view.dispatch({
136
+ changes: { from, to, insert: marker + selectedText + marker },
137
+ selection: { anchor: from + markerLen, head: to + markerLen },
138
+ });
139
+ }
140
+
141
+ return true;
142
+ };
143
+ }
@@ -6,44 +6,6 @@ import { draftlyBaseTheme } from "./theme";
6
6
  import { DecorationContext, DraftlyPlugin } from "./plugin";
7
7
  import { DraftlyNode } from "./draftly";
8
8
 
9
- /**
10
- * Mark decorations for inline styling
11
- */
12
- const markDecorations = {
13
- // Inline styles
14
- "inline-code": Decoration.mark({ class: "cm-draftly-inline-code" }),
15
-
16
- // Links and images
17
- link: Decoration.mark({ class: "cm-draftly-link" }),
18
- "link-text": Decoration.mark({ class: "cm-draftly-link-text" }),
19
- url: Decoration.mark({ class: "cm-draftly-url" }),
20
- image: Decoration.mark({ class: "cm-draftly-image" }),
21
-
22
- // Emphasis markers (* _ ~~ `)
23
- "emphasis-mark": Decoration.mark({ class: "cm-draftly-emphasis-mark" }),
24
-
25
- // Code blocks
26
- "fenced-code": Decoration.mark({ class: "cm-draftly-fenced-code" }),
27
- "code-mark": Decoration.mark({ class: "cm-draftly-code-mark" }),
28
- "code-info": Decoration.mark({ class: "cm-draftly-code-info" }),
29
-
30
- // Blockquote
31
- blockquote: Decoration.mark({ class: "cm-draftly-blockquote" }),
32
- "quote-mark": Decoration.mark({ class: "cm-draftly-quote-mark" }),
33
-
34
- // Horizontal rule
35
- hr: Decoration.mark({ class: "cm-draftly-hr" }),
36
- };
37
-
38
- /**
39
- * Line decorations for block-level elements
40
- */
41
- const lineDecorations = {
42
- blockquote: Decoration.line({ class: "cm-draftly-line-blockquote" }),
43
- "code-block": Decoration.line({ class: "cm-draftly-line-code" }),
44
- hr: Decoration.line({ class: "cm-draftly-line-hr" }),
45
- };
46
-
47
9
  /**
48
10
  * Facet to register plugins with the view plugin
49
11
  */
@@ -77,98 +39,6 @@ function buildDecorations(view: EditorView, plugins: DraftlyPlugin[] = []): Deco
77
39
  const builder = new RangeSetBuilder<Decoration>();
78
40
  const decorations: Range<Decoration>[] = [];
79
41
 
80
- const tree = syntaxTree(view.state);
81
-
82
- // Iterate through the syntax tree
83
- tree.iterate({
84
- enter: (node) => {
85
- const { from, to, name } = node;
86
-
87
- // Skip if cursor is in this range (show raw markdown)
88
- const cursorInNode = selectionOverlapsRange(view, from, to);
89
-
90
- // Handle inline code
91
- if (name === "InlineCode") {
92
- decorations.push(markDecorations["inline-code"].range(from, to));
93
-
94
- // Style the backticks
95
- if (!cursorInNode) {
96
- const marks = node.node.getChildren("CodeMark");
97
- for (const mark of marks) {
98
- decorations.push(markDecorations["code-mark"].range(mark.from, mark.to));
99
- }
100
- }
101
- }
102
-
103
- // Handle links
104
- if (name === "Link") {
105
- decorations.push(markDecorations.link.range(from, to));
106
-
107
- // Find the URL child
108
- const url = node.node.getChild("URL");
109
- if (url) {
110
- decorations.push(markDecorations.url.range(url.from, url.to));
111
- }
112
- }
113
-
114
- // Handle images
115
- if (name === "Image") {
116
- decorations.push(markDecorations.image.range(from, to));
117
- }
118
-
119
- // Handle fenced code blocks
120
- if (name === "FencedCode") {
121
- decorations.push(markDecorations["fenced-code"].range(from, to));
122
-
123
- // Add line decorations for each line in the code block
124
- const startLine = view.state.doc.lineAt(from);
125
- const endLine = view.state.doc.lineAt(to);
126
- for (let i = startLine.number; i <= endLine.number; i++) {
127
- const line = view.state.doc.line(i);
128
- decorations.push(lineDecorations["code-block"].range(line.from));
129
- }
130
-
131
- // Style code info (language identifier)
132
- const codeInfo = node.node.getChild("CodeInfo");
133
- if (codeInfo) {
134
- decorations.push(markDecorations["code-info"].range(codeInfo.from, codeInfo.to));
135
- }
136
-
137
- // Style code marks (```)
138
- const codeMarks = node.node.getChildren("CodeMark");
139
- for (const mark of codeMarks) {
140
- decorations.push(markDecorations["code-mark"].range(mark.from, mark.to));
141
- }
142
- }
143
-
144
- // Handle blockquotes
145
- if (name === "Blockquote") {
146
- decorations.push(markDecorations.blockquote.range(from, to));
147
-
148
- // Add line decorations
149
- const startLine = view.state.doc.lineAt(from);
150
- const endLine = view.state.doc.lineAt(to);
151
- for (let i = startLine.number; i <= endLine.number; i++) {
152
- const line = view.state.doc.line(i);
153
- decorations.push(lineDecorations.blockquote.range(line.from));
154
- }
155
-
156
- // Style quote marks (>)
157
- const quoteMarks = node.node.getChildren("QuoteMark");
158
- for (const mark of quoteMarks) {
159
- decorations.push(markDecorations["quote-mark"].range(mark.from, mark.to));
160
- }
161
- }
162
-
163
- // Handle horizontal rules
164
- if (name === "HorizontalRule") {
165
- const line = view.state.doc.lineAt(from);
166
- decorations.push(lineDecorations.hr.range(line.from));
167
- decorations.push(markDecorations.hr.range(from, to));
168
- }
169
- },
170
- });
171
-
172
42
  // Allow plugins to contribute decorations
173
43
  if (plugins.length > 0) {
174
44
  const ctx: DecorationContext = {
@@ -182,7 +52,12 @@ function buildDecorations(view: EditorView, plugins: DraftlyPlugin[] = []): Deco
182
52
  const sortedPlugins = [...plugins].sort((a, b) => a.decorationPriority - b.decorationPriority);
183
53
 
184
54
  for (const plugin of sortedPlugins) {
185
- plugin.buildDecorations(ctx);
55
+ try {
56
+ plugin.buildDecorations(ctx);
57
+ } catch {
58
+ // Silently ignore errors from partial tree states (e.g., Lezer TreeBuffer
59
+ // "Invalid child in posBefore"). These resolve on the next update cycle.
60
+ }
186
61
  }
187
62
  }
188
63