@dxos/react-ui-editor 0.3.10-next.e7dbe51 → 0.3.10
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/lib/browser/index.mjs +1270 -372
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +23 -2
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +2 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +3 -0
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/basic.d.ts +2 -1
- package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts +25 -0
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/code.d.ts +2 -0
- package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts +11 -7
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/demo.d.ts +11 -0
- package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/experimental.d.ts +1 -1
- package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/highlight.d.ts +24 -0
- package/dist/types/src/components/TextEditor/extensions/highlight.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/image.d.ts +4 -0
- package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/index.d.ts +7 -0
- package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/listener.d.ts +4 -2
- package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts +10 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts +9 -3
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/mention.d.ts +6 -0
- package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/table.d.ts +8 -0
- package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +2 -1
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/themes/default.d.ts +5 -0
- package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts +3 -0
- package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts +8 -1
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/index.d.ts +1 -1
- package/dist/types/src/hooks/automerge/index.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts +5 -0
- package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts +6 -0
- package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/translation/index.d.ts +3 -0
- package/dist/types/src/hooks/automerge/translation/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextModel.d.ts +6 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/{components/TextEditor → hooks/yjs}/yjs.stories.d.ts +2 -2
- package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +1 -0
- package/dist/types/src/styles/markdown.d.ts +3 -2
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/testing/replicator.d.ts.map +1 -1
- package/package.json +23 -20
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +128 -34
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -1
- package/src/components/TextEditor/TextEditor.tsx +30 -9
- package/src/components/TextEditor/extensions/autocomplete.ts +5 -20
- package/src/components/TextEditor/extensions/basic.ts +6 -4
- package/src/components/TextEditor/extensions/blast.ts +373 -0
- package/src/components/TextEditor/extensions/code.ts +99 -0
- package/src/components/TextEditor/extensions/comments.ts +67 -67
- package/src/components/TextEditor/extensions/demo.ts +69 -0
- package/src/components/TextEditor/extensions/experimental.tsx +15 -36
- package/src/components/TextEditor/extensions/highlight.ts +128 -0
- package/src/components/TextEditor/extensions/image.ts +67 -0
- package/src/components/TextEditor/extensions/index.ts +7 -0
- package/src/components/TextEditor/extensions/link.ts +17 -25
- package/src/components/TextEditor/extensions/listener.ts +4 -4
- package/src/components/TextEditor/extensions/markdown/bundle.ts +45 -34
- package/src/components/TextEditor/extensions/markdown/highlight.ts +148 -108
- package/src/components/TextEditor/extensions/mention.ts +31 -0
- package/src/components/TextEditor/extensions/table.ts +119 -0
- package/src/components/TextEditor/extensions/tasklist.ts +42 -28
- package/src/components/TextEditor/themes/default.ts +98 -4
- package/src/hooks/automerge/PatchSemaphore.ts +12 -9
- package/src/hooks/automerge/automerge.stories.tsx +4 -2
- package/src/hooks/automerge/index.ts +1 -1
- package/src/hooks/automerge/plugin.ts +1 -0
- package/src/hooks/automerge/{amToCodemirror.ts → translation/automerge-to-codemirror.ts} +10 -2
- package/src/hooks/automerge/{codeMirrorToAm.ts → translation/codemirror-to-automerge.ts} +7 -4
- package/src/hooks/automerge/translation/index.ts +6 -0
- package/src/hooks/useTextModel.ts +9 -0
- package/src/{components/TextEditor → hooks/yjs}/yjs.stories.tsx +2 -2
- package/src/styles/markdown.ts +15 -8
- package/src/testing/replicator.ts +1 -0
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/amToCodemirror.d.ts +0 -6
- package/dist/types/src/hooks/automerge/amToCodemirror.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts +0 -7
- package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts.map +0 -1
|
@@ -24,13 +24,13 @@ var autocomplete = ({ onSearch }) => {
|
|
|
24
24
|
// TODO(burdon): Optional decoration via addToOptions
|
|
25
25
|
override: [
|
|
26
26
|
(context) => {
|
|
27
|
-
const
|
|
28
|
-
if (!
|
|
27
|
+
const match = context.matchBefore(/\w*/);
|
|
28
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
31
31
|
return {
|
|
32
|
-
from:
|
|
33
|
-
options: onSearch(
|
|
32
|
+
from: match.from,
|
|
33
|
+
options: onSearch(match.text.toLowerCase())
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
]
|
|
@@ -42,30 +42,531 @@ var autocomplete = ({ onSearch }) => {
|
|
|
42
42
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
43
43
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
44
44
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
45
|
-
import { EditorView, placeholder } from "@codemirror/view";
|
|
46
|
-
var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
|
|
45
|
+
import { drawSelection, EditorView, placeholder } from "@codemirror/view";
|
|
46
|
+
var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
47
|
+
EditorView.lineWrapping,
|
|
47
48
|
// TODO(burdon): Compare with minimalSetup.
|
|
48
49
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
49
50
|
bracketMatching(),
|
|
50
51
|
closeBrackets(),
|
|
51
|
-
|
|
52
|
+
drawSelection(),
|
|
52
53
|
_placeholder && placeholder(_placeholder),
|
|
53
54
|
// TODO(burdon): Is this required?
|
|
54
55
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
55
56
|
].filter(Boolean);
|
|
56
57
|
|
|
57
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/
|
|
58
|
-
import {
|
|
58
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts
|
|
59
|
+
import { EditorView as EditorView2, keymap as keymap2 } from "@codemirror/view";
|
|
60
|
+
import defaultsDeep from "lodash.defaultsdeep";
|
|
59
61
|
import { invariant } from "@dxos/invariant";
|
|
60
|
-
var __dxlog_file = "/home/
|
|
62
|
+
var __dxlog_file = "/home/circleci/project/packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts";
|
|
63
|
+
var defaultOptions = {
|
|
64
|
+
effect: 2,
|
|
65
|
+
maxParticles: 200,
|
|
66
|
+
particleGravity: 0.08,
|
|
67
|
+
particleAlphaFadeout: 0.996,
|
|
68
|
+
particleSize: {
|
|
69
|
+
min: 2,
|
|
70
|
+
max: 8
|
|
71
|
+
},
|
|
72
|
+
particleNumRange: {
|
|
73
|
+
min: 5,
|
|
74
|
+
max: 10
|
|
75
|
+
},
|
|
76
|
+
particleVelocityRange: {
|
|
77
|
+
x: [
|
|
78
|
+
-1,
|
|
79
|
+
1
|
|
80
|
+
],
|
|
81
|
+
y: [
|
|
82
|
+
-3.5,
|
|
83
|
+
-1.5
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
particleShrinkRate: 0.95,
|
|
87
|
+
shakeIntensity: 5
|
|
88
|
+
};
|
|
89
|
+
var blast = (options = defaultOptions) => {
|
|
90
|
+
let blaster;
|
|
91
|
+
let last = 0;
|
|
92
|
+
const getPoint = (view, pos) => {
|
|
93
|
+
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
94
|
+
const element = document.elementFromPoint(x, y);
|
|
95
|
+
const { offsetLeft: left = 0, offsetTop: top = 0 } = view.scrollDOM.parentElement ?? {};
|
|
96
|
+
const point = {
|
|
97
|
+
x: x - left,
|
|
98
|
+
y: y - top
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
element,
|
|
102
|
+
point
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
return [
|
|
106
|
+
// Cursor moved.
|
|
107
|
+
EditorView2.updateListener.of((update4) => {
|
|
108
|
+
if (blaster?.node !== update4.view.scrollDOM) {
|
|
109
|
+
if (blaster) {
|
|
110
|
+
blaster.destroy();
|
|
111
|
+
}
|
|
112
|
+
blaster = new Blaster(update4.view.scrollDOM, defaultsDeep({
|
|
113
|
+
particleGravity: 0.2,
|
|
114
|
+
particleShrinkRate: 0.995,
|
|
115
|
+
color: () => [
|
|
116
|
+
100 + Math.random() * 100,
|
|
117
|
+
0,
|
|
118
|
+
0
|
|
119
|
+
]
|
|
120
|
+
}, options, defaultOptions));
|
|
121
|
+
blaster.initialize();
|
|
122
|
+
blaster.start();
|
|
123
|
+
} else {
|
|
124
|
+
blaster.resize();
|
|
125
|
+
}
|
|
126
|
+
const current = update4.state.selection.main.head;
|
|
127
|
+
if (current !== last) {
|
|
128
|
+
last = current;
|
|
129
|
+
const { element, point } = getPoint(update4.view, current - 1);
|
|
130
|
+
if (element && point) {
|
|
131
|
+
blaster.spawn({
|
|
132
|
+
element,
|
|
133
|
+
point
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
138
|
+
keymap2.of([
|
|
139
|
+
{
|
|
140
|
+
any: (_, event) => {
|
|
141
|
+
if (blaster) {
|
|
142
|
+
if (event.key === "Enter" && event.shiftKey) {
|
|
143
|
+
blaster.shake({
|
|
144
|
+
time: 0.8
|
|
145
|
+
});
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
])
|
|
153
|
+
];
|
|
154
|
+
};
|
|
155
|
+
var Blaster = class {
|
|
156
|
+
constructor(_node, _options) {
|
|
157
|
+
this._node = _node;
|
|
158
|
+
this._options = _options;
|
|
159
|
+
this._running = false;
|
|
160
|
+
this._shakeTime = 0;
|
|
161
|
+
this._shakeTimeMax = 0;
|
|
162
|
+
this._particles = [];
|
|
163
|
+
this._particlePointer = 0;
|
|
164
|
+
this._lastPoint = {
|
|
165
|
+
x: 0,
|
|
166
|
+
y: 0
|
|
167
|
+
};
|
|
168
|
+
this.shake = throttle(({ time }) => {
|
|
169
|
+
this._shakeTime = this._shakeTimeMax || time;
|
|
170
|
+
this._shakeTimeMax = time;
|
|
171
|
+
}, 100);
|
|
172
|
+
this.spawn = throttle(({ element, point }) => {
|
|
173
|
+
const color = getRGBComponents(element, this._options.color);
|
|
174
|
+
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
175
|
+
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
176
|
+
this._lastPoint = point;
|
|
177
|
+
for (let i = numParticles; i--; i > 0) {
|
|
178
|
+
this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
|
|
179
|
+
this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
|
|
180
|
+
}
|
|
181
|
+
}, 100);
|
|
182
|
+
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
183
|
+
}
|
|
184
|
+
get node() {
|
|
185
|
+
return this._node;
|
|
186
|
+
}
|
|
187
|
+
initialize() {
|
|
188
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
189
|
+
F: __dxlog_file,
|
|
190
|
+
L: 138,
|
|
191
|
+
S: this,
|
|
192
|
+
A: [
|
|
193
|
+
"!this._canvas && !this._ctx",
|
|
194
|
+
""
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
this._canvas = document.createElement("canvas");
|
|
198
|
+
this._canvas.id = "code-blast-canvas";
|
|
199
|
+
this._canvas.style.position = "absolute";
|
|
200
|
+
this._canvas.style.zIndex = "0";
|
|
201
|
+
this._canvas.style.pointerEvents = "none";
|
|
202
|
+
this._ctx = this._canvas.getContext("2d");
|
|
203
|
+
const parent = this._node.parentElement?.parentElement;
|
|
204
|
+
parent?.appendChild(this._canvas);
|
|
205
|
+
this.resize();
|
|
206
|
+
}
|
|
207
|
+
destroy() {
|
|
208
|
+
this.stop();
|
|
209
|
+
if (this._canvas) {
|
|
210
|
+
this._canvas.remove();
|
|
211
|
+
this._canvas = void 0;
|
|
212
|
+
this._ctx = void 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
resize() {
|
|
216
|
+
if (this._node.parentElement && this._canvas) {
|
|
217
|
+
const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
|
|
218
|
+
this._canvas.style.top = `${y}px`;
|
|
219
|
+
this._canvas.style.left = `${x}px`;
|
|
220
|
+
this._canvas.width = width;
|
|
221
|
+
this._canvas.height = height;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
start() {
|
|
225
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
226
|
+
F: __dxlog_file,
|
|
227
|
+
L: 177,
|
|
228
|
+
S: this,
|
|
229
|
+
A: [
|
|
230
|
+
"this._canvas && this._ctx",
|
|
231
|
+
""
|
|
232
|
+
]
|
|
233
|
+
});
|
|
234
|
+
this._running = true;
|
|
235
|
+
this.loop();
|
|
236
|
+
}
|
|
237
|
+
stop() {
|
|
238
|
+
this._running = false;
|
|
239
|
+
this._node.style.transform = "translate(0px, 0px)";
|
|
240
|
+
}
|
|
241
|
+
loop() {
|
|
242
|
+
if (!this._running || !this._canvas || !this._ctx) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
this._ctx.clearRect(0, 0, this._canvas.width ?? 0, this._canvas.height ?? 0);
|
|
246
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
247
|
+
this._lastTime ??= now;
|
|
248
|
+
const dt = (now - this._lastTime) / 1e3;
|
|
249
|
+
this._lastTime = now;
|
|
250
|
+
if (this._shakeTime > 0) {
|
|
251
|
+
this._shakeTime -= dt;
|
|
252
|
+
const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
|
|
253
|
+
const shakeX = random(-magnitude, magnitude);
|
|
254
|
+
const shakeY = random(-magnitude, magnitude);
|
|
255
|
+
this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
|
|
256
|
+
}
|
|
257
|
+
this.drawParticles();
|
|
258
|
+
requestAnimationFrame(this.loop.bind(this));
|
|
259
|
+
}
|
|
260
|
+
drawParticles() {
|
|
261
|
+
for (let i = this._particles.length; i--; i > 0) {
|
|
262
|
+
const particle = this._particles[i];
|
|
263
|
+
if (!particle) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (particle.alpha < 0.01 || particle.size <= 0.5) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
this._effect.update(this._ctx, particle);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
var Effect = class {
|
|
274
|
+
constructor(_options) {
|
|
275
|
+
this._options = _options;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
var Effect1 = class extends Effect {
|
|
279
|
+
create(x, y, color) {
|
|
280
|
+
return {
|
|
281
|
+
x,
|
|
282
|
+
y: y + 10,
|
|
283
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
284
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
285
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
286
|
+
color,
|
|
287
|
+
alpha: 1
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
update(ctx, particle) {
|
|
291
|
+
particle.vy += this._options.particleGravity;
|
|
292
|
+
particle.x += particle.vx;
|
|
293
|
+
particle.y += particle.vy;
|
|
294
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
295
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
296
|
+
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
var Effect2 = class extends Effect {
|
|
300
|
+
create(x, y, color) {
|
|
301
|
+
return {
|
|
302
|
+
x,
|
|
303
|
+
y: y + 10,
|
|
304
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
305
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
306
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
307
|
+
color,
|
|
308
|
+
alpha: 1,
|
|
309
|
+
theta: random(0, 360) * Math.PI / 180,
|
|
310
|
+
drag: 0.92,
|
|
311
|
+
wander: 0.15
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
update(ctx, particle) {
|
|
315
|
+
particle.vy += this._options.particleGravity;
|
|
316
|
+
particle.x += particle.vx;
|
|
317
|
+
particle.y += particle.vy;
|
|
318
|
+
particle.vx *= particle.drag;
|
|
319
|
+
particle.vy *= particle.drag;
|
|
320
|
+
particle.theta += random(-0.5, 0.5);
|
|
321
|
+
particle.vx += Math.sin(particle.theta) * 0.1;
|
|
322
|
+
particle.vy += Math.cos(particle.theta) * 0.1;
|
|
323
|
+
particle.size *= this._options.particleShrinkRate;
|
|
324
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
325
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
326
|
+
ctx.beginPath();
|
|
327
|
+
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
|
328
|
+
ctx.fill();
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
function throttle(callback, limit) {
|
|
332
|
+
let wait = false;
|
|
333
|
+
return function(...args) {
|
|
334
|
+
if (!wait) {
|
|
335
|
+
callback.apply(this, args);
|
|
336
|
+
wait = true;
|
|
337
|
+
setTimeout(() => {
|
|
338
|
+
wait = false;
|
|
339
|
+
}, limit);
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
var getRGBComponents = (node, color) => {
|
|
344
|
+
if (typeof color === "function") {
|
|
345
|
+
return color();
|
|
346
|
+
}
|
|
347
|
+
const bgColor = getComputedStyle(node).color;
|
|
348
|
+
if (bgColor) {
|
|
349
|
+
const x = bgColor.match(/(\d+), (\d+), (\d+)/)?.slice(1);
|
|
350
|
+
if (x) {
|
|
351
|
+
return x;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return [
|
|
355
|
+
50,
|
|
356
|
+
50,
|
|
357
|
+
50
|
|
358
|
+
];
|
|
359
|
+
};
|
|
360
|
+
var random = (min, max) => {
|
|
361
|
+
if (!max) {
|
|
362
|
+
max = min;
|
|
363
|
+
min = 0;
|
|
364
|
+
}
|
|
365
|
+
return min + ~~(Math.random() * (max - min + 1));
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/code.ts
|
|
369
|
+
import { ViewPlugin, EditorView as EditorView3, Decoration } from "@codemirror/view";
|
|
370
|
+
import get from "lodash.get";
|
|
371
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
372
|
+
|
|
373
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
374
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
375
|
+
var headings = {
|
|
376
|
+
1: [
|
|
377
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
378
|
+
"-ml-[10px]"
|
|
379
|
+
],
|
|
380
|
+
2: [
|
|
381
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
382
|
+
"-ml-[8px]"
|
|
383
|
+
],
|
|
384
|
+
3: [
|
|
385
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
386
|
+
"-ml-[7px]"
|
|
387
|
+
],
|
|
388
|
+
4: [
|
|
389
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
390
|
+
"-ml-[6px]"
|
|
391
|
+
],
|
|
392
|
+
5: [
|
|
393
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
394
|
+
"-ml-[5px]"
|
|
395
|
+
],
|
|
396
|
+
6: [
|
|
397
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
398
|
+
"-ml-[4px]"
|
|
399
|
+
]
|
|
400
|
+
};
|
|
401
|
+
var heading = (level, readonly) => {
|
|
402
|
+
const [style, offset] = headings[level];
|
|
403
|
+
return mx(style, readonly && offset);
|
|
404
|
+
};
|
|
405
|
+
var light = "text-neutral-200 dark:text-neutral-800";
|
|
406
|
+
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
407
|
+
var bold = "font-bold";
|
|
408
|
+
var italic = "italic";
|
|
409
|
+
var strikethrough = "line-through";
|
|
410
|
+
var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
411
|
+
var codeMark = "font-mono text-primary-500";
|
|
412
|
+
var inlineUrl = mx(code, "px-1");
|
|
413
|
+
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
414
|
+
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800";
|
|
415
|
+
|
|
416
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
417
|
+
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
418
|
+
var tokens = tailwindConfig({}).theme;
|
|
419
|
+
|
|
420
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/code.ts
|
|
421
|
+
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
422
|
+
var styles = EditorView3.baseTheme({
|
|
423
|
+
"& .cm-code-block": {
|
|
424
|
+
display: "block",
|
|
425
|
+
paddingInline: "4px !important"
|
|
426
|
+
},
|
|
427
|
+
"&light .cm-code-block": {
|
|
428
|
+
background: get(tokens, "extend.colors.neutral.50")
|
|
429
|
+
},
|
|
430
|
+
"&dark .cm-code-block": {
|
|
431
|
+
background: get(tokens, "extend.colors.neutral.850")
|
|
432
|
+
},
|
|
433
|
+
"& .cm-code-block-first": {
|
|
434
|
+
paddingTop: "4px !important",
|
|
435
|
+
borderTopLeftRadius: "4px",
|
|
436
|
+
borderTopRightRadius: "4px"
|
|
437
|
+
},
|
|
438
|
+
"& .cm-code-block-last": {
|
|
439
|
+
paddingBottom: "4px !important",
|
|
440
|
+
borderBottomLeftRadius: "4px",
|
|
441
|
+
borderBottomRightRadius: "4px"
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
var getLineRange = (lines, from, to) => {
|
|
445
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
446
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
447
|
+
return [
|
|
448
|
+
start,
|
|
449
|
+
end
|
|
450
|
+
];
|
|
451
|
+
};
|
|
452
|
+
var code2 = () => {
|
|
453
|
+
const getDecorations = (view) => {
|
|
454
|
+
const decorations = [];
|
|
455
|
+
if (view.state.readOnly) {
|
|
456
|
+
const text = view.state.doc.sliceString(0);
|
|
457
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
458
|
+
const blocks = view.viewportLineBlocks;
|
|
459
|
+
for (const match of matches) {
|
|
460
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
461
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
462
|
+
const block = blocks[i];
|
|
463
|
+
decorations.push(Decoration.line({
|
|
464
|
+
class: mx2("cm-code-block", i === range[0] && "cm-code-block-first", i === range[1] && "cm-code-block-last")
|
|
465
|
+
}).range(block.from));
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return Decoration.set(decorations);
|
|
470
|
+
};
|
|
471
|
+
return [
|
|
472
|
+
ViewPlugin.fromClass(class {
|
|
473
|
+
constructor(view) {
|
|
474
|
+
this.decorations = getDecorations(view);
|
|
475
|
+
}
|
|
476
|
+
update(update4) {
|
|
477
|
+
if (update4.docChanged || update4.viewportChanged) {
|
|
478
|
+
this.decorations = getDecorations(update4.view);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}, {
|
|
482
|
+
decorations: (value) => value.decorations
|
|
483
|
+
}),
|
|
484
|
+
styles
|
|
485
|
+
];
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
|
|
489
|
+
import { keymap as keymap3 } from "@codemirror/view";
|
|
490
|
+
var defaultItems = [
|
|
491
|
+
"hello world!",
|
|
492
|
+
"this is a test.",
|
|
493
|
+
"this is [DXOS](https://dxos.org)"
|
|
494
|
+
];
|
|
495
|
+
var demo = ({ delay = 75, items = defaultItems } = {}) => {
|
|
496
|
+
let t;
|
|
497
|
+
let idx = 0;
|
|
498
|
+
return [
|
|
499
|
+
keymap3.of([
|
|
500
|
+
{
|
|
501
|
+
// Reset.
|
|
502
|
+
key: "alt-meta-'",
|
|
503
|
+
run: (view) => {
|
|
504
|
+
clearTimeout(t);
|
|
505
|
+
idx = 0;
|
|
506
|
+
return true;
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
// Next prompt.
|
|
511
|
+
// TODO(burdon): Press 1-9 to select prompt?
|
|
512
|
+
key: "shift-meta-'",
|
|
513
|
+
run: (view) => {
|
|
514
|
+
clearTimeout(t);
|
|
515
|
+
const text = items[idx++];
|
|
516
|
+
if (idx === items?.length) {
|
|
517
|
+
idx = 0;
|
|
518
|
+
}
|
|
519
|
+
let i = 0;
|
|
520
|
+
const insert = (d = 0) => {
|
|
521
|
+
t = setTimeout(() => {
|
|
522
|
+
const pos = view.state.selection.main.head;
|
|
523
|
+
view.dispatch({
|
|
524
|
+
changes: {
|
|
525
|
+
from: pos,
|
|
526
|
+
insert: text[i++]
|
|
527
|
+
},
|
|
528
|
+
selection: {
|
|
529
|
+
anchor: pos + 1
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
if (i < text.length) {
|
|
533
|
+
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
534
|
+
}
|
|
535
|
+
}, d);
|
|
536
|
+
};
|
|
537
|
+
insert();
|
|
538
|
+
return true;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
])
|
|
542
|
+
];
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
|
|
546
|
+
import { keymap as keymap4, Decoration as Decoration2, EditorView as EditorView4, MatchDecorator, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
547
|
+
import { debounce } from "@dxos/async";
|
|
548
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
549
|
+
var __dxlog_file2 = "/home/circleci/project/packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts";
|
|
550
|
+
var styles2 = EditorView4.baseTheme({
|
|
551
|
+
"& .cm-bookmark": {
|
|
552
|
+
cursor: "pointer",
|
|
553
|
+
margin: "4px",
|
|
554
|
+
padding: "4px",
|
|
555
|
+
backgroundColor: "yellow"
|
|
556
|
+
},
|
|
557
|
+
"& .cm-bookmark-selected": {
|
|
558
|
+
backgroundColor: "orange"
|
|
559
|
+
}
|
|
560
|
+
});
|
|
61
561
|
var BookmarkWidget = class extends WidgetType {
|
|
62
|
-
constructor(_pos, _id) {
|
|
562
|
+
constructor(_pos, _id, _handleClick) {
|
|
63
563
|
super();
|
|
64
564
|
this._pos = _pos;
|
|
65
565
|
this._id = _id;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
566
|
+
this._handleClick = _handleClick;
|
|
567
|
+
invariant2(this._id, void 0, {
|
|
568
|
+
F: __dxlog_file2,
|
|
569
|
+
L: 37,
|
|
69
570
|
S: this,
|
|
70
571
|
A: [
|
|
71
572
|
"this._id",
|
|
@@ -76,62 +577,60 @@ var BookmarkWidget = class extends WidgetType {
|
|
|
76
577
|
eq(other) {
|
|
77
578
|
return this._id === other._id;
|
|
78
579
|
}
|
|
79
|
-
// TODO(burdon): Click to select.
|
|
80
580
|
toDOM() {
|
|
81
581
|
const span = document.createElement("span");
|
|
82
582
|
span.className = "cm-bookmark";
|
|
83
|
-
span.textContent = "\
|
|
583
|
+
span.textContent = "\xA7";
|
|
584
|
+
span.onclick = () => this._handleClick();
|
|
84
585
|
return span;
|
|
85
586
|
}
|
|
86
587
|
};
|
|
87
|
-
var styles = EditorView2.baseTheme({
|
|
88
|
-
"& .cm-bookmark": {
|
|
89
|
-
cursor: "pointer",
|
|
90
|
-
margin: "4px",
|
|
91
|
-
padding: "4px",
|
|
92
|
-
backgroundColor: "yellow"
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
588
|
var comments = (options = {}) => {
|
|
589
|
+
let active;
|
|
96
590
|
const bookmarkMatcher = new MatchDecorator({
|
|
97
591
|
regexp: /\[\^(\w+)\]/g,
|
|
98
592
|
decoration: (match, view, pos) => {
|
|
99
593
|
const id = match[1];
|
|
100
|
-
return
|
|
594
|
+
return Decoration2.replace({
|
|
101
595
|
id,
|
|
102
|
-
widget: new BookmarkWidget(pos, id)
|
|
596
|
+
widget: new BookmarkWidget(pos, id, () => handleUpdate({
|
|
597
|
+
active: id
|
|
598
|
+
}))
|
|
103
599
|
});
|
|
104
600
|
}
|
|
105
601
|
});
|
|
106
|
-
const bookmarks =
|
|
602
|
+
const bookmarks = ViewPlugin2.fromClass(class {
|
|
107
603
|
constructor(view) {
|
|
108
604
|
this.bookmarks = bookmarkMatcher.createDeco(view);
|
|
109
605
|
}
|
|
110
|
-
update(
|
|
111
|
-
this.bookmarks = bookmarkMatcher.updateDeco(
|
|
606
|
+
update(update4) {
|
|
607
|
+
this.bookmarks = bookmarkMatcher.updateDeco(update4, this.bookmarks);
|
|
112
608
|
}
|
|
113
609
|
}, {
|
|
114
610
|
decorations: (instance) => instance.bookmarks,
|
|
115
|
-
provide: (plugin) =>
|
|
116
|
-
return view.plugin(plugin)?.bookmarks ||
|
|
611
|
+
provide: (plugin) => EditorView4.atomicRanges.of((view) => {
|
|
612
|
+
return view.plugin(plugin)?.bookmarks || Decoration2.none;
|
|
117
613
|
})
|
|
118
614
|
});
|
|
615
|
+
const handleUpdate = debounce((data) => {
|
|
616
|
+
options.onUpdate?.(data);
|
|
617
|
+
}, 200);
|
|
119
618
|
return [
|
|
120
|
-
|
|
619
|
+
keymap4.of([
|
|
121
620
|
{
|
|
122
|
-
key: options?.key ?? "
|
|
621
|
+
key: options?.key ?? "shift-meta-c",
|
|
123
622
|
run: (view) => {
|
|
124
|
-
const
|
|
623
|
+
const { from, to, head } = view.state.selection.main;
|
|
624
|
+
const id = options.onCreate?.(from, to);
|
|
125
625
|
if (id) {
|
|
126
|
-
const pos = view.state.selection.main.head;
|
|
127
626
|
const tag = `[^${id}]`;
|
|
128
627
|
view.dispatch({
|
|
129
628
|
changes: {
|
|
130
|
-
from:
|
|
629
|
+
from: head,
|
|
131
630
|
insert: tag
|
|
132
631
|
},
|
|
133
632
|
selection: {
|
|
134
|
-
anchor:
|
|
633
|
+
anchor: head + tag.length
|
|
135
634
|
}
|
|
136
635
|
});
|
|
137
636
|
return true;
|
|
@@ -142,42 +641,210 @@ var comments = (options = {}) => {
|
|
|
142
641
|
]),
|
|
143
642
|
bookmarks,
|
|
144
643
|
// Monitor cursor movement.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
644
|
+
EditorView4.updateListener.of((update4) => {
|
|
645
|
+
active = void 0;
|
|
646
|
+
if (!options.onUpdate) {
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
const { view, state } = update4;
|
|
650
|
+
const pos = state.selection.main.head;
|
|
148
651
|
const decorations = [];
|
|
149
652
|
const rangeSet = view.plugin(bookmarks)?.bookmarks;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
653
|
+
let closest = Infinity;
|
|
654
|
+
const { from, to } = (
|
|
655
|
+
/* view.visibleRanges?.[0] ?? */
|
|
656
|
+
{
|
|
657
|
+
from: 0,
|
|
658
|
+
to: state.doc.length
|
|
659
|
+
}
|
|
660
|
+
);
|
|
661
|
+
rangeSet?.between(from, to, (from2, to2, value) => {
|
|
662
|
+
decorations.push({
|
|
663
|
+
from: from2,
|
|
664
|
+
to: to2,
|
|
665
|
+
value
|
|
666
|
+
});
|
|
667
|
+
const d = Math.min(Math.abs(pos - from2), Math.abs(pos - to2));
|
|
668
|
+
if (d < closest) {
|
|
669
|
+
active = value.spec.id;
|
|
670
|
+
closest = d;
|
|
157
671
|
}
|
|
158
672
|
});
|
|
159
673
|
if (decorations.length) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
});
|
|
169
|
-
}
|
|
674
|
+
handleUpdate({
|
|
675
|
+
active,
|
|
676
|
+
items: decorations.map(({ from: from2, value: { spec: { id } } }) => ({
|
|
677
|
+
id,
|
|
678
|
+
pos: from2,
|
|
679
|
+
location: view.coordsAtPos(from2)
|
|
680
|
+
}))
|
|
681
|
+
});
|
|
170
682
|
}
|
|
171
683
|
}),
|
|
172
|
-
|
|
684
|
+
styles2
|
|
173
685
|
];
|
|
174
686
|
};
|
|
175
687
|
|
|
176
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/
|
|
688
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/highlight.ts
|
|
689
|
+
import { StateEffect, StateField } from "@codemirror/state";
|
|
690
|
+
import { Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
|
|
691
|
+
import sortBy from "lodash.sortby";
|
|
692
|
+
import { useEffect } from "react";
|
|
693
|
+
var styles3 = EditorView5.baseTheme({
|
|
694
|
+
"& .cm-highlight": {
|
|
695
|
+
backgroundColor: "yellow"
|
|
696
|
+
},
|
|
697
|
+
"& .cm-highlight::before": {
|
|
698
|
+
content: "]"
|
|
699
|
+
},
|
|
700
|
+
"& .cm-highlight-active": {
|
|
701
|
+
backgroundColor: "lime"
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
var marks = {
|
|
705
|
+
highlight: Decoration3.mark({
|
|
706
|
+
class: "cm-highlight"
|
|
707
|
+
}),
|
|
708
|
+
HighlightActive: Decoration3.mark({
|
|
709
|
+
class: "cm-highlight-active"
|
|
710
|
+
})
|
|
711
|
+
};
|
|
712
|
+
var setHighlights = StateEffect.define();
|
|
713
|
+
var useHighlights = (view, ranges = []) => {
|
|
714
|
+
useEffect(() => {
|
|
715
|
+
view?.dispatch({
|
|
716
|
+
effects: setHighlights.of(ranges)
|
|
717
|
+
});
|
|
718
|
+
}, [
|
|
719
|
+
view,
|
|
720
|
+
ranges
|
|
721
|
+
]);
|
|
722
|
+
};
|
|
723
|
+
var highlightStateField = StateField.define({
|
|
724
|
+
create: () => [],
|
|
725
|
+
update: (threads, tr) => {
|
|
726
|
+
for (const effect of tr.effects) {
|
|
727
|
+
if (effect.is(setHighlights)) {
|
|
728
|
+
return effect.value;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return threads;
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
var highlightDecorations = EditorView5.decorations.compute([
|
|
735
|
+
highlightStateField
|
|
736
|
+
], (state) => {
|
|
737
|
+
const selectionRanges = state.field(highlightStateField);
|
|
738
|
+
const decorations = sortBy(selectionRanges ?? [], (selection) => selection.from)?.flatMap((selection) => {
|
|
739
|
+
const range = {
|
|
740
|
+
from: selection.from,
|
|
741
|
+
to: selection.to + 1
|
|
742
|
+
};
|
|
743
|
+
if (selection.to > selection.from) {
|
|
744
|
+
if (selection.active) {
|
|
745
|
+
return marks.HighlightActive.range(range.from, range.to);
|
|
746
|
+
} else {
|
|
747
|
+
return marks.highlight.range(range.from, range.to);
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
return [];
|
|
751
|
+
}
|
|
752
|
+
}) ?? [];
|
|
753
|
+
return Decoration3.set(decorations);
|
|
754
|
+
});
|
|
755
|
+
var listener = (options) => {
|
|
756
|
+
return EditorView5.updateListener.of((update4) => {
|
|
757
|
+
const { view, state } = update4;
|
|
758
|
+
const { head } = state.selection.main;
|
|
759
|
+
const ranges = state.field(highlightStateField);
|
|
760
|
+
let mod = false;
|
|
761
|
+
const newRanges = ranges.map((range) => {
|
|
762
|
+
const active = head >= range.from && head <= range.to;
|
|
763
|
+
if (active !== range.active) {
|
|
764
|
+
mod = true;
|
|
765
|
+
return {
|
|
766
|
+
...range,
|
|
767
|
+
active
|
|
768
|
+
};
|
|
769
|
+
} else {
|
|
770
|
+
return range;
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
if (mod) {
|
|
774
|
+
view.dispatch({
|
|
775
|
+
effects: setHighlights.of(newRanges)
|
|
776
|
+
});
|
|
777
|
+
options?.onChange?.(newRanges.find((range) => range.active)?.id);
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
};
|
|
781
|
+
var highlight = (options = {}) => {
|
|
782
|
+
return [
|
|
783
|
+
highlightStateField,
|
|
784
|
+
highlightDecorations,
|
|
785
|
+
listener(options),
|
|
786
|
+
styles3
|
|
787
|
+
];
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/image.ts
|
|
177
791
|
import { syntaxTree } from "@codemirror/language";
|
|
178
|
-
import { RangeSetBuilder, StateField } from "@codemirror/state";
|
|
179
|
-
import { Decoration as
|
|
180
|
-
var
|
|
792
|
+
import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
|
|
793
|
+
import { Decoration as Decoration4, EditorView as EditorView6, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
794
|
+
var image = (options = {}) => {
|
|
795
|
+
return StateField2.define({
|
|
796
|
+
create: (state) => update(state, options),
|
|
797
|
+
update: (_, tr) => update(tr.state, options),
|
|
798
|
+
provide: (field) => EditorView6.decorations.from(field)
|
|
799
|
+
});
|
|
800
|
+
};
|
|
801
|
+
var update = (state, options) => {
|
|
802
|
+
const builder = new RangeSetBuilder();
|
|
803
|
+
const cursor = state.selection.main.head;
|
|
804
|
+
syntaxTree(state).iterate({
|
|
805
|
+
enter: (node) => {
|
|
806
|
+
if (node.name === "Image") {
|
|
807
|
+
const urlNode = node.node.getChild("URL");
|
|
808
|
+
if (urlNode) {
|
|
809
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
810
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
811
|
+
builder.add(hide ? node.from : node.to, node.to, Decoration4.replace({
|
|
812
|
+
widget: new ImageWidget(url)
|
|
813
|
+
}));
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
return builder.finish();
|
|
819
|
+
};
|
|
820
|
+
var ImageWidget = class extends WidgetType2 {
|
|
821
|
+
constructor(_url) {
|
|
822
|
+
super();
|
|
823
|
+
this._url = _url;
|
|
824
|
+
}
|
|
825
|
+
eq(other) {
|
|
826
|
+
return this._url === other?._url;
|
|
827
|
+
}
|
|
828
|
+
toDOM(view) {
|
|
829
|
+
const img = document.createElement("img");
|
|
830
|
+
img.setAttribute("src", this._url);
|
|
831
|
+
img.setAttribute("class", "cm-image");
|
|
832
|
+
return img;
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
|
|
837
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
838
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
|
|
839
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
840
|
+
var link = (options = {}) => {
|
|
841
|
+
return StateField3.define({
|
|
842
|
+
create: (state) => update2(state, options),
|
|
843
|
+
update: (_, tr) => update2(tr.state, options),
|
|
844
|
+
provide: (field) => EditorView7.decorations.from(field)
|
|
845
|
+
});
|
|
846
|
+
};
|
|
847
|
+
var LinkButton = class extends WidgetType3 {
|
|
181
848
|
constructor(_pos, _url, _onAttach) {
|
|
182
849
|
super();
|
|
183
850
|
this._pos = _pos;
|
|
@@ -193,7 +860,7 @@ var LinkButton = class extends WidgetType2 {
|
|
|
193
860
|
return el;
|
|
194
861
|
}
|
|
195
862
|
};
|
|
196
|
-
var LinkText = class extends
|
|
863
|
+
var LinkText = class extends WidgetType3 {
|
|
197
864
|
constructor(_pos, _text, _url) {
|
|
198
865
|
super();
|
|
199
866
|
this._pos = _pos;
|
|
@@ -223,26 +890,26 @@ var LinkText = class extends WidgetType2 {
|
|
|
223
890
|
return link2;
|
|
224
891
|
}
|
|
225
892
|
};
|
|
226
|
-
var
|
|
227
|
-
const builder = new
|
|
893
|
+
var update2 = (state, options) => {
|
|
894
|
+
const builder = new RangeSetBuilder2();
|
|
228
895
|
const cursor = state.selection.main.head;
|
|
229
|
-
|
|
896
|
+
syntaxTree2(state).iterate({
|
|
230
897
|
enter: (node) => {
|
|
231
898
|
if (node.name === "Link") {
|
|
232
|
-
const
|
|
233
|
-
const text =
|
|
899
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
900
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
234
901
|
const urlNode = node.node.getChild("URL");
|
|
235
902
|
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
236
903
|
if (!url) {
|
|
237
904
|
return false;
|
|
238
905
|
}
|
|
239
|
-
if (cursor < node.from || cursor > node.to) {
|
|
240
|
-
builder.add(node.from, node.to,
|
|
906
|
+
if (state.readOnly || cursor < node.from || cursor > node.to) {
|
|
907
|
+
builder.add(node.from, node.to, Decoration5.replace({
|
|
241
908
|
widget: new LinkText(node.from, text, options.link ? url : void 0)
|
|
242
909
|
}));
|
|
243
910
|
}
|
|
244
911
|
if (options.onRender) {
|
|
245
|
-
builder.add(node.to, node.to,
|
|
912
|
+
builder.add(node.to, node.to, Decoration5.replace({
|
|
246
913
|
widget: new LinkButton(node.from, url, options.onRender)
|
|
247
914
|
}));
|
|
248
915
|
}
|
|
@@ -252,69 +919,39 @@ var update = (state, options) => {
|
|
|
252
919
|
});
|
|
253
920
|
return builder.finish();
|
|
254
921
|
};
|
|
255
|
-
var link = (options = {}) => {
|
|
256
|
-
return StateField.define({
|
|
257
|
-
create: (state) => update(state, options),
|
|
258
|
-
update: (_, tr) => update(tr.state, options),
|
|
259
|
-
provide: (field) => EditorView3.decorations.from(field)
|
|
260
|
-
});
|
|
261
|
-
};
|
|
262
922
|
|
|
263
923
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
|
|
264
|
-
import { StateField as
|
|
265
|
-
var
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
924
|
+
import { StateField as StateField4 } from "@codemirror/state";
|
|
925
|
+
var listener2 = ({ onChange }) => {
|
|
926
|
+
return StateField4.define({
|
|
927
|
+
create: () => null,
|
|
928
|
+
update: (_value, transaction) => {
|
|
929
|
+
if (transaction.docChanged && onChange) {
|
|
930
|
+
onChange(transaction.newDoc.toString());
|
|
931
|
+
}
|
|
932
|
+
return null;
|
|
270
933
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
});
|
|
934
|
+
});
|
|
935
|
+
};
|
|
274
936
|
|
|
275
937
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
276
938
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
277
|
-
import {
|
|
939
|
+
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
278
940
|
import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
|
|
279
941
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
280
942
|
import { languages } from "@codemirror/language-data";
|
|
281
|
-
import {
|
|
943
|
+
import { searchKeymap } from "@codemirror/search";
|
|
282
944
|
import { EditorState } from "@codemirror/state";
|
|
283
945
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
284
|
-
import { crosshairCursor, drawSelection, dropCursor, EditorView as
|
|
946
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView8, highlightActiveLine, keymap as keymap5, placeholder as placeholder2 } from "@codemirror/view";
|
|
285
947
|
|
|
286
948
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
|
|
287
949
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
288
950
|
import { HighlightStyle } from "@codemirror/language";
|
|
289
951
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
290
|
-
import
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
import { mx } from "@dxos/react-ui-theme";
|
|
294
|
-
var heading = {
|
|
295
|
-
1: "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
296
|
-
2: "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
297
|
-
3: "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
298
|
-
4: "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
299
|
-
5: "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
300
|
-
6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
|
|
301
|
-
};
|
|
302
|
-
var light = "text-neutral-200 dark:text-neutral-800";
|
|
303
|
-
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
304
|
-
var bold = "font-bold";
|
|
305
|
-
var italic = "italic";
|
|
306
|
-
var strikethrough = "line-through";
|
|
307
|
-
var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
308
|
-
var codeMark = "font-mono text-primary-500";
|
|
309
|
-
var inlineUrl = mx(code, "px-1");
|
|
310
|
-
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
311
|
-
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-500/50";
|
|
312
|
-
|
|
313
|
-
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
314
|
-
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
315
|
-
var tokens = tailwindConfig({}).theme;
|
|
316
|
-
|
|
317
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
|
|
952
|
+
import { Table } from "@lezer/markdown";
|
|
953
|
+
import get2 from "lodash.get";
|
|
954
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
318
955
|
var markdownTags = {
|
|
319
956
|
Blockquote: Tag.define(),
|
|
320
957
|
CodeMark: Tag.define(),
|
|
@@ -327,179 +964,202 @@ var markdownTags = {
|
|
|
327
964
|
LinkReference: Tag.define(),
|
|
328
965
|
ListMark: Tag.define(),
|
|
329
966
|
QuoteMark: Tag.define(),
|
|
330
|
-
URL: Tag.define()
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
props: [
|
|
334
|
-
styleTags(markdownTags)
|
|
335
|
-
]
|
|
967
|
+
URL: Tag.define(),
|
|
968
|
+
// Custom.
|
|
969
|
+
TableCell: Tag.define()
|
|
336
970
|
};
|
|
337
|
-
|
|
338
|
-
{
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
tags.character,
|
|
344
|
-
tags.propertyName,
|
|
345
|
-
tags.macroName,
|
|
346
|
-
tags.color,
|
|
347
|
-
tags.constant(tags.name),
|
|
348
|
-
tags.standard(tags.name),
|
|
349
|
-
tags.definition(tags.name),
|
|
350
|
-
tags.separator,
|
|
351
|
-
tags.typeName,
|
|
352
|
-
tags.className,
|
|
353
|
-
tags.number,
|
|
354
|
-
tags.changed,
|
|
355
|
-
tags.annotation,
|
|
356
|
-
tags.modifier,
|
|
357
|
-
tags.self,
|
|
358
|
-
tags.namespace,
|
|
359
|
-
tags.operator,
|
|
360
|
-
tags.operatorKeyword,
|
|
361
|
-
tags.escape,
|
|
362
|
-
tags.regexp,
|
|
363
|
-
tags.special(tags.string),
|
|
364
|
-
tags.meta,
|
|
365
|
-
tags.comment,
|
|
366
|
-
tags.atom,
|
|
367
|
-
tags.bool,
|
|
368
|
-
tags.special(tags.variableName),
|
|
369
|
-
tags.processingInstruction,
|
|
370
|
-
tags.string,
|
|
371
|
-
tags.inserted,
|
|
372
|
-
tags.invalid
|
|
373
|
-
],
|
|
374
|
-
color: "inherit !important"
|
|
375
|
-
},
|
|
376
|
-
// Markdown marks.
|
|
377
|
-
{
|
|
378
|
-
tag: [
|
|
379
|
-
tags.meta,
|
|
380
|
-
tags.processingInstruction,
|
|
381
|
-
markdownTags.CodeMark,
|
|
382
|
-
markdownTags.EmphasisMark,
|
|
383
|
-
markdownTags.HeaderMark,
|
|
384
|
-
markdownTags.LinkLabel,
|
|
385
|
-
markdownTags.LinkReference,
|
|
386
|
-
markdownTags.ListMark,
|
|
387
|
-
markdownTags.QuoteMark
|
|
388
|
-
],
|
|
389
|
-
class: mark
|
|
390
|
-
},
|
|
391
|
-
// Headings.
|
|
392
|
-
{
|
|
393
|
-
tag: tags.heading1,
|
|
394
|
-
class: heading[1]
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
tag: tags.heading2,
|
|
398
|
-
class: heading[2]
|
|
399
|
-
},
|
|
400
|
-
{
|
|
401
|
-
tag: tags.heading3,
|
|
402
|
-
class: heading[3]
|
|
403
|
-
},
|
|
404
|
-
{
|
|
405
|
-
tag: tags.heading4,
|
|
406
|
-
class: heading[4]
|
|
407
|
-
},
|
|
408
|
-
{
|
|
409
|
-
tag: tags.heading5,
|
|
410
|
-
class: heading[5]
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
tag: tags.heading6,
|
|
414
|
-
class: heading[6]
|
|
415
|
-
},
|
|
416
|
-
// Emphasis.
|
|
417
|
-
{
|
|
418
|
-
tag: tags.emphasis,
|
|
419
|
-
class: italic
|
|
420
|
-
},
|
|
421
|
-
{
|
|
422
|
-
tag: tags.strong,
|
|
423
|
-
class: bold
|
|
424
|
-
},
|
|
425
|
-
{
|
|
426
|
-
tag: tags.strikethrough,
|
|
427
|
-
class: strikethrough
|
|
428
|
-
},
|
|
429
|
-
// Naked URLs.
|
|
430
|
-
{
|
|
431
|
-
tag: [
|
|
432
|
-
markdownTags.URL
|
|
433
|
-
],
|
|
434
|
-
class: inlineUrl
|
|
435
|
-
},
|
|
436
|
-
// E.g., code block language (after ```).
|
|
437
|
-
{
|
|
438
|
-
tag: [
|
|
439
|
-
tags.function(tags.variableName),
|
|
440
|
-
tags.labelName
|
|
441
|
-
],
|
|
442
|
-
class: codeMark
|
|
443
|
-
},
|
|
444
|
-
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
445
|
-
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
446
|
-
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
447
|
-
// the code, but all other CSS properties will be inherited.
|
|
448
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
449
|
-
{
|
|
450
|
-
tag: [
|
|
451
|
-
markdownTags.CodeText,
|
|
452
|
-
markdownTags.InlineCode
|
|
453
|
-
],
|
|
454
|
-
class: code
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
tag: [
|
|
458
|
-
markdownTags.QuoteMark
|
|
459
|
-
],
|
|
460
|
-
class: blockquote
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
tag: [
|
|
464
|
-
markdownTags.HorizontalRule
|
|
465
|
-
],
|
|
466
|
-
class: horizontalRule
|
|
467
|
-
}
|
|
468
|
-
], {
|
|
469
|
-
scope: markdownLanguage,
|
|
470
|
-
all: {
|
|
471
|
-
fontFamily: get(tokens, "fontFamily.body", []).join(",")
|
|
971
|
+
Table.defineNodes?.forEach((node) => {
|
|
972
|
+
switch (node?.name) {
|
|
973
|
+
case "TableCell": {
|
|
974
|
+
node.style = markdownTags.TableCell;
|
|
975
|
+
break;
|
|
976
|
+
}
|
|
472
977
|
}
|
|
473
978
|
});
|
|
979
|
+
var markdownTagsExtensions = [
|
|
980
|
+
Table,
|
|
981
|
+
{
|
|
982
|
+
props: [
|
|
983
|
+
styleTags(markdownTags)
|
|
984
|
+
]
|
|
985
|
+
}
|
|
986
|
+
];
|
|
987
|
+
var markdownHighlightStyle = (readonly) => {
|
|
988
|
+
return HighlightStyle.define([
|
|
989
|
+
{
|
|
990
|
+
tag: [
|
|
991
|
+
tags.keyword,
|
|
992
|
+
tags.name,
|
|
993
|
+
tags.deleted,
|
|
994
|
+
tags.character,
|
|
995
|
+
tags.propertyName,
|
|
996
|
+
tags.macroName,
|
|
997
|
+
tags.color,
|
|
998
|
+
tags.constant(tags.name),
|
|
999
|
+
tags.standard(tags.name),
|
|
1000
|
+
tags.definition(tags.name),
|
|
1001
|
+
tags.separator,
|
|
1002
|
+
tags.typeName,
|
|
1003
|
+
tags.className,
|
|
1004
|
+
tags.number,
|
|
1005
|
+
tags.changed,
|
|
1006
|
+
tags.annotation,
|
|
1007
|
+
tags.modifier,
|
|
1008
|
+
tags.self,
|
|
1009
|
+
tags.namespace,
|
|
1010
|
+
tags.operator,
|
|
1011
|
+
tags.operatorKeyword,
|
|
1012
|
+
tags.escape,
|
|
1013
|
+
tags.regexp,
|
|
1014
|
+
tags.special(tags.string),
|
|
1015
|
+
tags.meta,
|
|
1016
|
+
tags.comment,
|
|
1017
|
+
tags.atom,
|
|
1018
|
+
tags.bool,
|
|
1019
|
+
tags.special(tags.variableName),
|
|
1020
|
+
tags.processingInstruction,
|
|
1021
|
+
tags.string,
|
|
1022
|
+
tags.inserted,
|
|
1023
|
+
tags.invalid
|
|
1024
|
+
],
|
|
1025
|
+
color: "inherit !important"
|
|
1026
|
+
},
|
|
1027
|
+
// Markdown marks.
|
|
1028
|
+
{
|
|
1029
|
+
tag: [
|
|
1030
|
+
tags.meta,
|
|
1031
|
+
tags.processingInstruction,
|
|
1032
|
+
markdownTags.LinkLabel,
|
|
1033
|
+
markdownTags.LinkReference,
|
|
1034
|
+
markdownTags.ListMark
|
|
1035
|
+
],
|
|
1036
|
+
class: mark
|
|
1037
|
+
},
|
|
1038
|
+
// Markdown marks.
|
|
1039
|
+
{
|
|
1040
|
+
tag: [
|
|
1041
|
+
markdownTags.CodeMark,
|
|
1042
|
+
markdownTags.HeaderMark,
|
|
1043
|
+
markdownTags.QuoteMark,
|
|
1044
|
+
markdownTags.EmphasisMark
|
|
1045
|
+
],
|
|
1046
|
+
class: readonly ? "hidden" : mark
|
|
1047
|
+
},
|
|
1048
|
+
// E.g., code block language (after ```).
|
|
1049
|
+
{
|
|
1050
|
+
tag: [
|
|
1051
|
+
tags.function(tags.variableName),
|
|
1052
|
+
tags.labelName
|
|
1053
|
+
],
|
|
1054
|
+
class: readonly ? "hidden" : codeMark
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
tag: [
|
|
1058
|
+
tags.monospace
|
|
1059
|
+
],
|
|
1060
|
+
class: "font-mono"
|
|
1061
|
+
},
|
|
1062
|
+
// Headings.
|
|
1063
|
+
{
|
|
1064
|
+
tag: tags.heading1,
|
|
1065
|
+
class: heading(1, readonly)
|
|
1066
|
+
},
|
|
1067
|
+
{
|
|
1068
|
+
tag: tags.heading2,
|
|
1069
|
+
class: heading(2, readonly)
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
tag: tags.heading3,
|
|
1073
|
+
class: heading(3, readonly)
|
|
1074
|
+
},
|
|
1075
|
+
{
|
|
1076
|
+
tag: tags.heading4,
|
|
1077
|
+
class: heading(4, readonly)
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
tag: tags.heading5,
|
|
1081
|
+
class: heading(5, readonly)
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
tag: tags.heading6,
|
|
1085
|
+
class: heading(6, readonly)
|
|
1086
|
+
},
|
|
1087
|
+
// Emphasis.
|
|
1088
|
+
{
|
|
1089
|
+
tag: tags.emphasis,
|
|
1090
|
+
class: italic
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
tag: tags.strong,
|
|
1094
|
+
class: bold
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
tag: tags.strikethrough,
|
|
1098
|
+
class: strikethrough
|
|
1099
|
+
},
|
|
1100
|
+
// Naked URLs.
|
|
1101
|
+
{
|
|
1102
|
+
tag: [
|
|
1103
|
+
markdownTags.URL
|
|
1104
|
+
],
|
|
1105
|
+
class: inlineUrl
|
|
1106
|
+
},
|
|
1107
|
+
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
1108
|
+
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
1109
|
+
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
1110
|
+
// the code, but all other CSS properties will be inherited.
|
|
1111
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
1112
|
+
{
|
|
1113
|
+
tag: [
|
|
1114
|
+
markdownTags.CodeText,
|
|
1115
|
+
markdownTags.InlineCode
|
|
1116
|
+
],
|
|
1117
|
+
class: code
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
tag: [
|
|
1121
|
+
markdownTags.QuoteMark
|
|
1122
|
+
],
|
|
1123
|
+
class: blockquote
|
|
1124
|
+
},
|
|
1125
|
+
// TODO(burdon): Replace with extension.
|
|
1126
|
+
{
|
|
1127
|
+
tag: [
|
|
1128
|
+
markdownTags.HorizontalRule
|
|
1129
|
+
],
|
|
1130
|
+
class: mx3(horizontalRule, readonly && "-indent-[100rem]")
|
|
1131
|
+
},
|
|
1132
|
+
// TODO(burdon): Only if being edited.
|
|
1133
|
+
{
|
|
1134
|
+
tag: [
|
|
1135
|
+
markdownTags.TableCell
|
|
1136
|
+
],
|
|
1137
|
+
class: "font-mono"
|
|
1138
|
+
}
|
|
1139
|
+
], {
|
|
1140
|
+
scope: markdownLanguage,
|
|
1141
|
+
all: {
|
|
1142
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
};
|
|
474
1146
|
|
|
475
1147
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
476
|
-
var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
1148
|
+
var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
477
1149
|
return [
|
|
1150
|
+
EditorState.allowMultipleSelections.of(true),
|
|
1151
|
+
EditorState.tabSize.of(2),
|
|
1152
|
+
EditorView8.lineWrapping,
|
|
1153
|
+
customKeymap(),
|
|
478
1154
|
bracketMatching2(),
|
|
479
1155
|
closeBrackets2(),
|
|
480
|
-
_placeholder && placeholder2(_placeholder),
|
|
481
|
-
EditorState.allowMultipleSelections.of(true),
|
|
482
|
-
EditorView4.lineWrapping,
|
|
483
1156
|
crosshairCursor(),
|
|
484
1157
|
dropCursor(),
|
|
485
|
-
|
|
1158
|
+
drawSelection2(),
|
|
486
1159
|
highlightActiveLine(),
|
|
487
|
-
highlightActiveLineGutter(),
|
|
488
|
-
highlightSelectionMatches(),
|
|
489
|
-
highlightSpecialChars(),
|
|
490
1160
|
history(),
|
|
491
1161
|
indentOnInput(),
|
|
492
|
-
|
|
493
|
-
// TODO(burdon): Review.
|
|
494
|
-
keymap3.of([
|
|
495
|
-
...closeBracketsKeymap,
|
|
496
|
-
...defaultKeymap,
|
|
497
|
-
// ...foldKeymap,
|
|
498
|
-
// ...historyKeymap,
|
|
499
|
-
// ...lintKeymap,
|
|
500
|
-
...searchKeymap,
|
|
501
|
-
indentWithTab
|
|
502
|
-
]),
|
|
1162
|
+
_placeholder && placeholder2(_placeholder),
|
|
503
1163
|
// Main extension.
|
|
504
1164
|
// https://github.com/codemirror/lang-markdown
|
|
505
1165
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -514,20 +1174,156 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
514
1174
|
codeLanguages: languages,
|
|
515
1175
|
// Parser extensions.
|
|
516
1176
|
extensions: [
|
|
517
|
-
// GFM
|
|
518
|
-
|
|
1177
|
+
// GFM provided by default.
|
|
1178
|
+
markdownTagsExtensions
|
|
519
1179
|
]
|
|
520
1180
|
}),
|
|
1181
|
+
// https://github.com/codemirror/theme-one-dark
|
|
1182
|
+
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
521
1183
|
// Custom styles.
|
|
522
|
-
syntaxHighlighting2(markdownHighlightStyle)
|
|
523
|
-
// TODO(thure): All but one rule here apply to both themes; rename or refactor.
|
|
524
|
-
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2)
|
|
1184
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
525
1185
|
].filter(Boolean);
|
|
526
1186
|
};
|
|
1187
|
+
var customKeymap = () => keymap5.of([
|
|
1188
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1189
|
+
indentWithTab,
|
|
1190
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1191
|
+
...standardKeymap,
|
|
1192
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
1193
|
+
...historyKeymap,
|
|
1194
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1195
|
+
...closeBracketsKeymap,
|
|
1196
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
1197
|
+
...searchKeymap
|
|
1198
|
+
]);
|
|
1199
|
+
|
|
1200
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/mention.ts
|
|
1201
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1202
|
+
var mention = ({ onSearch }) => {
|
|
1203
|
+
return autocompletion2({
|
|
1204
|
+
closeOnBlur: false,
|
|
1205
|
+
override: [
|
|
1206
|
+
(context) => {
|
|
1207
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
1208
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
1209
|
+
return null;
|
|
1210
|
+
}
|
|
1211
|
+
console.log(match);
|
|
1212
|
+
return {
|
|
1213
|
+
from: match.from,
|
|
1214
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
1215
|
+
label: `@${value}`
|
|
1216
|
+
}))
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
]
|
|
1220
|
+
});
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/table.ts
|
|
1224
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1225
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField5 } from "@codemirror/state";
|
|
1226
|
+
import { Decoration as Decoration6, EditorView as EditorView9, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1227
|
+
var table = (options = {}) => {
|
|
1228
|
+
return StateField5.define({
|
|
1229
|
+
create: (state) => update3(state, options),
|
|
1230
|
+
update: (_, tr) => update3(tr.state, options),
|
|
1231
|
+
provide: (field) => EditorView9.decorations.from(field)
|
|
1232
|
+
});
|
|
1233
|
+
};
|
|
1234
|
+
var update3 = (state, options) => {
|
|
1235
|
+
const builder = new RangeSetBuilder3();
|
|
1236
|
+
const cursor = state.selection.main.head;
|
|
1237
|
+
const tables = [];
|
|
1238
|
+
const getTable = () => tables[tables.length - 1];
|
|
1239
|
+
const getRow = () => {
|
|
1240
|
+
const table2 = getTable();
|
|
1241
|
+
return table2.rows?.[table2.rows.length - 1];
|
|
1242
|
+
};
|
|
1243
|
+
syntaxTree3(state).iterate({
|
|
1244
|
+
enter: (node) => {
|
|
1245
|
+
switch (node.name) {
|
|
1246
|
+
case "Table": {
|
|
1247
|
+
tables.push({
|
|
1248
|
+
from: node.from,
|
|
1249
|
+
to: node.to
|
|
1250
|
+
});
|
|
1251
|
+
break;
|
|
1252
|
+
}
|
|
1253
|
+
case "TableHeader": {
|
|
1254
|
+
getTable().header = [];
|
|
1255
|
+
break;
|
|
1256
|
+
}
|
|
1257
|
+
case "TableRow": {
|
|
1258
|
+
(getTable().rows ??= []).push([]);
|
|
1259
|
+
break;
|
|
1260
|
+
}
|
|
1261
|
+
case "TableCell": {
|
|
1262
|
+
const row = getRow();
|
|
1263
|
+
if (row) {
|
|
1264
|
+
row.push(state.sliceDoc(node.from, node.to));
|
|
1265
|
+
} else {
|
|
1266
|
+
getTable().header?.push(state.sliceDoc(node.from, node.to));
|
|
1267
|
+
}
|
|
1268
|
+
break;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
});
|
|
1273
|
+
tables.forEach((table2) => {
|
|
1274
|
+
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
1275
|
+
hide && builder.add(table2.from, table2.to, Decoration6.replace({
|
|
1276
|
+
widget: new TableWidget(table2)
|
|
1277
|
+
}));
|
|
1278
|
+
builder.add(table2.from, table2.to, Decoration6.mark({
|
|
1279
|
+
class: "cm-table"
|
|
1280
|
+
}));
|
|
1281
|
+
});
|
|
1282
|
+
return builder.finish();
|
|
1283
|
+
};
|
|
1284
|
+
var TableWidget = class extends WidgetType4 {
|
|
1285
|
+
constructor(_table) {
|
|
1286
|
+
super();
|
|
1287
|
+
this._table = _table;
|
|
1288
|
+
}
|
|
1289
|
+
eq(other) {
|
|
1290
|
+
return this._table.from === other?._table?.from;
|
|
1291
|
+
}
|
|
1292
|
+
toDOM(view) {
|
|
1293
|
+
const table2 = document.createElement("table");
|
|
1294
|
+
{
|
|
1295
|
+
const header = table2.appendChild(document.createElement("thead"));
|
|
1296
|
+
const tr = header.appendChild(document.createElement("tr"));
|
|
1297
|
+
this._table.header?.forEach((cell) => {
|
|
1298
|
+
const th = document.createElement("th");
|
|
1299
|
+
th.setAttribute("class", "cm-table-head");
|
|
1300
|
+
tr.appendChild(th).textContent = cell;
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
{
|
|
1304
|
+
const body = table2.appendChild(document.createElement("tbody"));
|
|
1305
|
+
this._table.rows?.forEach((row) => {
|
|
1306
|
+
const tr = body.appendChild(document.createElement("tr"));
|
|
1307
|
+
row.forEach((cell) => {
|
|
1308
|
+
const td = document.createElement("td");
|
|
1309
|
+
td.setAttribute("class", "cm-table-cell");
|
|
1310
|
+
tr.appendChild(td).textContent = cell;
|
|
1311
|
+
});
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
return table2;
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
527
1317
|
|
|
528
1318
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
|
|
529
|
-
import { EditorView as
|
|
530
|
-
var
|
|
1319
|
+
import { EditorView as EditorView10, Decoration as Decoration7, WidgetType as WidgetType5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
|
|
1320
|
+
var styles4 = EditorView10.baseTheme({
|
|
1321
|
+
"& .cm-task-item": {
|
|
1322
|
+
paddingLeft: "4px",
|
|
1323
|
+
paddingRight: "8px"
|
|
1324
|
+
}
|
|
1325
|
+
});
|
|
1326
|
+
var CheckboxWidget = class extends WidgetType5 {
|
|
531
1327
|
constructor(_pos, _checked, _indent, _onCheck) {
|
|
532
1328
|
super();
|
|
533
1329
|
this._pos = _pos;
|
|
@@ -546,30 +1342,29 @@ var CheckboxWidget = class extends WidgetType3 {
|
|
|
546
1342
|
const input = wrap.appendChild(document.createElement("input"));
|
|
547
1343
|
input.type = "checkbox";
|
|
548
1344
|
input.checked = this._checked;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
1345
|
+
if (!this._onCheck) {
|
|
1346
|
+
input.setAttribute("disabled", "true");
|
|
1347
|
+
}
|
|
1348
|
+
if (this._onCheck) {
|
|
1349
|
+
input.onchange = (event) => {
|
|
1350
|
+
this._onCheck?.(event.target.checked);
|
|
1351
|
+
return true;
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
553
1354
|
return wrap;
|
|
554
1355
|
}
|
|
555
1356
|
ignoreEvent() {
|
|
556
1357
|
return false;
|
|
557
1358
|
}
|
|
558
1359
|
};
|
|
559
|
-
var
|
|
560
|
-
"& .cm-task-item": {
|
|
561
|
-
paddingLeft: "4px",
|
|
562
|
-
paddingRight: "8px"
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
|
-
var tasklist = () => {
|
|
1360
|
+
var tasklist = (options = {}) => {
|
|
566
1361
|
const taskMatcher = new MatchDecorator2({
|
|
567
1362
|
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
568
1363
|
decoration: (match, view, pos) => {
|
|
569
1364
|
const indent = Math.floor(match[1].length / 2);
|
|
570
1365
|
const checked = match[2] === "x" || match[2] === "X";
|
|
571
|
-
return
|
|
572
|
-
widget: new CheckboxWidget(pos, checked, indent, (checked2) => {
|
|
1366
|
+
return Decoration7.replace({
|
|
1367
|
+
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
573
1368
|
const idx = pos + match[0].indexOf("[") + 1;
|
|
574
1369
|
view.dispatch({
|
|
575
1370
|
changes: {
|
|
@@ -586,22 +1381,22 @@ var tasklist = () => {
|
|
|
586
1381
|
});
|
|
587
1382
|
}
|
|
588
1383
|
});
|
|
589
|
-
const tasks =
|
|
1384
|
+
const tasks = ViewPlugin3.fromClass(class {
|
|
590
1385
|
constructor(view) {
|
|
591
1386
|
this.tasks = taskMatcher.createDeco(view);
|
|
592
1387
|
}
|
|
593
|
-
update(
|
|
594
|
-
this.tasks = taskMatcher.updateDeco(
|
|
1388
|
+
update(update4) {
|
|
1389
|
+
this.tasks = taskMatcher.updateDeco(update4, this.tasks);
|
|
595
1390
|
}
|
|
596
1391
|
}, {
|
|
597
|
-
decorations: (
|
|
598
|
-
provide: (plugin) =>
|
|
599
|
-
return view.plugin(plugin)?.tasks ||
|
|
1392
|
+
decorations: (value) => value.tasks,
|
|
1393
|
+
provide: (plugin) => EditorView10.atomicRanges.of((view) => {
|
|
1394
|
+
return view.plugin(plugin)?.tasks || Decoration7.none;
|
|
600
1395
|
})
|
|
601
1396
|
});
|
|
602
1397
|
return [
|
|
603
1398
|
tasks,
|
|
604
|
-
|
|
1399
|
+
styles4
|
|
605
1400
|
];
|
|
606
1401
|
};
|
|
607
1402
|
|
|
@@ -650,7 +1445,7 @@ var tooltip = ({ onHover, regexp = markdownLinkRegexp }) => hoverTooltip((view,
|
|
|
650
1445
|
});
|
|
651
1446
|
|
|
652
1447
|
// packages/ui/react-ui-editor/src/components/TextEditor/themes/default.ts
|
|
653
|
-
import
|
|
1448
|
+
import get3 from "lodash.get";
|
|
654
1449
|
var defaultTheme = {
|
|
655
1450
|
//
|
|
656
1451
|
// Main layout:
|
|
@@ -667,7 +1462,8 @@ var defaultTheme = {
|
|
|
667
1462
|
outline: "none"
|
|
668
1463
|
},
|
|
669
1464
|
"& .cm-scroller": {
|
|
670
|
-
overflow: "visible"
|
|
1465
|
+
overflow: "visible",
|
|
1466
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
671
1467
|
},
|
|
672
1468
|
"& .cm-content": {
|
|
673
1469
|
padding: 0,
|
|
@@ -675,20 +1471,20 @@ var defaultTheme = {
|
|
|
675
1471
|
fontSize: "16px"
|
|
676
1472
|
},
|
|
677
1473
|
"&light .cm-content": {
|
|
678
|
-
color:
|
|
1474
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
679
1475
|
caretColor: "black"
|
|
680
1476
|
},
|
|
681
1477
|
"&dark .cm-content": {
|
|
682
|
-
color:
|
|
1478
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
683
1479
|
caretColor: "white"
|
|
684
1480
|
},
|
|
685
1481
|
//
|
|
686
1482
|
// Cursor
|
|
687
1483
|
//
|
|
688
|
-
"&light .cm-cursor": {
|
|
1484
|
+
"&light .cm-cursor, &light .cm-dropCursor": {
|
|
689
1485
|
borderLeft: "2px solid black"
|
|
690
1486
|
},
|
|
691
|
-
"&dark .cm-cursor": {
|
|
1487
|
+
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
692
1488
|
borderLeft: "2px solid white"
|
|
693
1489
|
},
|
|
694
1490
|
"& .cm-placeholder": {
|
|
@@ -708,16 +1504,16 @@ var defaultTheme = {
|
|
|
708
1504
|
// selection
|
|
709
1505
|
//
|
|
710
1506
|
"&light .cm-selectionBackground, &light.cm-focused .cm-selectionBackground": {
|
|
711
|
-
background:
|
|
1507
|
+
background: get3(tokens, "extend.colors.primary.150", "#00ffff")
|
|
712
1508
|
},
|
|
713
1509
|
"&dark .cm-selectionBackground, &dark.cm-focused .cm-selectionBackground": {
|
|
714
|
-
background:
|
|
1510
|
+
background: get3(tokens, "extend.colors.primary.850", "#00ffff")
|
|
715
1511
|
},
|
|
716
1512
|
"&light .cm-selectionMatch": {
|
|
717
|
-
background:
|
|
1513
|
+
background: get3(tokens, "extend.colors.primary.250", "#00ffff") + "44"
|
|
718
1514
|
},
|
|
719
1515
|
"&dark .cm-selectionMatch": {
|
|
720
|
-
background:
|
|
1516
|
+
background: get3(tokens, "extend.colors.primary.600", "#00ffff") + "44"
|
|
721
1517
|
},
|
|
722
1518
|
//
|
|
723
1519
|
// collaboration
|
|
@@ -750,12 +1546,12 @@ var defaultTheme = {
|
|
|
750
1546
|
// link
|
|
751
1547
|
//
|
|
752
1548
|
"& .cm-link": {
|
|
753
|
-
color:
|
|
1549
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
754
1550
|
textDecorationLine: "underline",
|
|
755
1551
|
textDecorationThickness: "1px",
|
|
756
1552
|
textUnderlineOffset: "2px",
|
|
757
1553
|
borderRadius: ".125rem",
|
|
758
|
-
fontFamily:
|
|
1554
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
759
1555
|
},
|
|
760
1556
|
//
|
|
761
1557
|
// tooltip
|
|
@@ -763,14 +1559,61 @@ var defaultTheme = {
|
|
|
763
1559
|
"& .cm-tooltip": {
|
|
764
1560
|
border: "none"
|
|
765
1561
|
},
|
|
766
|
-
|
|
767
|
-
//
|
|
1562
|
+
"& .cm-tooltip-below": {},
|
|
1563
|
+
//
|
|
1564
|
+
// autocomplete
|
|
1565
|
+
//
|
|
1566
|
+
"& .cm-tooltip-autocomplete": {
|
|
1567
|
+
marginTop: "4px",
|
|
1568
|
+
marginLeft: "-3px"
|
|
1569
|
+
},
|
|
1570
|
+
"& .cm-tooltip-autocomplete ul li": {},
|
|
1571
|
+
"& .cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
1572
|
+
"& .cm-completionIcon": {
|
|
1573
|
+
display: "none"
|
|
1574
|
+
},
|
|
1575
|
+
"& .cm-completionLabel": {
|
|
1576
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
1577
|
+
},
|
|
1578
|
+
"& .cm-completionMatchedText": {
|
|
1579
|
+
textDecoration: "none"
|
|
1580
|
+
},
|
|
1581
|
+
//
|
|
1582
|
+
// widgets
|
|
1583
|
+
//
|
|
1584
|
+
"& .cm-widgetBuffer": {
|
|
1585
|
+
display: "none",
|
|
1586
|
+
height: 0
|
|
1587
|
+
},
|
|
1588
|
+
//
|
|
1589
|
+
// table
|
|
1590
|
+
//
|
|
1591
|
+
"& .cm-table *": {
|
|
1592
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
1593
|
+
textDecoration: "none !important"
|
|
1594
|
+
},
|
|
1595
|
+
"& .cm-table-head": {
|
|
1596
|
+
padding: "2px 16px 2px 0px",
|
|
1597
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
1598
|
+
fontWeight: 100,
|
|
1599
|
+
textAlign: "left",
|
|
1600
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
1601
|
+
},
|
|
1602
|
+
"& .cm-table-cell": {
|
|
1603
|
+
padding: "2px 16px 2px 0px"
|
|
1604
|
+
},
|
|
1605
|
+
//
|
|
1606
|
+
// image
|
|
1607
|
+
//
|
|
1608
|
+
"& .cm-image": {
|
|
1609
|
+
margin: "0.5rem 0"
|
|
1610
|
+
},
|
|
768
1611
|
//
|
|
769
1612
|
// font size
|
|
770
1613
|
// TODO(thure): This appears to be the best or only way to set selection caret heights, but it's far more verbose than it needs to be.
|
|
771
1614
|
//
|
|
772
|
-
...Object.keys(
|
|
773
|
-
const height =
|
|
1615
|
+
...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
|
|
1616
|
+
const height = get3(tokens, [
|
|
774
1617
|
"extend",
|
|
775
1618
|
"fontSize",
|
|
776
1619
|
fontSize,
|
|
@@ -787,46 +1630,81 @@ var defaultTheme = {
|
|
|
787
1630
|
height
|
|
788
1631
|
};
|
|
789
1632
|
return acc;
|
|
790
|
-
}, {})
|
|
1633
|
+
}, {}),
|
|
1634
|
+
/**
|
|
1635
|
+
* Panels
|
|
1636
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
1637
|
+
*
|
|
1638
|
+
* Find/replace panel.
|
|
1639
|
+
* <div class="cm-announced">...</div>
|
|
1640
|
+
* <div class="cm-scroller">...</div>
|
|
1641
|
+
* <div class="cm-panels cm-panels-bottom">
|
|
1642
|
+
* <div class="cm-search cm-panel">
|
|
1643
|
+
* <input class="cm-textfield" />
|
|
1644
|
+
* <button class="cm-button">...</button>
|
|
1645
|
+
* <label><input type="checkbox" />...</label>
|
|
1646
|
+
* </div>
|
|
1647
|
+
* </div
|
|
1648
|
+
*/
|
|
1649
|
+
"& .cm-panels": {
|
|
1650
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`,
|
|
1651
|
+
borderBottom: "none"
|
|
1652
|
+
},
|
|
1653
|
+
"& .cm-panel": {
|
|
1654
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
1655
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
1656
|
+
},
|
|
1657
|
+
"& .cm-button": {
|
|
1658
|
+
margin: "4px",
|
|
1659
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
1660
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
1661
|
+
border: "none"
|
|
1662
|
+
},
|
|
1663
|
+
"& .cm-searchMatch": {
|
|
1664
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
1665
|
+
},
|
|
1666
|
+
"& .cm-searchMatch.cm-searchMatch-selected": {
|
|
1667
|
+
backgroundColor: get3(tokens, "extend.colors.primary.100")
|
|
1668
|
+
}
|
|
791
1669
|
};
|
|
792
1670
|
var textTheme = {
|
|
793
1671
|
"& .cm-scroller": {
|
|
794
|
-
fontFamily:
|
|
1672
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
795
1673
|
},
|
|
796
1674
|
"& .cm-placeholder": {
|
|
797
|
-
fontFamily:
|
|
1675
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
798
1676
|
}
|
|
799
1677
|
};
|
|
800
1678
|
var markdownTheme = {
|
|
801
1679
|
// NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
|
|
802
1680
|
"& .cm-placeholder": {
|
|
803
|
-
fontFamily:
|
|
1681
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
804
1682
|
}
|
|
805
1683
|
};
|
|
806
1684
|
var codeTheme = {
|
|
807
1685
|
"& .cm-scroller": {
|
|
808
|
-
fontFamily:
|
|
1686
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
809
1687
|
},
|
|
810
1688
|
"& .cm-placeholder": {
|
|
811
|
-
fontFamily:
|
|
1689
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
812
1690
|
}
|
|
813
1691
|
};
|
|
814
1692
|
|
|
815
1693
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
816
1694
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
817
|
-
import { EditorView as
|
|
1695
|
+
import { EditorView as EditorView11 } from "@codemirror/view";
|
|
818
1696
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
819
1697
|
import { vim } from "@replit/codemirror-vim";
|
|
820
|
-
import
|
|
821
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
1698
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
1699
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState } from "react";
|
|
822
1700
|
import { generateName } from "@dxos/display-name";
|
|
823
1701
|
import { useThemeContext } from "@dxos/react-ui";
|
|
824
|
-
import { getColorForValue, inputSurface, mx as
|
|
1702
|
+
import { getColorForValue, inputSurface, mx as mx4 } from "@dxos/react-ui-theme";
|
|
825
1703
|
var EditorModes = [
|
|
826
1704
|
"default",
|
|
827
1705
|
"vim"
|
|
828
1706
|
];
|
|
829
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots = defaultSlots
|
|
1707
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode, extensions = [], slots = defaultSlots }, forwardedRef) => {
|
|
830
1708
|
const { themeMode } = useThemeContext();
|
|
831
1709
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
832
1710
|
tabBehavior: "limited"
|
|
@@ -844,7 +1722,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
844
1722
|
root
|
|
845
1723
|
]);
|
|
846
1724
|
const { awareness, peer } = model;
|
|
847
|
-
|
|
1725
|
+
useEffect2(() => {
|
|
848
1726
|
if (awareness && peer) {
|
|
849
1727
|
awareness.setLocalStateField("user", {
|
|
850
1728
|
name: peer.name ?? generateName(peer.id),
|
|
@@ -864,20 +1742,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
864
1742
|
peer,
|
|
865
1743
|
themeMode
|
|
866
1744
|
]);
|
|
867
|
-
|
|
1745
|
+
useEffect2(() => {
|
|
868
1746
|
if (!root) {
|
|
869
1747
|
return;
|
|
870
1748
|
}
|
|
871
1749
|
const state2 = EditorState2.create({
|
|
872
1750
|
doc: model.text(),
|
|
873
1751
|
extensions: [
|
|
1752
|
+
readonly && EditorState2.readOnly.of(readonly),
|
|
874
1753
|
// TODO(burdon): Factor out VIM mode?
|
|
875
1754
|
editorMode === "vim" && vim(),
|
|
876
1755
|
// Theme.
|
|
877
|
-
|
|
878
|
-
|
|
1756
|
+
// TODO(burdon): Make optional.
|
|
1757
|
+
EditorView11.baseTheme(defaultTheme),
|
|
1758
|
+
EditorView11.theme(slots?.editor?.theme ?? {}),
|
|
879
1759
|
// TODO(burdon): themeMode doesn't change in storybooks.
|
|
880
|
-
|
|
1760
|
+
EditorView11.darkTheme.of(themeMode === "dark"),
|
|
881
1761
|
// Storage and replication.
|
|
882
1762
|
model.extension,
|
|
883
1763
|
// Custom.
|
|
@@ -885,7 +1765,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
885
1765
|
].filter(Boolean)
|
|
886
1766
|
});
|
|
887
1767
|
view?.destroy();
|
|
888
|
-
setView(new
|
|
1768
|
+
setView(new EditorView11({
|
|
889
1769
|
state: state2,
|
|
890
1770
|
parent: root
|
|
891
1771
|
}));
|
|
@@ -899,6 +1779,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
899
1779
|
root,
|
|
900
1780
|
model,
|
|
901
1781
|
themeMode,
|
|
1782
|
+
readonly,
|
|
902
1783
|
editorMode
|
|
903
1784
|
]);
|
|
904
1785
|
const handleKeyUp = useCallback((event) => {
|
|
@@ -926,13 +1807,15 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
926
1807
|
onKeyUp: handleKeyUp
|
|
927
1808
|
});
|
|
928
1809
|
});
|
|
929
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1810
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
930
1811
|
const { themeMode } = useThemeContext();
|
|
931
|
-
const slots =
|
|
1812
|
+
const slots = defaultsDeep2({}, _slots, defaultTextSlots);
|
|
932
1813
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
933
1814
|
ref: forwardedRef,
|
|
1815
|
+
readonly,
|
|
934
1816
|
extensions: [
|
|
935
1817
|
basicBundle({
|
|
1818
|
+
readonly,
|
|
936
1819
|
themeMode,
|
|
937
1820
|
placeholder: slots?.editor?.placeholder
|
|
938
1821
|
}),
|
|
@@ -942,13 +1825,15 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, .
|
|
|
942
1825
|
...props
|
|
943
1826
|
});
|
|
944
1827
|
});
|
|
945
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1828
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
946
1829
|
const { themeMode } = useThemeContext();
|
|
947
|
-
const slots =
|
|
1830
|
+
const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
|
|
948
1831
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
949
1832
|
ref: forwardedRef,
|
|
1833
|
+
readonly,
|
|
950
1834
|
extensions: [
|
|
951
1835
|
markdownBundle({
|
|
1836
|
+
readonly,
|
|
952
1837
|
themeMode,
|
|
953
1838
|
placeholder: slots?.editor?.placeholder
|
|
954
1839
|
}),
|
|
@@ -960,7 +1845,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slot
|
|
|
960
1845
|
});
|
|
961
1846
|
var defaultSlots = {
|
|
962
1847
|
root: {
|
|
963
|
-
className:
|
|
1848
|
+
className: mx4("p-2", inputSurface)
|
|
964
1849
|
}
|
|
965
1850
|
};
|
|
966
1851
|
var defaultTextSlots = {
|
|
@@ -977,23 +1862,23 @@ var defaultMarkdownSlots = {
|
|
|
977
1862
|
};
|
|
978
1863
|
|
|
979
1864
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
980
|
-
import
|
|
981
|
-
import { useEffect as
|
|
1865
|
+
import get4 from "lodash.get";
|
|
1866
|
+
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
982
1867
|
import { yCollab } from "y-codemirror.next";
|
|
983
|
-
import { invariant as
|
|
1868
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
984
1869
|
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
985
1870
|
|
|
986
1871
|
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
987
|
-
import { Annotation, Facet, StateEffect, StateField as
|
|
988
|
-
import { ViewPlugin as
|
|
1872
|
+
import { Annotation, Facet, StateEffect as StateEffect2, StateField as StateField6 } from "@codemirror/state";
|
|
1873
|
+
import { ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
989
1874
|
import * as automerge2 from "@dxos/automerge/automerge";
|
|
990
1875
|
|
|
991
1876
|
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
992
1877
|
import { next as automerge } from "@dxos/automerge/automerge";
|
|
993
1878
|
|
|
994
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/
|
|
1879
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
|
|
995
1880
|
import { ChangeSet } from "@codemirror/state";
|
|
996
|
-
var
|
|
1881
|
+
var automergeToCodemirror = (view, selection, target, patches) => {
|
|
997
1882
|
for (const patch of patches) {
|
|
998
1883
|
const changeSpec = handlePatch(patch, target, view.state);
|
|
999
1884
|
if (changeSpec != null) {
|
|
@@ -1098,9 +1983,9 @@ var charPath = (textPath, candidatePath) => {
|
|
|
1098
1983
|
return null;
|
|
1099
1984
|
};
|
|
1100
1985
|
|
|
1101
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/
|
|
1986
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
|
|
1102
1987
|
import { next as am } from "@dxos/automerge/automerge";
|
|
1103
|
-
var
|
|
1988
|
+
var codemirrorToAutomerge = (field, handle, transactions, state) => {
|
|
1104
1989
|
const { lastHeads, path } = state.field(field);
|
|
1105
1990
|
let hasChanges = false;
|
|
1106
1991
|
for (const tr of transactions) {
|
|
@@ -1144,12 +2029,12 @@ var PatchSemaphore = class {
|
|
|
1144
2029
|
annotations: reconcileAnnotationType.of(true)
|
|
1145
2030
|
});
|
|
1146
2031
|
}
|
|
1147
|
-
let newHeads =
|
|
2032
|
+
let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
|
|
1148
2033
|
if (newHeads === null || newHeads === void 0) {
|
|
1149
2034
|
newHeads = automerge.getHeads(handle.docSync());
|
|
1150
2035
|
}
|
|
1151
2036
|
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
1152
|
-
|
|
2037
|
+
automergeToCodemirror(view, selection, path, diff);
|
|
1153
2038
|
view.dispatch({
|
|
1154
2039
|
effects: updateHeads(newHeads),
|
|
1155
2040
|
annotations: reconcileAnnotationType.of({})
|
|
@@ -1163,7 +2048,7 @@ var PatchSemaphore = class {
|
|
|
1163
2048
|
};
|
|
1164
2049
|
|
|
1165
2050
|
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1166
|
-
var effectType =
|
|
2051
|
+
var effectType = StateEffect2.define({});
|
|
1167
2052
|
var updateHeads = (newHeads) => effectType.of({
|
|
1168
2053
|
newHeads
|
|
1169
2054
|
});
|
|
@@ -1173,7 +2058,7 @@ var semaphoreFacet = Facet.define({
|
|
|
1173
2058
|
combine: (values) => values.at(-1)
|
|
1174
2059
|
});
|
|
1175
2060
|
var automergePlugin = (handle, path) => {
|
|
1176
|
-
const stateField =
|
|
2061
|
+
const stateField = StateField6.define({
|
|
1177
2062
|
create: () => ({
|
|
1178
2063
|
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
1179
2064
|
unreconciledTransactions: [],
|
|
@@ -1203,7 +2088,7 @@ var automergePlugin = (handle, path) => {
|
|
|
1203
2088
|
}
|
|
1204
2089
|
});
|
|
1205
2090
|
const semaphore = new PatchSemaphore(stateField);
|
|
1206
|
-
const viewPlugin =
|
|
2091
|
+
const viewPlugin = ViewPlugin4.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
1207
2092
|
constructor(view) {
|
|
1208
2093
|
this._handleChange = () => {
|
|
1209
2094
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
@@ -1211,8 +2096,8 @@ var automergePlugin = (handle, path) => {
|
|
|
1211
2096
|
this._view = view;
|
|
1212
2097
|
handle.addListener("change", this._handleChange);
|
|
1213
2098
|
}
|
|
1214
|
-
update(
|
|
1215
|
-
if (
|
|
2099
|
+
update(update4) {
|
|
2100
|
+
if (update4.transactions.length > 0 && update4.transactions.some((t) => !isReconcileTx(t))) {
|
|
1216
2101
|
queueMicrotask(() => {
|
|
1217
2102
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
1218
2103
|
});
|
|
@@ -1234,7 +2119,7 @@ var reconcileAnnotationType = Annotation.define();
|
|
|
1234
2119
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
1235
2120
|
|
|
1236
2121
|
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
1237
|
-
import * as
|
|
2122
|
+
import * as random2 from "lib0/random";
|
|
1238
2123
|
var cursorColors = [
|
|
1239
2124
|
{
|
|
1240
2125
|
color: "#30bced",
|
|
@@ -1269,7 +2154,7 @@ var cursorColors = [
|
|
|
1269
2154
|
light: "#1be7ff33"
|
|
1270
2155
|
}
|
|
1271
2156
|
];
|
|
1272
|
-
var cursorColor = cursorColors[
|
|
2157
|
+
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
1273
2158
|
|
|
1274
2159
|
// packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
|
|
1275
2160
|
import * as decoding from "lib0/decoding";
|
|
@@ -1277,7 +2162,7 @@ import * as encoding from "lib0/encoding";
|
|
|
1277
2162
|
import { Observable } from "lib0/observable";
|
|
1278
2163
|
import * as awarenessProtocol from "y-protocols/awareness";
|
|
1279
2164
|
import { log } from "@dxos/log";
|
|
1280
|
-
var
|
|
2165
|
+
var __dxlog_file3 = "/home/circleci/project/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
|
|
1281
2166
|
var messageAwareness = 1;
|
|
1282
2167
|
var messageQueryAwareness = 3;
|
|
1283
2168
|
var SpaceAwarenessProvider = class extends Observable {
|
|
@@ -1314,7 +2199,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1314
2199
|
removed,
|
|
1315
2200
|
origin
|
|
1316
2201
|
}, {
|
|
1317
|
-
F:
|
|
2202
|
+
F: __dxlog_file3,
|
|
1318
2203
|
L: 67,
|
|
1319
2204
|
S: this,
|
|
1320
2205
|
C: (f, a) => f(...a)
|
|
@@ -1327,7 +2212,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1327
2212
|
}
|
|
1328
2213
|
_handleSpaceMessage({ payload }) {
|
|
1329
2214
|
log("space message", payload, {
|
|
1330
|
-
F:
|
|
2215
|
+
F: __dxlog_file3,
|
|
1331
2216
|
L: 79,
|
|
1332
2217
|
S: this,
|
|
1333
2218
|
C: (f, a) => f(...a)
|
|
@@ -1372,14 +2257,14 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1372
2257
|
};
|
|
1373
2258
|
|
|
1374
2259
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1375
|
-
var
|
|
2260
|
+
var __dxlog_file4 = "/home/circleci/project/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
1376
2261
|
var useTextModel = ({ identity, space, text }) => {
|
|
1377
2262
|
const [model, setModel] = useState2(() => createModel({
|
|
1378
2263
|
identity,
|
|
1379
2264
|
space,
|
|
1380
2265
|
text
|
|
1381
2266
|
}));
|
|
1382
|
-
|
|
2267
|
+
useEffect3(() => {
|
|
1383
2268
|
setModel(createModel({
|
|
1384
2269
|
identity,
|
|
1385
2270
|
space,
|
|
@@ -1404,9 +2289,9 @@ var createModel = (options) => {
|
|
|
1404
2289
|
}
|
|
1405
2290
|
};
|
|
1406
2291
|
var createYjsModel = ({ identity, space, text }) => {
|
|
1407
|
-
|
|
1408
|
-
F:
|
|
1409
|
-
L:
|
|
2292
|
+
invariant3(text?.doc && text?.content, void 0, {
|
|
2293
|
+
F: __dxlog_file4,
|
|
2294
|
+
L: 81,
|
|
1410
2295
|
S: void 0,
|
|
1411
2296
|
A: [
|
|
1412
2297
|
"text?.doc && text?.content",
|
|
@@ -1422,6 +2307,7 @@ var createYjsModel = ({ identity, space, text }) => {
|
|
|
1422
2307
|
id: text.doc.guid,
|
|
1423
2308
|
content: text.content,
|
|
1424
2309
|
text: () => text.content.toString(),
|
|
2310
|
+
ranges: [],
|
|
1425
2311
|
extension: yCollab(text.content, provider?.awareness),
|
|
1426
2312
|
awareness: provider?.awareness,
|
|
1427
2313
|
peer: identity ? {
|
|
@@ -1438,7 +2324,8 @@ var createAutomergeModel = ({ identity, text }) => {
|
|
|
1438
2324
|
return {
|
|
1439
2325
|
id: obj.id,
|
|
1440
2326
|
content: doc,
|
|
1441
|
-
text: () =>
|
|
2327
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2328
|
+
ranges: [],
|
|
1442
2329
|
extension: automergePlugin(doc.handle, doc.path),
|
|
1443
2330
|
peer: identity ? {
|
|
1444
2331
|
id: identity.identityKey.toHex(),
|
|
@@ -1458,24 +2345,35 @@ export {
|
|
|
1458
2345
|
YXmlFragment,
|
|
1459
2346
|
autocomplete,
|
|
1460
2347
|
basicBundle,
|
|
2348
|
+
blast,
|
|
2349
|
+
code2 as code,
|
|
1461
2350
|
codeTheme,
|
|
1462
2351
|
comments,
|
|
1463
2352
|
cursorColor,
|
|
1464
2353
|
defaultMarkdownSlots,
|
|
2354
|
+
defaultOptions,
|
|
1465
2355
|
defaultSlots,
|
|
1466
2356
|
defaultTextSlots,
|
|
1467
2357
|
defaultTheme,
|
|
2358
|
+
demo,
|
|
2359
|
+
highlight,
|
|
2360
|
+
highlightDecorations,
|
|
2361
|
+
highlightStateField,
|
|
2362
|
+
image,
|
|
1468
2363
|
link,
|
|
1469
|
-
listener,
|
|
2364
|
+
listener2 as listener,
|
|
1470
2365
|
markdownBundle,
|
|
1471
2366
|
markdownHighlightStyle,
|
|
1472
2367
|
markdownTags,
|
|
1473
|
-
|
|
2368
|
+
markdownTagsExtensions,
|
|
1474
2369
|
markdownTheme,
|
|
2370
|
+
mention,
|
|
2371
|
+
table,
|
|
1475
2372
|
tags2 as tags,
|
|
1476
2373
|
tasklist,
|
|
1477
2374
|
textTheme,
|
|
1478
2375
|
tooltip,
|
|
2376
|
+
useHighlights,
|
|
1479
2377
|
useTextModel
|
|
1480
2378
|
};
|
|
1481
2379
|
//# sourceMappingURL=index.mjs.map
|