@prosemark/core 0.0.3 → 0.0.4
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/main.d.ts +52 -12
- package/dist/main.js +311 -83
- package/package.json +11 -2
package/dist/main.d.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import { DOMEventHandlers, DOMEventMap, Decoration, DecorationSet } from "@codemirror/view";
|
|
1
|
+
import { DOMEventHandlers, DOMEventMap, Decoration, DecorationSet, EditorView, ViewPlugin, ViewUpdate } from "@codemirror/view";
|
|
2
2
|
import * as _codemirror_state0 from "@codemirror/state";
|
|
3
|
-
import { EditorState, Extension, Facet, Range, StateField } from "@codemirror/state";
|
|
3
|
+
import { EditorState, Extension, Facet, Line, Range, RangeSet, StateField } from "@codemirror/state";
|
|
4
4
|
import { Tag } from "@lezer/highlight";
|
|
5
5
|
import * as _lezer_markdown0 from "@lezer/markdown";
|
|
6
6
|
import { MarkdownConfig } from "@lezer/markdown";
|
|
7
7
|
import * as _lezer_common0 from "@lezer/common";
|
|
8
8
|
import { SyntaxNodeRef } from "@lezer/common";
|
|
9
9
|
|
|
10
|
-
//#region lib/hide/index.d.ts
|
|
11
|
-
declare const defaultHideExtensions: _codemirror_state0.Extension[];
|
|
12
|
-
declare const escapeMarkdownSyntaxExtension: MarkdownConfig;
|
|
13
|
-
//#endregion
|
|
14
10
|
//#region lib/utils.d.ts
|
|
15
11
|
interface RangeLike {
|
|
16
12
|
from: number;
|
|
@@ -19,13 +15,21 @@ interface RangeLike {
|
|
|
19
15
|
type ClassBasedEventHandlers<This> = { [event in keyof DOMEventMap]?: Record<string, DOMEventHandlers<This>[event]> };
|
|
20
16
|
declare function eventHandlersWithClass<This>(handlers: ClassBasedEventHandlers<This>): DOMEventHandlers<This>;
|
|
21
17
|
//#endregion
|
|
18
|
+
//#region lib/hide/core.d.ts
|
|
19
|
+
declare const hideExtension: StateField<DecorationSet>;
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region lib/hide/index.d.ts
|
|
22
|
+
declare const defaultHideExtensions: _codemirror_state0.Extension[];
|
|
23
|
+
declare const escapeMarkdownSyntaxExtension: MarkdownConfig;
|
|
24
|
+
//#endregion
|
|
22
25
|
//#region lib/fold/core.d.ts
|
|
23
|
-
declare const
|
|
26
|
+
declare const foldExtension: StateField<DecorationSet>;
|
|
24
27
|
interface FoldableSyntaxSpec {
|
|
25
28
|
nodePath: string | string[] | ((nodePath: string) => boolean);
|
|
26
|
-
|
|
29
|
+
buildDecorations?: (state: EditorState, node: SyntaxNodeRef, selectionTouchesRange: boolean) => Range<Decoration> | Range<Decoration>[] | undefined;
|
|
27
30
|
unfoldZone?: (state: EditorState, node: SyntaxNodeRef) => RangeLike;
|
|
28
31
|
eventHandlers?: DOMEventHandlers<void>;
|
|
32
|
+
keepDecorationOnUnfold?: boolean;
|
|
29
33
|
}
|
|
30
34
|
declare const foldableSyntaxFacet: Facet<FoldableSyntaxSpec, FoldableSyntaxSpec[]>;
|
|
31
35
|
declare const selectAllDecorationsOnSelectExtension: (widgetClass: string) => Extension;
|
|
@@ -37,6 +41,10 @@ declare const bulletListExtension: _codemirror_state0.Extension;
|
|
|
37
41
|
declare const emojiMarkdownSyntaxExtension: MarkdownConfig;
|
|
38
42
|
declare const emojiExtension: _codemirror_state0.Extension;
|
|
39
43
|
//#endregion
|
|
44
|
+
//#region lib/fold/dashes.d.ts
|
|
45
|
+
declare const dashMarkdownSyntaxExtension: MarkdownConfig;
|
|
46
|
+
declare const dashExtension: _codemirror_state0.Extension;
|
|
47
|
+
//#endregion
|
|
40
48
|
//#region lib/fold/horizontalRule.d.ts
|
|
41
49
|
declare const horizonalRuleExtension: _codemirror_state0.Extension[];
|
|
42
50
|
//#endregion
|
|
@@ -46,8 +54,26 @@ declare const imageExtension: _codemirror_state0.Extension[];
|
|
|
46
54
|
//#region lib/fold/task.d.ts
|
|
47
55
|
declare const taskExtension: _codemirror_state0.Extension[];
|
|
48
56
|
//#endregion
|
|
49
|
-
//#region lib/
|
|
50
|
-
|
|
57
|
+
//#region lib/blockQuote.d.ts
|
|
58
|
+
interface MeasureData {
|
|
59
|
+
lineFroms: number[];
|
|
60
|
+
nestedBorders: {
|
|
61
|
+
pos: number;
|
|
62
|
+
offset: number;
|
|
63
|
+
}[];
|
|
64
|
+
}
|
|
65
|
+
declare const blockQuoteExtension: ViewPlugin<{
|
|
66
|
+
decorations: DecorationSet;
|
|
67
|
+
update(u: ViewUpdate): void;
|
|
68
|
+
requestMeasure(view: EditorView): void;
|
|
69
|
+
applyMeasure(data: MeasureData, view: EditorView): void;
|
|
70
|
+
}, undefined>;
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region lib/fold/index.d.ts
|
|
73
|
+
declare const defaultFoldableSyntaxExtensions: _codemirror_state0.Extension[];
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region lib/revealBlockOnArrow.d.ts
|
|
76
|
+
declare const revealBlockOnArrowExtension: _codemirror_state0.Extension[];
|
|
51
77
|
//#endregion
|
|
52
78
|
//#region lib/syntaxHighlighting.d.ts
|
|
53
79
|
declare const additionalMarkdownSyntaxTags: {
|
|
@@ -69,6 +95,7 @@ declare const markdownTags: {
|
|
|
69
95
|
emoji: Tag;
|
|
70
96
|
emojiMark: Tag;
|
|
71
97
|
listMark: Tag;
|
|
98
|
+
dash: Tag;
|
|
72
99
|
};
|
|
73
100
|
//#endregion
|
|
74
101
|
//#region lib/clickLink.d.ts
|
|
@@ -77,6 +104,20 @@ declare const clickLinkHandler: Facet<ClickLinkHandler, readonly ClickLinkHandle
|
|
|
77
104
|
declare const defaultClickLinkHandler: _codemirror_state0.Extension;
|
|
78
105
|
declare const clickLinkExtension: _codemirror_state0.Extension[];
|
|
79
106
|
//#endregion
|
|
107
|
+
//#region lib/softIndentExtension.d.ts
|
|
108
|
+
interface IndentData {
|
|
109
|
+
line: Line;
|
|
110
|
+
indentWidth: number;
|
|
111
|
+
}
|
|
112
|
+
declare const softIndentExtension: ViewPlugin<{
|
|
113
|
+
decorations: DecorationSet;
|
|
114
|
+
update(u: ViewUpdate): void;
|
|
115
|
+
requestMeasure(view: EditorView): void;
|
|
116
|
+
measureIndents(view: EditorView): IndentData[];
|
|
117
|
+
buildDecorations(indents: IndentData[]): RangeSet<Decoration>;
|
|
118
|
+
applyIndents(indents: IndentData[], view: EditorView): void;
|
|
119
|
+
}, undefined>;
|
|
120
|
+
//#endregion
|
|
80
121
|
//#region lib/codeFenceExtension.d.ts
|
|
81
122
|
declare const codeBlockDecorationsExtension: Extension;
|
|
82
123
|
declare const codeFenceTheme: Extension;
|
|
@@ -86,9 +127,8 @@ declare const prosemarkMarkdownSyntaxExtensions: (_lezer_markdown0.MarkdownConfi
|
|
|
86
127
|
defineNodes: never[];
|
|
87
128
|
props: _lezer_common0.NodePropSource[];
|
|
88
129
|
})[];
|
|
89
|
-
declare const defaultFoldableSyntaxExtensions: Extension[];
|
|
90
130
|
declare const prosemarkBasicSetup: () => Extension;
|
|
91
131
|
declare const prosemarkBaseThemeSetup: () => Extension;
|
|
92
132
|
declare const prosemarkLightThemeSetup: () => Extension;
|
|
93
133
|
//#endregion
|
|
94
|
-
export { ClickLinkHandler, additionalMarkdownSyntaxTags, baseSyntaxHighlights, baseTheme, blockQuoteExtension, bulletListExtension, clickLinkExtension, clickLinkHandler, codeBlockDecorationsExtension, codeFenceTheme, defaultClickLinkHandler, defaultFoldableSyntaxExtensions, defaultHideExtensions, emojiExtension, emojiMarkdownSyntaxExtension, escapeMarkdownSyntaxExtension, eventHandlersWithClass,
|
|
134
|
+
export { ClickLinkHandler, additionalMarkdownSyntaxTags, baseSyntaxHighlights, baseTheme, blockQuoteExtension, bulletListExtension, clickLinkExtension, clickLinkHandler, codeBlockDecorationsExtension, codeFenceTheme, dashExtension, dashMarkdownSyntaxExtension, defaultClickLinkHandler, defaultFoldableSyntaxExtensions, defaultHideExtensions, emojiExtension, emojiMarkdownSyntaxExtension, escapeMarkdownSyntaxExtension, eventHandlersWithClass, foldExtension, foldableSyntaxFacet, generalSyntaxHighlights, hideExtension, horizonalRuleExtension, imageExtension, lightTheme, markdownTags, prosemarkBaseThemeSetup, prosemarkBasicSetup, prosemarkLightThemeSetup, prosemarkMarkdownSyntaxExtensions, revealBlockOnArrowExtension, selectAllDecorationsOnSelectExtension, softIndentExtension, taskExtension };
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Decoration, EditorView, EditorView as EditorView$1, ViewPlugin, WidgetType, dropCursor, keymap } from "@codemirror/view";
|
|
2
|
-
import { CharCategory, EditorSelection, EditorState, Facet, RangeSetBuilder, StateField, findClusterBreak } from "@codemirror/state";
|
|
1
|
+
import { Decoration, EditorView, EditorView as EditorView$1, ViewPlugin, ViewUpdate, WidgetType, dropCursor, keymap } from "@codemirror/view";
|
|
2
|
+
import { Annotation, CharCategory, EditorSelection, EditorState, Facet, Line, RangeSet, RangeSetBuilder, StateField, findClusterBreak } from "@codemirror/state";
|
|
3
3
|
import { HighlightStyle, bracketMatching, foldGutter, foldKeymap, indentOnInput, syntaxHighlighting, syntaxTree } from "@codemirror/language";
|
|
4
4
|
import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
|
|
5
5
|
import { searchKeymap } from "@codemirror/search";
|
|
@@ -51,12 +51,17 @@ function eventHandlersWithClass(handlers) {
|
|
|
51
51
|
|
|
52
52
|
//#endregion
|
|
53
53
|
//#region lib/hide/core.ts
|
|
54
|
-
const hideTheme = EditorView.theme({
|
|
54
|
+
const hideTheme = EditorView.theme({
|
|
55
|
+
".cm-hidden-token": { fontSize: "0px" },
|
|
56
|
+
".cm-transparent-token": { opacity: 0 }
|
|
57
|
+
});
|
|
55
58
|
const hideInlineDecoration = Decoration.mark({ class: "cm-hidden-token" });
|
|
59
|
+
const hideInlineKeepSpaceDecoration = Decoration.mark({ class: "cm-transparent-token" });
|
|
56
60
|
const hideBlockDecoration = Decoration.replace({ block: true });
|
|
57
61
|
const buildDecorations$1 = (state) => {
|
|
58
62
|
const decorations = [];
|
|
59
63
|
const specs = state.facet(hidableNodeFacet);
|
|
64
|
+
specs.map(checkSpec);
|
|
60
65
|
syntaxTree(state).iterate({ enter: (node) => {
|
|
61
66
|
if (state.selection.ranges.some((range) => rangeTouchesRange(node, range))) return;
|
|
62
67
|
for (const spec of specs) {
|
|
@@ -78,11 +83,9 @@ const buildDecorations$1 = (state) => {
|
|
|
78
83
|
let names;
|
|
79
84
|
if (!Array.isArray(spec.subNodeNameToHide)) names = [spec.subNodeNameToHide];
|
|
80
85
|
else names = spec.subNodeNameToHide;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (names.includes(cursor.type.name)) decorations.push((spec.block ? hideBlockDecoration : hideInlineDecoration).range(cursor.from, cursor.to));
|
|
85
|
-
while (cursor.nextSibling());
|
|
86
|
+
node.node.cursor().iterate((node$1) => {
|
|
87
|
+
if (names.includes(node$1.type.name)) decorations.push((spec.block ? hideBlockDecoration : spec.keepSpace ? hideInlineKeepSpaceDecoration : hideInlineDecoration).range(node$1.from, node$1.to));
|
|
88
|
+
});
|
|
86
89
|
}
|
|
87
90
|
}
|
|
88
91
|
} });
|
|
@@ -98,6 +101,9 @@ const hideExtension = StateField.define({
|
|
|
98
101
|
},
|
|
99
102
|
provide: (f) => [EditorView.decorations.from(f), hideTheme]
|
|
100
103
|
});
|
|
104
|
+
const checkSpec = (spec) => {
|
|
105
|
+
if (spec.block && spec.keepSpace) console.warn("Only inline hide nodes can maintain space currently, but `block` and `keepSpace` are set in:", spec);
|
|
106
|
+
};
|
|
101
107
|
const hidableNodeFacet = Facet.define({
|
|
102
108
|
combine(value) {
|
|
103
109
|
return [...value];
|
|
@@ -115,7 +121,8 @@ const markdownTags = {
|
|
|
115
121
|
escapeMark: Tag.define(),
|
|
116
122
|
emoji: Tag.define(),
|
|
117
123
|
emojiMark: Tag.define(),
|
|
118
|
-
listMark: Tag.define()
|
|
124
|
+
listMark: Tag.define(),
|
|
125
|
+
dash: Tag.define()
|
|
119
126
|
};
|
|
120
127
|
|
|
121
128
|
//#endregion
|
|
@@ -168,7 +175,8 @@ const defaultHidableSpecs = [
|
|
|
168
175
|
},
|
|
169
176
|
{
|
|
170
177
|
nodeName: "Blockquote",
|
|
171
|
-
subNodeNameToHide: "QuoteMark"
|
|
178
|
+
subNodeNameToHide: "QuoteMark",
|
|
179
|
+
keepSpace: true
|
|
172
180
|
}
|
|
173
181
|
];
|
|
174
182
|
const defaultHideExtensions = defaultHidableSpecs.map((spec) => hidableNodeFacet.of(spec));
|
|
@@ -187,31 +195,102 @@ const escapeMarkdownSyntaxExtension = {
|
|
|
187
195
|
}]
|
|
188
196
|
};
|
|
189
197
|
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region lib/blockQuote.ts
|
|
200
|
+
var NestedBlockQuoteBorder = class extends WidgetType {
|
|
201
|
+
constructor(offset) {
|
|
202
|
+
super();
|
|
203
|
+
this.offset = offset;
|
|
204
|
+
}
|
|
205
|
+
toDOM() {
|
|
206
|
+
const span = document.createElement("span");
|
|
207
|
+
span.className = "cm-nested-blockquote-border";
|
|
208
|
+
span.style = `--blockquote-border-offset: ${this.offset.toString()}px`;
|
|
209
|
+
return span;
|
|
210
|
+
}
|
|
211
|
+
ignoreEvent(_event) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
function measureBlockQuotes(view) {
|
|
216
|
+
const lineFroms = [];
|
|
217
|
+
const nestedBorders = [];
|
|
218
|
+
syntaxTree(view.state).iterate({ enter(node) {
|
|
219
|
+
if (node.type.name != "Blockquote") return;
|
|
220
|
+
const startLine = view.state.doc.lineAt(node.from).number;
|
|
221
|
+
const endLine = view.state.doc.lineAt(node.to).number;
|
|
222
|
+
for (let i = startLine; i <= endLine; i++) {
|
|
223
|
+
const line = view.state.doc.line(i);
|
|
224
|
+
lineFroms.push(line.from);
|
|
225
|
+
}
|
|
226
|
+
node.node.cursor().iterate((child) => {
|
|
227
|
+
if (child.type.name !== "QuoteMark") return;
|
|
228
|
+
const line = view.state.doc.lineAt(child.from);
|
|
229
|
+
if (child.from == line.from) return;
|
|
230
|
+
const offset = (view.coordsAtPos(child.from)?.left ?? 0) - (view.coordsAtPos(line.from)?.left ?? 0);
|
|
231
|
+
nestedBorders.push({
|
|
232
|
+
pos: child.from,
|
|
233
|
+
offset
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
return false;
|
|
237
|
+
} });
|
|
238
|
+
return {
|
|
239
|
+
lineFroms,
|
|
240
|
+
nestedBorders
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function buildDecorationsFromMeasure(_view, data) {
|
|
244
|
+
const decos = [];
|
|
245
|
+
for (const from of data.lineFroms) decos.push(Decoration.line({ attributes: { class: "cm-blockquote-line" } }).range(from));
|
|
246
|
+
for (const { pos, offset } of data.nestedBorders) decos.push(Decoration.widget({ widget: new NestedBlockQuoteBorder(offset) }).range(pos));
|
|
247
|
+
return RangeSet.of(decos, true);
|
|
248
|
+
}
|
|
249
|
+
const blockQuoteExtension = ViewPlugin.fromClass(class {
|
|
250
|
+
decorations = Decoration.none;
|
|
251
|
+
constructor(view) {
|
|
252
|
+
this.requestMeasure(view);
|
|
253
|
+
}
|
|
254
|
+
update(u) {
|
|
255
|
+
if (u.docChanged || u.viewportChanged) this.requestMeasure(u.view);
|
|
256
|
+
}
|
|
257
|
+
requestMeasure(view) {
|
|
258
|
+
view.requestMeasure({
|
|
259
|
+
read: (v) => measureBlockQuotes(v),
|
|
260
|
+
write: (data, v) => {
|
|
261
|
+
this.applyMeasure(data, v);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
applyMeasure(data, view) {
|
|
266
|
+
this.decorations = buildDecorationsFromMeasure(view, data);
|
|
267
|
+
}
|
|
268
|
+
}, { decorations: (v) => v.decorations });
|
|
269
|
+
|
|
190
270
|
//#endregion
|
|
191
271
|
//#region lib/fold/core.ts
|
|
192
272
|
const buildDecorations = (state) => {
|
|
193
273
|
const decorations = [];
|
|
194
274
|
const specs = state.facet(foldableSyntaxFacet);
|
|
195
275
|
syntaxTree(state).iterate({ enter: (node) => {
|
|
196
|
-
|
|
276
|
+
const selectionTouchesNodeRange = selectionTouchesRange(state.selection.ranges, node);
|
|
277
|
+
const lineage = [];
|
|
278
|
+
let node_ = node;
|
|
279
|
+
while (node_) {
|
|
280
|
+
lineage.push(node_.name);
|
|
281
|
+
node_ = node_.node.parent;
|
|
282
|
+
}
|
|
283
|
+
const path = lineage.reverse().join("/");
|
|
197
284
|
for (const spec of specs) {
|
|
198
|
-
const lineage = [];
|
|
199
|
-
let node_ = node;
|
|
200
|
-
while (node_) {
|
|
201
|
-
lineage.push(node_.name);
|
|
202
|
-
node_ = node_.node.parent;
|
|
203
|
-
}
|
|
204
|
-
const path = lineage.reverse().join("/");
|
|
205
285
|
if (spec.nodePath instanceof Function) {
|
|
206
286
|
if (!spec.nodePath(path)) continue;
|
|
207
287
|
} else if (spec.nodePath instanceof Array) {
|
|
208
288
|
if (!spec.nodePath.some((testPath) => path.endsWith(testPath))) continue;
|
|
209
289
|
} else if (!path.endsWith(spec.nodePath)) continue;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const res = spec.onFold(state, node);
|
|
290
|
+
const selectionTouchesRange_ = spec.unfoldZone ? selectionTouchesRange(state.selection.ranges, spec.unfoldZone(state, node)) : selectionTouchesNodeRange;
|
|
291
|
+
if (!spec.keepDecorationOnUnfold && selectionTouchesRange_) return;
|
|
292
|
+
if (spec.buildDecorations) {
|
|
293
|
+
const res = spec.buildDecorations(state, node, selectionTouchesRange_);
|
|
215
294
|
if (res instanceof Array) decorations.push(...res);
|
|
216
295
|
else if (res) decorations.push(res);
|
|
217
296
|
}
|
|
@@ -219,7 +298,7 @@ const buildDecorations = (state) => {
|
|
|
219
298
|
} });
|
|
220
299
|
return Decoration.set(decorations, true);
|
|
221
300
|
};
|
|
222
|
-
const
|
|
301
|
+
const foldExtension = StateField.define({
|
|
223
302
|
create(state) {
|
|
224
303
|
return buildDecorations(state);
|
|
225
304
|
},
|
|
@@ -229,7 +308,6 @@ const foldDecorationExtension = StateField.define({
|
|
|
229
308
|
},
|
|
230
309
|
provide: (f) => [EditorView.decorations.from(f)]
|
|
231
310
|
});
|
|
232
|
-
const foldExtension = [foldDecorationExtension];
|
|
233
311
|
const foldableSyntaxFacet = Facet.define({
|
|
234
312
|
combine(value) {
|
|
235
313
|
return [...value];
|
|
@@ -241,7 +319,7 @@ const selectAllDecorationsOnSelectExtension = (widgetClass) => EditorView.domEve
|
|
|
241
319
|
if (ranges.length === 0 || ranges[0]?.anchor !== ranges[0]?.head) return;
|
|
242
320
|
const target = e.target;
|
|
243
321
|
const pos = view.posAtDOM(target);
|
|
244
|
-
view.state.field(
|
|
322
|
+
view.state.field(foldExtension).between(pos, pos, (from, to) => {
|
|
245
323
|
setTimeout(() => {
|
|
246
324
|
view.dispatch({ selection: EditorSelection.single(to, from) });
|
|
247
325
|
}, 0);
|
|
@@ -264,13 +342,55 @@ var BulletPoint = class extends WidgetType {
|
|
|
264
342
|
};
|
|
265
343
|
const bulletListExtension = foldableSyntaxFacet.of({
|
|
266
344
|
nodePath: "BulletList/ListItem/ListMark",
|
|
267
|
-
|
|
345
|
+
buildDecorations: (_state, node) => {
|
|
268
346
|
const cursor = node.node.cursor();
|
|
269
347
|
if (cursor.nextSibling() && cursor.name === "Task") return;
|
|
270
348
|
return Decoration.replace({ widget: new BulletPoint() }).range(node.from, node.to);
|
|
271
349
|
}
|
|
272
350
|
});
|
|
273
351
|
|
|
352
|
+
//#endregion
|
|
353
|
+
//#region lib/fold/dashes.ts
|
|
354
|
+
const dashMarkdownSyntaxExtension = {
|
|
355
|
+
defineNodes: [{
|
|
356
|
+
name: "Dash",
|
|
357
|
+
style: markdownTags.dash
|
|
358
|
+
}],
|
|
359
|
+
parseInline: [{
|
|
360
|
+
name: "Dash",
|
|
361
|
+
parse: (cx, next, pos) => {
|
|
362
|
+
if (next !== 45 || pos > 1 && cx.char(pos - 1) == 45) return -1;
|
|
363
|
+
let i;
|
|
364
|
+
for (i = pos; i < cx.end && cx.char(i) === 45; i++);
|
|
365
|
+
if (i - pos > 3) return -1;
|
|
366
|
+
return cx.addElement(cx.elt("Dash", pos, i));
|
|
367
|
+
},
|
|
368
|
+
before: "Emphasis"
|
|
369
|
+
}]
|
|
370
|
+
};
|
|
371
|
+
var DashWidget = class extends WidgetType {
|
|
372
|
+
constructor(dashCount) {
|
|
373
|
+
super();
|
|
374
|
+
this.dashCount = dashCount;
|
|
375
|
+
}
|
|
376
|
+
toDOM() {
|
|
377
|
+
const span = document.createElement("span");
|
|
378
|
+
span.className = "cm-dash";
|
|
379
|
+
if (this.dashCount === 2) span.innerHTML = "–";
|
|
380
|
+
else if (this.dashCount === 3) span.innerHTML = "—";
|
|
381
|
+
else span.innerHTML = "-".repeat(this.dashCount);
|
|
382
|
+
return span;
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
const dashExtension = foldableSyntaxFacet.of({
|
|
386
|
+
nodePath: "Dash",
|
|
387
|
+
buildDecorations: (_state, node) => {
|
|
388
|
+
const dashCount = node.to - node.from;
|
|
389
|
+
if (dashCount < 2 || dashCount > 3) return;
|
|
390
|
+
return Decoration.replace({ widget: new DashWidget(dashCount) }).range(node.from, node.to);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
274
394
|
//#endregion
|
|
275
395
|
//#region lib/fold/emoji.ts
|
|
276
396
|
const emojiDelimiter = {
|
|
@@ -311,7 +431,7 @@ var EmojiWidget = class extends WidgetType {
|
|
|
311
431
|
};
|
|
312
432
|
const emojiExtension = foldableSyntaxFacet.of({
|
|
313
433
|
nodePath: "Emoji",
|
|
314
|
-
|
|
434
|
+
buildDecorations: (state, node) => {
|
|
315
435
|
const emojiName = state.doc.sliceString(node.from + 1, node.to - 1);
|
|
316
436
|
const emoji_ = emoji.get(emojiName);
|
|
317
437
|
if (!emoji_) return;
|
|
@@ -336,16 +456,19 @@ var HorizontalRuleWidget = class extends WidgetType {
|
|
|
336
456
|
dom.remove();
|
|
337
457
|
}
|
|
338
458
|
};
|
|
339
|
-
const horizontalRuleTheme = EditorView.theme({
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
459
|
+
const horizontalRuleTheme = EditorView.theme({
|
|
460
|
+
".cm-horizontal-rule-container": {
|
|
461
|
+
height: "1.4em",
|
|
462
|
+
display: "flex",
|
|
463
|
+
"align-items": "center",
|
|
464
|
+
padding: "0 2px 0 6px"
|
|
465
|
+
},
|
|
466
|
+
".cm-horizontal-rule-container hr": { width: "100%" }
|
|
467
|
+
});
|
|
345
468
|
const horizonalRuleExtension = [
|
|
346
469
|
foldableSyntaxFacet.of({
|
|
347
470
|
nodePath: "HorizontalRule",
|
|
348
|
-
|
|
471
|
+
buildDecorations: (_state, node) => {
|
|
349
472
|
return Decoration.replace({
|
|
350
473
|
widget: new HorizontalRuleWidget(),
|
|
351
474
|
block: true,
|
|
@@ -360,15 +483,17 @@ const horizonalRuleExtension = [
|
|
|
360
483
|
//#endregion
|
|
361
484
|
//#region lib/fold/image.ts
|
|
362
485
|
var ImageWidget = class extends WidgetType {
|
|
363
|
-
constructor(url) {
|
|
486
|
+
constructor(url, block) {
|
|
364
487
|
super();
|
|
365
488
|
this.url = url;
|
|
489
|
+
this.block = block;
|
|
366
490
|
}
|
|
367
491
|
toDOM() {
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
if (this.
|
|
371
|
-
|
|
492
|
+
const elem = document.createElement(this.block ? "div" : "span");
|
|
493
|
+
elem.className = "cm-image";
|
|
494
|
+
if (this.block) elem.className += " cm-image-block";
|
|
495
|
+
elem.innerHTML = `<img src="${this.url}" />`;
|
|
496
|
+
return elem;
|
|
372
497
|
}
|
|
373
498
|
ignoreEvent(_event) {
|
|
374
499
|
return false;
|
|
@@ -376,12 +501,25 @@ var ImageWidget = class extends WidgetType {
|
|
|
376
501
|
};
|
|
377
502
|
const imageExtension = [foldableSyntaxFacet.of({
|
|
378
503
|
nodePath: "Image",
|
|
379
|
-
|
|
504
|
+
keepDecorationOnUnfold: true,
|
|
505
|
+
buildDecorations: (state, node, selectionTouchesRange$1) => {
|
|
380
506
|
let imageUrl;
|
|
381
507
|
iterChildren(node.node.cursor(), (node$1) => {
|
|
382
508
|
if (node$1.name === "URL") imageUrl = state.doc.sliceString(node$1.from, node$1.to);
|
|
383
509
|
});
|
|
384
|
-
if (imageUrl)
|
|
510
|
+
if (imageUrl) {
|
|
511
|
+
const line = state.doc.lineAt(node.from);
|
|
512
|
+
const block = node.from == line.from && node.to == line.to;
|
|
513
|
+
const widget = new ImageWidget(imageUrl, block);
|
|
514
|
+
if (selectionTouchesRange$1) return Decoration.widget({
|
|
515
|
+
widget,
|
|
516
|
+
block
|
|
517
|
+
}).range(node.to, node.to);
|
|
518
|
+
else return Decoration.replace({
|
|
519
|
+
widget,
|
|
520
|
+
block
|
|
521
|
+
}).range(node.from, node.to);
|
|
522
|
+
}
|
|
385
523
|
}
|
|
386
524
|
}), selectAllDecorationsOnSelectExtension("cm-image")];
|
|
387
525
|
|
|
@@ -406,7 +544,7 @@ var Checkbox = class extends WidgetType {
|
|
|
406
544
|
};
|
|
407
545
|
const taskExtension = [foldableSyntaxFacet.of({
|
|
408
546
|
nodePath: "BulletList/ListItem/Task/TaskMarker",
|
|
409
|
-
|
|
547
|
+
buildDecorations: (state, node) => {
|
|
410
548
|
const value = state.doc.sliceString(node.from + 1, node.to - 1).toLowerCase() === "x";
|
|
411
549
|
return Decoration.replace({ widget: new Checkbox(value) }).range(node.from - 2, node.to);
|
|
412
550
|
},
|
|
@@ -426,23 +564,39 @@ const taskExtension = [foldableSyntaxFacet.of({
|
|
|
426
564
|
} } }))];
|
|
427
565
|
|
|
428
566
|
//#endregion
|
|
429
|
-
//#region lib/fold/
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
567
|
+
//#region lib/fold/index.ts
|
|
568
|
+
const defaultFoldableSyntaxExtensions = [
|
|
569
|
+
blockQuoteExtension,
|
|
570
|
+
bulletListExtension,
|
|
571
|
+
taskExtension,
|
|
572
|
+
imageExtension,
|
|
573
|
+
emojiExtension,
|
|
574
|
+
horizonalRuleExtension,
|
|
575
|
+
dashExtension
|
|
576
|
+
];
|
|
577
|
+
|
|
578
|
+
//#endregion
|
|
579
|
+
//#region lib/revealBlockOnArrow.ts
|
|
580
|
+
const maybeReveal = (decorationField, view, direction) => {
|
|
581
|
+
const decorations = view.state.field(decorationField);
|
|
582
|
+
const cursorAt = view.state.selection.main.head;
|
|
583
|
+
for (let iter = decorations.iter(); iter.value; iter.next()) if (direction === "down" && cursorAt == iter.from - 1) {
|
|
584
|
+
view.dispatch({ selection: EditorSelection.single(iter.from) });
|
|
585
|
+
return true;
|
|
586
|
+
} else if (direction === "up" && cursorAt == iter.to + 1) {
|
|
587
|
+
view.dispatch({ selection: EditorSelection.single(iter.to) });
|
|
588
|
+
return true;
|
|
438
589
|
}
|
|
590
|
+
return false;
|
|
439
591
|
};
|
|
440
|
-
const
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
592
|
+
const revealBlockOnArrowExtension_ = (decorationField) => keymap.of([{
|
|
593
|
+
key: "ArrowUp",
|
|
594
|
+
run: (view) => maybeReveal(decorationField, view, "up")
|
|
595
|
+
}, {
|
|
596
|
+
key: "ArrowDown",
|
|
597
|
+
run: (view) => maybeReveal(decorationField, view, "down")
|
|
598
|
+
}]);
|
|
599
|
+
const revealBlockOnArrowExtension = [hideExtension, foldExtension].map(revealBlockOnArrowExtension_);
|
|
446
600
|
|
|
447
601
|
//#endregion
|
|
448
602
|
//#region lib/syntaxHighlighting.ts
|
|
@@ -538,15 +692,29 @@ const baseTheme = EditorView.theme({
|
|
|
538
692
|
color: "var(--pm-muted-color)",
|
|
539
693
|
margin: "0 0.2em"
|
|
540
694
|
},
|
|
541
|
-
".cm-blockquote-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
695
|
+
".cm-blockquote-line": {
|
|
696
|
+
position: "relative",
|
|
697
|
+
"&:before": {
|
|
698
|
+
content: "\"\"",
|
|
699
|
+
display: "block",
|
|
700
|
+
borderLeft: "solid 0.3em var(--pm-blockquote-vertical-line-background-color)",
|
|
701
|
+
position: "absolute",
|
|
702
|
+
top: "0px",
|
|
703
|
+
bottom: "0px",
|
|
704
|
+
insetInlineStart: "6px",
|
|
705
|
+
zIndex: -10
|
|
706
|
+
}
|
|
707
|
+
},
|
|
708
|
+
".cm-nested-blockquote-border": {
|
|
709
|
+
display: "block",
|
|
710
|
+
borderLeft: "solid 0.3em var(--pm-blockquote-vertical-line-background-color)",
|
|
711
|
+
position: "absolute",
|
|
712
|
+
top: "0px",
|
|
713
|
+
bottom: "0px",
|
|
714
|
+
insetInlineStart: "calc(6px + var(--blockquote-border-offset))",
|
|
715
|
+
zIndex: -10
|
|
716
|
+
},
|
|
717
|
+
".cm-image-block": { paddingLeft: "6px" }
|
|
550
718
|
});
|
|
551
719
|
const generalSyntaxHighlights = syntaxHighlighting(HighlightStyle.define([
|
|
552
720
|
{
|
|
@@ -709,6 +877,70 @@ const clickLinkExtension = [
|
|
|
709
877
|
clickRawUrlExtension
|
|
710
878
|
];
|
|
711
879
|
|
|
880
|
+
//#endregion
|
|
881
|
+
//#region lib/softIndentExtension.ts
|
|
882
|
+
const softIndentPattern = /^(> )*(\s*)?(([-*+]?|\d[.)])\s)?(\[.\]\s)?/;
|
|
883
|
+
const softIndentRefresh = Annotation.define();
|
|
884
|
+
const softIndentExtension = ViewPlugin.fromClass(class {
|
|
885
|
+
decorations = Decoration.none;
|
|
886
|
+
constructor(view) {
|
|
887
|
+
this.requestMeasure(view);
|
|
888
|
+
}
|
|
889
|
+
update(u) {
|
|
890
|
+
if (u.docChanged || u.viewportChanged || u.selectionSet) this.requestMeasure(u.view);
|
|
891
|
+
if (u.transactions.some((tr) => tr.annotation(softIndentRefresh))) this.requestMeasure(u.view);
|
|
892
|
+
}
|
|
893
|
+
requestMeasure(view) {
|
|
894
|
+
view.requestMeasure({
|
|
895
|
+
read: (view$1) => this.measureIndents(view$1),
|
|
896
|
+
write: (indents, view$1) => {
|
|
897
|
+
this.applyIndents(indents, view$1);
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
measureIndents(view) {
|
|
902
|
+
const indents = [];
|
|
903
|
+
for (const { from, to } of view.visibleRanges) {
|
|
904
|
+
const start = view.state.doc.lineAt(from);
|
|
905
|
+
const end = view.state.doc.lineAt(to);
|
|
906
|
+
for (let i = start.number; i <= end.number; i++) {
|
|
907
|
+
const line = view.state.doc.line(i);
|
|
908
|
+
const text = view.state.sliceDoc(line.from, line.to);
|
|
909
|
+
const matches = softIndentPattern.exec(text);
|
|
910
|
+
if (!matches) continue;
|
|
911
|
+
const nonContent = matches[0];
|
|
912
|
+
const indentWidth = (view.coordsAtPos(line.from + nonContent.length)?.left ?? 0) - (view.coordsAtPos(line.from)?.left ?? 0);
|
|
913
|
+
if (!indentWidth) continue;
|
|
914
|
+
indents.push({
|
|
915
|
+
line,
|
|
916
|
+
indentWidth
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
return indents;
|
|
921
|
+
}
|
|
922
|
+
buildDecorations(indents) {
|
|
923
|
+
const builder = new RangeSetBuilder();
|
|
924
|
+
for (const { line, indentWidth } of indents) {
|
|
925
|
+
const deco = Decoration.line({ attributes: { style: `padding-inline-start: ${(indentWidth + 6).toString()}px; text-indent: -${indentWidth.toString()}px;` } });
|
|
926
|
+
builder.add(line.from, line.from, deco);
|
|
927
|
+
}
|
|
928
|
+
return builder.finish();
|
|
929
|
+
}
|
|
930
|
+
applyIndents(indents, view) {
|
|
931
|
+
const newDecos = this.buildDecorations(indents);
|
|
932
|
+
let changed = false;
|
|
933
|
+
for (const { from, to } of view.visibleRanges) if (!RangeSet.eq([this.decorations], [newDecos], from, to)) {
|
|
934
|
+
changed = true;
|
|
935
|
+
break;
|
|
936
|
+
}
|
|
937
|
+
if (changed) queueMicrotask(() => {
|
|
938
|
+
view.dispatch({ annotations: [softIndentRefresh.of(true)] });
|
|
939
|
+
});
|
|
940
|
+
this.decorations = newDecos;
|
|
941
|
+
}
|
|
942
|
+
}, { decorations: (v) => v.decorations });
|
|
943
|
+
|
|
712
944
|
//#endregion
|
|
713
945
|
//#region lib/codeFenceExtension.ts
|
|
714
946
|
const codeBlockDecorations = (view) => {
|
|
@@ -829,17 +1061,17 @@ const codeFenceTheme = EditorView.theme({
|
|
|
829
1061
|
const prosemarkMarkdownSyntaxExtensions = [
|
|
830
1062
|
additionalMarkdownSyntaxTags,
|
|
831
1063
|
escapeMarkdownSyntaxExtension,
|
|
832
|
-
emojiMarkdownSyntaxExtension
|
|
833
|
-
|
|
834
|
-
const defaultFoldableSyntaxExtensions = [
|
|
835
|
-
blockQuoteExtension,
|
|
836
|
-
bulletListExtension,
|
|
837
|
-
taskExtension,
|
|
838
|
-
imageExtension,
|
|
839
|
-
emojiExtension,
|
|
840
|
-
horizonalRuleExtension
|
|
1064
|
+
emojiMarkdownSyntaxExtension,
|
|
1065
|
+
dashMarkdownSyntaxExtension
|
|
841
1066
|
];
|
|
842
1067
|
const prosemarkBasicSetup = () => [
|
|
1068
|
+
defaultHideExtensions,
|
|
1069
|
+
defaultFoldableSyntaxExtensions,
|
|
1070
|
+
revealBlockOnArrowExtension,
|
|
1071
|
+
clickLinkExtension,
|
|
1072
|
+
defaultClickLinkHandler,
|
|
1073
|
+
softIndentExtension,
|
|
1074
|
+
codeBlockDecorationsExtension,
|
|
843
1075
|
history(),
|
|
844
1076
|
dropCursor(),
|
|
845
1077
|
indentOnInput(),
|
|
@@ -857,11 +1089,7 @@ const prosemarkBasicSetup = () => [
|
|
|
857
1089
|
indentWithTab
|
|
858
1090
|
]),
|
|
859
1091
|
foldGutter(),
|
|
860
|
-
EditorView.lineWrapping
|
|
861
|
-
defaultHideExtensions,
|
|
862
|
-
defaultFoldableSyntaxExtensions,
|
|
863
|
-
clickLinkExtension,
|
|
864
|
-
codeBlockDecorationsExtension
|
|
1092
|
+
EditorView.lineWrapping
|
|
865
1093
|
];
|
|
866
1094
|
const prosemarkBaseThemeSetup = () => [
|
|
867
1095
|
baseSyntaxHighlights,
|
|
@@ -869,7 +1097,7 @@ const prosemarkBaseThemeSetup = () => [
|
|
|
869
1097
|
baseTheme,
|
|
870
1098
|
codeFenceTheme
|
|
871
1099
|
];
|
|
872
|
-
const prosemarkLightThemeSetup = () => lightTheme;
|
|
1100
|
+
const prosemarkLightThemeSetup = () => [prosemarkBaseThemeSetup(), lightTheme];
|
|
873
1101
|
|
|
874
1102
|
//#endregion
|
|
875
|
-
export { additionalMarkdownSyntaxTags, baseSyntaxHighlights, baseTheme, blockQuoteExtension, bulletListExtension, clickLinkExtension, clickLinkHandler, codeBlockDecorationsExtension, codeFenceTheme, defaultClickLinkHandler, defaultFoldableSyntaxExtensions, defaultHideExtensions, emojiExtension, emojiMarkdownSyntaxExtension, escapeMarkdownSyntaxExtension, eventHandlersWithClass,
|
|
1103
|
+
export { additionalMarkdownSyntaxTags, baseSyntaxHighlights, baseTheme, blockQuoteExtension, bulletListExtension, clickLinkExtension, clickLinkHandler, codeBlockDecorationsExtension, codeFenceTheme, dashExtension, dashMarkdownSyntaxExtension, defaultClickLinkHandler, defaultFoldableSyntaxExtensions, defaultHideExtensions, emojiExtension, emojiMarkdownSyntaxExtension, escapeMarkdownSyntaxExtension, eventHandlersWithClass, foldExtension, foldableSyntaxFacet, generalSyntaxHighlights, hideExtension, horizonalRuleExtension, imageExtension, lightTheme, markdownTags, prosemarkBaseThemeSetup, prosemarkBasicSetup, prosemarkLightThemeSetup, prosemarkMarkdownSyntaxExtensions, revealBlockOnArrowExtension, selectAllDecorationsOnSelectExtension, softIndentExtension, taskExtension };
|
package/package.json
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prosemark/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"repository": {
|
|
5
|
+
"url": "https://github.com/jsimonrichard/ProseMark",
|
|
6
|
+
"type": "github"
|
|
7
|
+
},
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"author": {
|
|
10
|
+
"name": "J. Simon Richard",
|
|
11
|
+
"url": "https://jsimonrichard.com"
|
|
12
|
+
},
|
|
4
13
|
"type": "module",
|
|
5
14
|
"files": [
|
|
6
15
|
"dist"
|
|
@@ -19,7 +28,7 @@
|
|
|
19
28
|
"preview": "vite preview",
|
|
20
29
|
"lint": "eslint --max-warnings=0",
|
|
21
30
|
"check-types": "tsc",
|
|
22
|
-
"ci:publish": "
|
|
31
|
+
"ci:publish": "bash ../../scripts/ci-publish.sh"
|
|
23
32
|
},
|
|
24
33
|
"dependencies": {
|
|
25
34
|
"@lezer/common": "^1.2.3",
|