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.
- package/dist/chunk-2B3A3VSQ.cjs +3382 -0
- package/dist/chunk-2B3A3VSQ.cjs.map +1 -0
- package/dist/{chunk-ZDSZRRUY.cjs → chunk-72ZYRGRT.cjs} +48 -104
- package/dist/chunk-72ZYRGRT.cjs.map +1 -0
- package/dist/{chunk-MOG6E2LY.js → chunk-CG4M4TC7.js} +46 -103
- package/dist/chunk-CG4M4TC7.js.map +1 -0
- package/dist/{chunk-LCQALOEI.js → chunk-DFQYXFOP.js} +36 -3
- package/dist/chunk-DFQYXFOP.js.map +1 -0
- package/dist/{chunk-6LQ2VR4I.js → chunk-HPSMS2WB.js} +38 -22
- package/dist/chunk-HPSMS2WB.js.map +1 -0
- package/dist/{chunk-7Z3SRTPZ.cjs → chunk-KBQDZ5IW.cjs} +38 -22
- package/dist/chunk-KBQDZ5IW.cjs.map +1 -0
- package/dist/{chunk-RV2SYFA6.cjs → chunk-KDEDLC3D.cjs} +36 -2
- package/dist/chunk-KDEDLC3D.cjs.map +1 -0
- package/dist/chunk-N3WL3XPB.js +3360 -0
- package/dist/chunk-N3WL3XPB.js.map +1 -0
- package/dist/{draftly-Bxu_H4nw.d.ts → draftly-BLnx3uGX.d.cts} +12 -6
- package/dist/{draftly-Bxu_H4nw.d.cts → draftly-BLnx3uGX.d.ts} +12 -6
- package/dist/editor/index.cjs +20 -12
- package/dist/editor/index.d.cts +3 -2
- package/dist/editor/index.d.ts +3 -2
- package/dist/editor/index.js +2 -2
- package/dist/index.cjs +59 -27
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/plugins/index.cjs +35 -11
- package/dist/plugins/index.d.cts +321 -3
- package/dist/plugins/index.d.ts +321 -3
- package/dist/plugins/index.js +3 -3
- package/dist/preview/index.cjs +7 -7
- package/dist/preview/index.d.cts +9 -4
- package/dist/preview/index.d.ts +9 -4
- package/dist/preview/index.js +2 -2
- package/package.json +2 -1
- package/src/editor/draftly.ts +9 -13
- package/src/editor/plugin.ts +4 -1
- package/src/editor/theme.ts +34 -1
- package/src/editor/utils.ts +49 -0
- package/src/editor/view-plugin.ts +6 -131
- package/src/plugins/code-plugin.ts +1119 -0
- package/src/plugins/heading-plugin.ts +23 -11
- package/src/plugins/hr-plugin.ts +102 -0
- package/src/plugins/image-plugin.ts +96 -2
- package/src/plugins/index.ts +57 -39
- package/src/plugins/inline-plugin.ts +125 -6
- package/src/plugins/link-plugin.ts +509 -0
- package/src/plugins/list-plugin.ts +116 -2
- package/src/plugins/math-plugin.ts +5 -1
- package/src/plugins/mermaid-plugin.ts +500 -0
- package/src/plugins/paragraph-plugin.ts +38 -0
- package/src/plugins/quote-plugin.ts +146 -0
- package/src/preview/context.ts +1 -1
- package/src/preview/css-generator.ts +3 -1
- package/src/preview/default-renderers.ts +0 -5
- package/src/preview/preview.ts +2 -2
- package/src/preview/renderer.ts +34 -12
- package/src/preview/types.ts +1 -1
- package/dist/chunk-6LQ2VR4I.js.map +0 -1
- package/dist/chunk-7Z3SRTPZ.cjs.map +0 -1
- package/dist/chunk-GA6NYY77.cjs +0 -1400
- package/dist/chunk-GA6NYY77.cjs.map +0 -1
- package/dist/chunk-LCQALOEI.js.map +0 -1
- package/dist/chunk-MOG6E2LY.js.map +0 -1
- package/dist/chunk-RV2SYFA6.cjs.map +0 -1
- package/dist/chunk-TKZNKWGF.js +0 -1385
- package/dist/chunk-TKZNKWGF.js.map +0 -1
- package/dist/chunk-ZDSZRRUY.cjs.map +0 -1
package/src/editor/theme.ts
CHANGED
|
@@ -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
|
-
|
|
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 });
|
package/src/editor/utils.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|