@dxos/react-ui-editor 0.3.11-main.d8b8a39 → 0.3.11-main.d8f9aa0
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 +529 -484
- 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.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -6
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
- package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +7 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
- package/package.json +23 -23
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +2 -0
- package/src/extensions/index.ts +0 -6
- package/src/extensions/{code.ts → markdown/code.ts} +1 -1
- package/src/extensions/markdown/heading.ts +60 -0
- package/src/extensions/{hr.ts → markdown/hr.ts} +1 -1
- package/src/extensions/markdown/index.ts +7 -0
- package/src/extensions/{tasklist.ts → markdown/tasklist.ts} +1 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
- /package/src/extensions/{image.ts → markdown/image.ts} +0 -0
- /package/src/extensions/{link.ts → markdown/link.ts} +0 -0
- /package/src/extensions/{table.ts → markdown/table.ts} +0 -0
|
@@ -947,9 +947,14 @@ var random = (min, max) => {
|
|
|
947
947
|
return min + ~~(Math.random() * (max - min + 1));
|
|
948
948
|
};
|
|
949
949
|
|
|
950
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
951
|
-
import {
|
|
952
|
-
import {
|
|
950
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
951
|
+
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
952
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
953
|
+
import sortBy from "lodash.sortby";
|
|
954
|
+
import { useEffect } from "react";
|
|
955
|
+
import { debounce } from "@dxos/async";
|
|
956
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
957
|
+
import { nonNullable } from "@dxos/util";
|
|
953
958
|
|
|
954
959
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
955
960
|
import * as random2 from "lib0/random";
|
|
@@ -1037,89 +1042,6 @@ import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
|
1037
1042
|
var tokens = tailwindConfig({}).theme;
|
|
1038
1043
|
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1039
1044
|
|
|
1040
|
-
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1041
|
-
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1042
|
-
var styles2 = EditorView5.baseTheme({
|
|
1043
|
-
"& .cm-codeblock": {
|
|
1044
|
-
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1045
|
-
},
|
|
1046
|
-
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1047
|
-
background: getToken("extend.colors.neutral.50")
|
|
1048
|
-
},
|
|
1049
|
-
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1050
|
-
background: getToken("extend.colors.neutral.850")
|
|
1051
|
-
},
|
|
1052
|
-
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1053
|
-
display: "block",
|
|
1054
|
-
paddingInline: "4px !important"
|
|
1055
|
-
},
|
|
1056
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1057
|
-
paddingTop: "4px !important",
|
|
1058
|
-
borderTopLeftRadius: "4px",
|
|
1059
|
-
borderTopRightRadius: "4px"
|
|
1060
|
-
},
|
|
1061
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1062
|
-
paddingBottom: "4px !important",
|
|
1063
|
-
borderBottomLeftRadius: "4px",
|
|
1064
|
-
borderBottomRightRadius: "4px"
|
|
1065
|
-
}
|
|
1066
|
-
});
|
|
1067
|
-
var getLineRange = (lines, from, to) => {
|
|
1068
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1069
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1070
|
-
return [
|
|
1071
|
-
start,
|
|
1072
|
-
end
|
|
1073
|
-
];
|
|
1074
|
-
};
|
|
1075
|
-
var code2 = () => {
|
|
1076
|
-
const buildDecorations5 = (view) => {
|
|
1077
|
-
const decorations = [];
|
|
1078
|
-
const text = view.state.doc.sliceString(0);
|
|
1079
|
-
const matches = text.matchAll(CODE_REGEX);
|
|
1080
|
-
const blocks = view.viewportLineBlocks;
|
|
1081
|
-
for (const match of matches) {
|
|
1082
|
-
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1083
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1084
|
-
const block = blocks[i];
|
|
1085
|
-
decorations.push(Decoration2.line({
|
|
1086
|
-
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1087
|
-
}).range(block.from));
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
return Decoration2.set(decorations);
|
|
1091
|
-
};
|
|
1092
|
-
return [
|
|
1093
|
-
ViewPlugin3.fromClass(class {
|
|
1094
|
-
constructor(view) {
|
|
1095
|
-
this.hasFocus = false;
|
|
1096
|
-
this.decorations = buildDecorations5(view);
|
|
1097
|
-
}
|
|
1098
|
-
update(update2) {
|
|
1099
|
-
if (
|
|
1100
|
-
// TODO(burdon): Generalize for other extensions.
|
|
1101
|
-
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1102
|
-
) {
|
|
1103
|
-
this.hasFocus = update2.view.hasFocus;
|
|
1104
|
-
this.decorations = buildDecorations5(update2.view);
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
}, {
|
|
1108
|
-
decorations: (value) => value.decorations
|
|
1109
|
-
}),
|
|
1110
|
-
styles2
|
|
1111
|
-
];
|
|
1112
|
-
};
|
|
1113
|
-
|
|
1114
|
-
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1115
|
-
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1116
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
|
|
1117
|
-
import sortBy from "lodash.sortby";
|
|
1118
|
-
import { useEffect } from "react";
|
|
1119
|
-
import { debounce } from "@dxos/async";
|
|
1120
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1121
|
-
import { nonNullable } from "@dxos/util";
|
|
1122
|
-
|
|
1123
1045
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1124
1046
|
import { log } from "@dxos/log";
|
|
1125
1047
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
@@ -1157,7 +1079,7 @@ var logChanges = (trs) => {
|
|
|
1157
1079
|
|
|
1158
1080
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1159
1081
|
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1160
|
-
var
|
|
1082
|
+
var styles2 = EditorView5.baseTheme({
|
|
1161
1083
|
"& .cm-comment": {
|
|
1162
1084
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1163
1085
|
},
|
|
@@ -1166,10 +1088,10 @@ var styles3 = EditorView6.baseTheme({
|
|
|
1166
1088
|
}
|
|
1167
1089
|
});
|
|
1168
1090
|
var marks = {
|
|
1169
|
-
highlight:
|
|
1091
|
+
highlight: Decoration2.mark({
|
|
1170
1092
|
class: "cm-comment"
|
|
1171
1093
|
}),
|
|
1172
|
-
highlightActive:
|
|
1094
|
+
highlightActive: Decoration2.mark({
|
|
1173
1095
|
class: "cm-comment-current"
|
|
1174
1096
|
})
|
|
1175
1097
|
};
|
|
@@ -1186,7 +1108,7 @@ var setFocus = (view, id, center = true) => {
|
|
|
1186
1108
|
},
|
|
1187
1109
|
effects: [
|
|
1188
1110
|
//
|
|
1189
|
-
|
|
1111
|
+
EditorView5.scrollIntoView(range.from, center ? {
|
|
1190
1112
|
y: "center"
|
|
1191
1113
|
} : void 0),
|
|
1192
1114
|
setSelection.of({
|
|
@@ -1235,7 +1157,7 @@ var commentsState = StateField2.define({
|
|
|
1235
1157
|
return value;
|
|
1236
1158
|
}
|
|
1237
1159
|
});
|
|
1238
|
-
var highlightDecorations =
|
|
1160
|
+
var highlightDecorations = EditorView5.decorations.compute([
|
|
1239
1161
|
commentsState
|
|
1240
1162
|
], (state) => {
|
|
1241
1163
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
@@ -1251,7 +1173,7 @@ var highlightDecorations = EditorView6.decorations.compute([
|
|
|
1251
1173
|
return marks.highlight.range(range.from, range.to);
|
|
1252
1174
|
}
|
|
1253
1175
|
}).filter(nonNullable);
|
|
1254
|
-
return
|
|
1176
|
+
return Decoration2.set(decorations);
|
|
1255
1177
|
});
|
|
1256
1178
|
var trackPastedComments = (onUpdate) => {
|
|
1257
1179
|
let tracked = null;
|
|
@@ -1273,12 +1195,12 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1273
1195
|
}
|
|
1274
1196
|
};
|
|
1275
1197
|
return [
|
|
1276
|
-
|
|
1198
|
+
EditorView5.domEventHandlers({
|
|
1277
1199
|
cut: handleTrack,
|
|
1278
1200
|
copy: handleTrack
|
|
1279
1201
|
}),
|
|
1280
1202
|
// Handle paste.
|
|
1281
|
-
|
|
1203
|
+
EditorView5.updateListener.of(({ view, state, transactions }) => {
|
|
1282
1204
|
if (tracked) {
|
|
1283
1205
|
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1284
1206
|
if (paste) {
|
|
@@ -1355,7 +1277,7 @@ var comments = (options = {}) => {
|
|
|
1355
1277
|
return [
|
|
1356
1278
|
commentsState,
|
|
1357
1279
|
highlightDecorations,
|
|
1358
|
-
|
|
1280
|
+
styles2,
|
|
1359
1281
|
//
|
|
1360
1282
|
// Keymap.
|
|
1361
1283
|
//
|
|
@@ -1398,7 +1320,7 @@ var comments = (options = {}) => {
|
|
|
1398
1320
|
//
|
|
1399
1321
|
// Track deleted ranges and update ranges for decorations.
|
|
1400
1322
|
//
|
|
1401
|
-
|
|
1323
|
+
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1402
1324
|
let mod = false;
|
|
1403
1325
|
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1404
1326
|
changes.iterChanges((from, to, from2, to2) => {
|
|
@@ -1428,7 +1350,7 @@ var comments = (options = {}) => {
|
|
|
1428
1350
|
//
|
|
1429
1351
|
// Track selection/proximity.
|
|
1430
1352
|
//
|
|
1431
|
-
|
|
1353
|
+
EditorView5.updateListener.of(({ view, state }) => {
|
|
1432
1354
|
let min = Infinity;
|
|
1433
1355
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1434
1356
|
const { head } = state.selection.main;
|
|
@@ -1476,329 +1398,65 @@ var useComments = (view, comments2 = []) => {
|
|
|
1476
1398
|
]);
|
|
1477
1399
|
};
|
|
1478
1400
|
|
|
1479
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1480
|
-
import {
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
const el = document.createElement("div");
|
|
1492
|
-
el.className = "cm-hr";
|
|
1493
|
-
return el;
|
|
1494
|
-
}
|
|
1495
|
-
};
|
|
1496
|
-
var decoration = Decoration4.replace({
|
|
1497
|
-
widget: new HorizontalRuleWidget()
|
|
1498
|
-
});
|
|
1499
|
-
var buildDecorations = (view) => {
|
|
1500
|
-
const builder = new RangeSetBuilder();
|
|
1501
|
-
const { state } = view;
|
|
1502
|
-
const cursor = state.selection.main.head;
|
|
1503
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1504
|
-
syntaxTree(state).iterate({
|
|
1505
|
-
enter: (node) => {
|
|
1506
|
-
if (node.name === "HorizontalRule") {
|
|
1507
|
-
if (cursor <= node.from || cursor >= node.to) {
|
|
1508
|
-
builder.add(node.from, node.to, decoration);
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
},
|
|
1512
|
-
from,
|
|
1513
|
-
to
|
|
1514
|
-
});
|
|
1515
|
-
}
|
|
1516
|
-
return builder.finish();
|
|
1517
|
-
};
|
|
1518
|
-
var hr = () => {
|
|
1519
|
-
return [
|
|
1520
|
-
styles4,
|
|
1521
|
-
ViewPlugin4.fromClass(class {
|
|
1522
|
-
constructor(view) {
|
|
1523
|
-
this.decorations = buildDecorations(view);
|
|
1524
|
-
}
|
|
1525
|
-
update(update2) {
|
|
1526
|
-
this.decorations = buildDecorations(update2.view);
|
|
1527
|
-
}
|
|
1528
|
-
}, {
|
|
1529
|
-
decorations: (v) => v.decorations
|
|
1530
|
-
})
|
|
1531
|
-
];
|
|
1401
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1402
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
1403
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1404
|
+
const extensions = [];
|
|
1405
|
+
onFocus && extensions.push(EditorView6.focusChangeEffect.of((_, focused) => {
|
|
1406
|
+
onFocus(focused);
|
|
1407
|
+
return null;
|
|
1408
|
+
}));
|
|
1409
|
+
onChange && extensions.push(EditorView6.updateListener.of((update2) => {
|
|
1410
|
+
onChange(update2.state.doc.toString());
|
|
1411
|
+
}));
|
|
1412
|
+
return extensions;
|
|
1532
1413
|
};
|
|
1533
1414
|
|
|
1534
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1535
|
-
import {
|
|
1536
|
-
import {
|
|
1537
|
-
import {
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
provide: (field) => EditorView8.decorations.from(field)
|
|
1565
|
-
});
|
|
1566
|
-
};
|
|
1567
|
-
var buildDecorations2 = (from, to, state) => {
|
|
1568
|
-
const decorations = [];
|
|
1569
|
-
const cursor = state.selection.main.head;
|
|
1570
|
-
syntaxTree2(state).iterate({
|
|
1571
|
-
enter: (node) => {
|
|
1572
|
-
if (node.name === "Image") {
|
|
1573
|
-
const urlNode = node.node.getChild("URL");
|
|
1574
|
-
if (urlNode) {
|
|
1575
|
-
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1576
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1577
|
-
decorations.push(Decoration5.replace({
|
|
1578
|
-
block: true,
|
|
1579
|
-
widget: new ImageWidget(url)
|
|
1580
|
-
}).range(hide ? node.from : node.to, node.to));
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
},
|
|
1584
|
-
from,
|
|
1585
|
-
to
|
|
1586
|
-
});
|
|
1587
|
-
return decorations;
|
|
1415
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1416
|
+
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1417
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1418
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1419
|
+
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1420
|
+
import { languages } from "@codemirror/language-data";
|
|
1421
|
+
import { searchKeymap } from "@codemirror/search";
|
|
1422
|
+
import { EditorState } from "@codemirror/state";
|
|
1423
|
+
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1424
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1425
|
+
|
|
1426
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1427
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1428
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
1429
|
+
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1430
|
+
import { Table } from "@lezer/markdown";
|
|
1431
|
+
var markdownTags = {
|
|
1432
|
+
Blockquote: Tag.define(),
|
|
1433
|
+
CodeMark: Tag.define(),
|
|
1434
|
+
CodeText: Tag.define(),
|
|
1435
|
+
EmphasisMark: Tag.define(),
|
|
1436
|
+
HeaderMark: Tag.define(),
|
|
1437
|
+
InlineCode: Tag.define(),
|
|
1438
|
+
LinkLabel: Tag.define(),
|
|
1439
|
+
LinkReference: Tag.define(),
|
|
1440
|
+
ListMark: Tag.define(),
|
|
1441
|
+
QuoteMark: Tag.define(),
|
|
1442
|
+
URL: Tag.define(),
|
|
1443
|
+
// Custom.
|
|
1444
|
+
TableCell: Tag.define()
|
|
1588
1445
|
};
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
return this._url === other._url;
|
|
1446
|
+
Table.defineNodes?.forEach((node) => {
|
|
1447
|
+
switch (node?.name) {
|
|
1448
|
+
case "TableCell": {
|
|
1449
|
+
node.style = markdownTags.TableCell;
|
|
1450
|
+
break;
|
|
1451
|
+
}
|
|
1596
1452
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
};
|
|
1605
|
-
|
|
1606
|
-
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1607
|
-
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1608
|
-
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1609
|
-
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin5, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1610
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1611
|
-
var link = (options = {}) => {
|
|
1612
|
-
const extensions = [
|
|
1613
|
-
ViewPlugin5.fromClass(class {
|
|
1614
|
-
constructor(view) {
|
|
1615
|
-
this.decorations = buildDecorations3(view, options);
|
|
1616
|
-
}
|
|
1617
|
-
update(update2) {
|
|
1618
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1619
|
-
this.decorations = buildDecorations3(update2.view, options);
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
}, {
|
|
1623
|
-
decorations: (v) => v.decorations
|
|
1624
|
-
})
|
|
1625
|
-
];
|
|
1626
|
-
if (options.onHover) {
|
|
1627
|
-
extensions.push(
|
|
1628
|
-
// https://codemirror.net/examples/tooltip
|
|
1629
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1630
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1631
|
-
hoverTooltip2((view, pos, side) => {
|
|
1632
|
-
const syntax = syntaxTree3(view.state).resolveInner(pos, side);
|
|
1633
|
-
let link2 = null;
|
|
1634
|
-
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1635
|
-
link2 = node.name === "Link" ? node : null;
|
|
1636
|
-
}
|
|
1637
|
-
const url = link2 && link2.getChild("URL");
|
|
1638
|
-
if (!url || !link2) {
|
|
1639
|
-
return null;
|
|
1640
|
-
}
|
|
1641
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1642
|
-
return {
|
|
1643
|
-
pos: link2.from,
|
|
1644
|
-
end: link2.to,
|
|
1645
|
-
above: true,
|
|
1646
|
-
create: () => {
|
|
1647
|
-
const el = document.createElement("div");
|
|
1648
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1649
|
-
options.onHover(el, urlText);
|
|
1650
|
-
return {
|
|
1651
|
-
dom: el,
|
|
1652
|
-
offset: {
|
|
1653
|
-
x: 0,
|
|
1654
|
-
y: 4
|
|
1655
|
-
}
|
|
1656
|
-
};
|
|
1657
|
-
}
|
|
1658
|
-
};
|
|
1659
|
-
})
|
|
1660
|
-
);
|
|
1661
|
-
}
|
|
1662
|
-
return extensions;
|
|
1663
|
-
};
|
|
1664
|
-
var LinkButton = class extends WidgetType4 {
|
|
1665
|
-
constructor(_url, _onAttach) {
|
|
1666
|
-
super();
|
|
1667
|
-
this._url = _url;
|
|
1668
|
-
this._onAttach = _onAttach;
|
|
1669
|
-
}
|
|
1670
|
-
eq(other) {
|
|
1671
|
-
return this._url === other._url;
|
|
1672
|
-
}
|
|
1673
|
-
toDOM(view) {
|
|
1674
|
-
const el = document.createElement("span");
|
|
1675
|
-
this._onAttach(el, this._url);
|
|
1676
|
-
return el;
|
|
1677
|
-
}
|
|
1678
|
-
};
|
|
1679
|
-
var LinkText = class extends WidgetType4 {
|
|
1680
|
-
constructor(_text, _url) {
|
|
1681
|
-
super();
|
|
1682
|
-
this._text = _text;
|
|
1683
|
-
this._url = _url;
|
|
1684
|
-
}
|
|
1685
|
-
eq(other) {
|
|
1686
|
-
return this._url === other._url;
|
|
1687
|
-
}
|
|
1688
|
-
toDOM(view) {
|
|
1689
|
-
const link2 = document.createElement("a");
|
|
1690
|
-
link2.setAttribute("class", "cm-link");
|
|
1691
|
-
link2.textContent = this._text;
|
|
1692
|
-
if (this._url) {
|
|
1693
|
-
link2.setAttribute("rel", "noreferrer");
|
|
1694
|
-
link2.setAttribute("target", "_blank");
|
|
1695
|
-
link2.href = this._url;
|
|
1696
|
-
} else {
|
|
1697
|
-
link2.onclick = () => {
|
|
1698
|
-
view.dispatch({
|
|
1699
|
-
selection: {
|
|
1700
|
-
anchor: view.posAtDOM(link2)
|
|
1701
|
-
}
|
|
1702
|
-
});
|
|
1703
|
-
};
|
|
1704
|
-
}
|
|
1705
|
-
return link2;
|
|
1706
|
-
}
|
|
1707
|
-
};
|
|
1708
|
-
var buildDecorations3 = (view, options) => {
|
|
1709
|
-
const builder = new RangeSetBuilder2();
|
|
1710
|
-
const { state } = view;
|
|
1711
|
-
const cursor = state.selection.main.head;
|
|
1712
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1713
|
-
syntaxTree3(state).iterate({
|
|
1714
|
-
enter: (node) => {
|
|
1715
|
-
if (node.name === "Link") {
|
|
1716
|
-
const marks2 = node.node.getChildren("LinkMark");
|
|
1717
|
-
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1718
|
-
const urlNode = node.node.getChild("URL");
|
|
1719
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1720
|
-
if (!url) {
|
|
1721
|
-
return false;
|
|
1722
|
-
}
|
|
1723
|
-
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1724
|
-
builder.add(node.from, node.to, Decoration6.replace({
|
|
1725
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
1726
|
-
}));
|
|
1727
|
-
}
|
|
1728
|
-
if (options.onRender) {
|
|
1729
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1730
|
-
widget: new LinkButton(url, options.onRender)
|
|
1731
|
-
}));
|
|
1732
|
-
}
|
|
1733
|
-
return false;
|
|
1734
|
-
}
|
|
1735
|
-
},
|
|
1736
|
-
from,
|
|
1737
|
-
to
|
|
1738
|
-
});
|
|
1739
|
-
}
|
|
1740
|
-
return builder.finish();
|
|
1741
|
-
};
|
|
1742
|
-
|
|
1743
|
-
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1744
|
-
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1745
|
-
var listener = ({ onFocus, onChange }) => {
|
|
1746
|
-
const extensions = [];
|
|
1747
|
-
onFocus && extensions.push(EditorView9.focusChangeEffect.of((_, focused) => {
|
|
1748
|
-
onFocus(focused);
|
|
1749
|
-
return null;
|
|
1750
|
-
}));
|
|
1751
|
-
onChange && extensions.push(EditorView9.updateListener.of((update2) => {
|
|
1752
|
-
onChange(update2.state.doc.toString());
|
|
1753
|
-
}));
|
|
1754
|
-
return extensions;
|
|
1755
|
-
};
|
|
1756
|
-
|
|
1757
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1758
|
-
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1759
|
-
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1760
|
-
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1761
|
-
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1762
|
-
import { languages } from "@codemirror/language-data";
|
|
1763
|
-
import { searchKeymap } from "@codemirror/search";
|
|
1764
|
-
import { EditorState } from "@codemirror/state";
|
|
1765
|
-
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1766
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView10, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1767
|
-
|
|
1768
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1769
|
-
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1770
|
-
import { HighlightStyle } from "@codemirror/language";
|
|
1771
|
-
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1772
|
-
import { Table } from "@lezer/markdown";
|
|
1773
|
-
var markdownTags = {
|
|
1774
|
-
Blockquote: Tag.define(),
|
|
1775
|
-
CodeMark: Tag.define(),
|
|
1776
|
-
CodeText: Tag.define(),
|
|
1777
|
-
EmphasisMark: Tag.define(),
|
|
1778
|
-
HeaderMark: Tag.define(),
|
|
1779
|
-
InlineCode: Tag.define(),
|
|
1780
|
-
LinkLabel: Tag.define(),
|
|
1781
|
-
LinkReference: Tag.define(),
|
|
1782
|
-
ListMark: Tag.define(),
|
|
1783
|
-
QuoteMark: Tag.define(),
|
|
1784
|
-
URL: Tag.define(),
|
|
1785
|
-
// Custom.
|
|
1786
|
-
TableCell: Tag.define()
|
|
1787
|
-
};
|
|
1788
|
-
Table.defineNodes?.forEach((node) => {
|
|
1789
|
-
switch (node?.name) {
|
|
1790
|
-
case "TableCell": {
|
|
1791
|
-
node.style = markdownTags.TableCell;
|
|
1792
|
-
break;
|
|
1793
|
-
}
|
|
1794
|
-
}
|
|
1795
|
-
});
|
|
1796
|
-
var markdownTagsExtensions = [
|
|
1797
|
-
Table,
|
|
1798
|
-
{
|
|
1799
|
-
props: [
|
|
1800
|
-
styleTags(markdownTags)
|
|
1801
|
-
]
|
|
1453
|
+
});
|
|
1454
|
+
var markdownTagsExtensions = [
|
|
1455
|
+
Table,
|
|
1456
|
+
{
|
|
1457
|
+
props: [
|
|
1458
|
+
styleTags(markdownTags)
|
|
1459
|
+
]
|
|
1802
1460
|
}
|
|
1803
1461
|
];
|
|
1804
1462
|
var markdownHighlightStyle = (readonly) => {
|
|
@@ -1958,7 +1616,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1958
1616
|
return [
|
|
1959
1617
|
EditorState.allowMultipleSelections.of(true),
|
|
1960
1618
|
EditorState.tabSize.of(2),
|
|
1961
|
-
|
|
1619
|
+
EditorView7.lineWrapping,
|
|
1962
1620
|
// https://github.com/codemirror/basic-setup
|
|
1963
1621
|
bracketMatching2(),
|
|
1964
1622
|
closeBrackets2(),
|
|
@@ -2006,61 +1664,413 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
2006
1664
|
];
|
|
2007
1665
|
};
|
|
2008
1666
|
|
|
2009
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
2010
|
-
import {
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
}
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField4 } from "@codemirror/state";
|
|
2046
|
-
import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
2047
|
-
var table = (options = {}) => {
|
|
2048
|
-
return StateField4.define({
|
|
2049
|
-
create: (state) => update(state, options),
|
|
2050
|
-
update: (_, tr) => update(tr.state, options),
|
|
2051
|
-
provide: (field) => EditorView11.decorations.from(field)
|
|
2052
|
-
});
|
|
1667
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
1668
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Decoration3 } from "@codemirror/view";
|
|
1669
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1670
|
+
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1671
|
+
var styles3 = EditorView8.baseTheme({
|
|
1672
|
+
"& .cm-codeblock": {
|
|
1673
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1674
|
+
},
|
|
1675
|
+
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1676
|
+
background: getToken("extend.colors.neutral.50")
|
|
1677
|
+
},
|
|
1678
|
+
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1679
|
+
background: getToken("extend.colors.neutral.850")
|
|
1680
|
+
},
|
|
1681
|
+
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1682
|
+
display: "block",
|
|
1683
|
+
paddingInline: "4px !important"
|
|
1684
|
+
},
|
|
1685
|
+
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1686
|
+
paddingTop: "4px !important",
|
|
1687
|
+
borderTopLeftRadius: "4px",
|
|
1688
|
+
borderTopRightRadius: "4px"
|
|
1689
|
+
},
|
|
1690
|
+
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1691
|
+
paddingBottom: "4px !important",
|
|
1692
|
+
borderBottomLeftRadius: "4px",
|
|
1693
|
+
borderBottomRightRadius: "4px"
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1696
|
+
var getLineRange = (lines, from, to) => {
|
|
1697
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1698
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1699
|
+
return [
|
|
1700
|
+
start,
|
|
1701
|
+
end
|
|
1702
|
+
];
|
|
2053
1703
|
};
|
|
2054
|
-
var
|
|
2055
|
-
const
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
const
|
|
1704
|
+
var code2 = () => {
|
|
1705
|
+
const buildDecorations6 = (view) => {
|
|
1706
|
+
const decorations = [];
|
|
1707
|
+
const text = view.state.doc.sliceString(0);
|
|
1708
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1709
|
+
const blocks = view.viewportLineBlocks;
|
|
1710
|
+
for (const match of matches) {
|
|
1711
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1712
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1713
|
+
const block = blocks[i];
|
|
1714
|
+
decorations.push(Decoration3.line({
|
|
1715
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1716
|
+
}).range(block.from));
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
return Decoration3.set(decorations);
|
|
1720
|
+
};
|
|
1721
|
+
return [
|
|
1722
|
+
ViewPlugin3.fromClass(class {
|
|
1723
|
+
constructor(view) {
|
|
1724
|
+
this.hasFocus = false;
|
|
1725
|
+
this.decorations = buildDecorations6(view);
|
|
1726
|
+
}
|
|
1727
|
+
update(update2) {
|
|
1728
|
+
if (
|
|
1729
|
+
// TODO(burdon): Generalize for other extensions.
|
|
1730
|
+
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1731
|
+
) {
|
|
1732
|
+
this.hasFocus = update2.view.hasFocus;
|
|
1733
|
+
this.decorations = buildDecorations6(update2.view);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
}, {
|
|
1737
|
+
decorations: (value) => value.decorations
|
|
1738
|
+
}),
|
|
1739
|
+
styles3
|
|
1740
|
+
];
|
|
1741
|
+
};
|
|
1742
|
+
|
|
1743
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1744
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1745
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1746
|
+
import { Decoration as Decoration4, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1747
|
+
var buildDecorations = (view) => {
|
|
1748
|
+
const builder = new RangeSetBuilder();
|
|
1749
|
+
const { state } = view;
|
|
1750
|
+
const cursor = state.selection.main.head;
|
|
1751
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1752
|
+
syntaxTree(state).iterate({
|
|
1753
|
+
enter: (node) => {
|
|
1754
|
+
switch (node.name) {
|
|
1755
|
+
case "ATXHeading1":
|
|
1756
|
+
case "ATXHeading2":
|
|
1757
|
+
case "ATXHeading3":
|
|
1758
|
+
case "ATXHeading4":
|
|
1759
|
+
case "ATXHeading5":
|
|
1760
|
+
case "ATXHeading6": {
|
|
1761
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
1762
|
+
if (mark2 && (cursor < node.from || cursor > node.to)) {
|
|
1763
|
+
builder.add(mark2.from, mark2.to + 1, Decoration4.replace({}));
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
},
|
|
1768
|
+
from,
|
|
1769
|
+
to
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
return builder.finish();
|
|
1773
|
+
};
|
|
1774
|
+
var heading2 = () => {
|
|
1775
|
+
return [
|
|
1776
|
+
ViewPlugin4.fromClass(class {
|
|
1777
|
+
constructor(view) {
|
|
1778
|
+
this.decorations = buildDecorations(view);
|
|
1779
|
+
}
|
|
1780
|
+
update(update2) {
|
|
1781
|
+
this.decorations = buildDecorations(update2.view);
|
|
1782
|
+
}
|
|
1783
|
+
}, {
|
|
1784
|
+
decorations: (v) => v.decorations
|
|
1785
|
+
})
|
|
1786
|
+
];
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1789
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
1790
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1791
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1792
|
+
import { Decoration as Decoration5, EditorView as EditorView9, ViewPlugin as ViewPlugin5, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1793
|
+
var styles4 = EditorView9.baseTheme({
|
|
1794
|
+
"& .cm-hr": {
|
|
1795
|
+
// Note that block-level decorations should not have vertical margins,
|
|
1796
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1797
|
+
}
|
|
1798
|
+
});
|
|
1799
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1800
|
+
toDOM() {
|
|
1801
|
+
const el = document.createElement("div");
|
|
1802
|
+
el.className = "cm-hr";
|
|
1803
|
+
return el;
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
var decoration = Decoration5.replace({
|
|
1807
|
+
widget: new HorizontalRuleWidget()
|
|
1808
|
+
});
|
|
1809
|
+
var buildDecorations2 = (view) => {
|
|
1810
|
+
const builder = new RangeSetBuilder2();
|
|
1811
|
+
const { state } = view;
|
|
1812
|
+
const cursor = state.selection.main.head;
|
|
1813
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1814
|
+
syntaxTree2(state).iterate({
|
|
1815
|
+
enter: (node) => {
|
|
1816
|
+
if (node.name === "HorizontalRule") {
|
|
1817
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1818
|
+
builder.add(node.from, node.to, decoration);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
},
|
|
1822
|
+
from,
|
|
1823
|
+
to
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
return builder.finish();
|
|
1827
|
+
};
|
|
1828
|
+
var hr = () => {
|
|
1829
|
+
return [
|
|
1830
|
+
styles4,
|
|
1831
|
+
ViewPlugin5.fromClass(class {
|
|
1832
|
+
constructor(view) {
|
|
1833
|
+
this.decorations = buildDecorations2(view);
|
|
1834
|
+
}
|
|
1835
|
+
update(update2) {
|
|
1836
|
+
this.decorations = buildDecorations2(update2.view);
|
|
1837
|
+
}
|
|
1838
|
+
}, {
|
|
1839
|
+
decorations: (v) => v.decorations
|
|
1840
|
+
})
|
|
1841
|
+
];
|
|
1842
|
+
};
|
|
1843
|
+
|
|
1844
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
1845
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1846
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1847
|
+
import { Decoration as Decoration6, EditorView as EditorView10, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1848
|
+
var image = (options = {}) => {
|
|
1849
|
+
return StateField3.define({
|
|
1850
|
+
create: (state) => {
|
|
1851
|
+
return Decoration6.set(buildDecorations3(0, state.doc.length, state));
|
|
1852
|
+
},
|
|
1853
|
+
update: (value, tr) => {
|
|
1854
|
+
if (!tr.docChanged && !tr.selection) {
|
|
1855
|
+
return value;
|
|
1856
|
+
}
|
|
1857
|
+
const cursor = tr.state.selection.main.head;
|
|
1858
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1859
|
+
let from = Math.min(cursor, oldCursor);
|
|
1860
|
+
let to = Math.max(cursor, oldCursor);
|
|
1861
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1862
|
+
from = Math.min(from, fromB);
|
|
1863
|
+
to = Math.max(to, toB);
|
|
1864
|
+
});
|
|
1865
|
+
from = tr.state.doc.lineAt(from).from;
|
|
1866
|
+
to = tr.state.doc.lineAt(to).to;
|
|
1867
|
+
return value.map(tr.changes).update({
|
|
1868
|
+
filterFrom: from,
|
|
1869
|
+
filterTo: to,
|
|
1870
|
+
filter: () => false,
|
|
1871
|
+
add: buildDecorations3(from, to, tr.state)
|
|
1872
|
+
});
|
|
1873
|
+
},
|
|
1874
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1875
|
+
});
|
|
1876
|
+
};
|
|
1877
|
+
var buildDecorations3 = (from, to, state) => {
|
|
1878
|
+
const decorations = [];
|
|
1879
|
+
const cursor = state.selection.main.head;
|
|
1880
|
+
syntaxTree3(state).iterate({
|
|
1881
|
+
enter: (node) => {
|
|
1882
|
+
if (node.name === "Image") {
|
|
1883
|
+
const urlNode = node.node.getChild("URL");
|
|
1884
|
+
if (urlNode) {
|
|
1885
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1886
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1887
|
+
decorations.push(Decoration6.replace({
|
|
1888
|
+
block: true,
|
|
1889
|
+
widget: new ImageWidget(url)
|
|
1890
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
},
|
|
1894
|
+
from,
|
|
1895
|
+
to
|
|
1896
|
+
});
|
|
1897
|
+
return decorations;
|
|
1898
|
+
};
|
|
1899
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1900
|
+
constructor(_url) {
|
|
1901
|
+
super();
|
|
1902
|
+
this._url = _url;
|
|
1903
|
+
}
|
|
1904
|
+
eq(other) {
|
|
1905
|
+
return this._url === other._url;
|
|
1906
|
+
}
|
|
1907
|
+
toDOM(view) {
|
|
1908
|
+
const img = document.createElement("img");
|
|
1909
|
+
img.setAttribute("src", this._url);
|
|
1910
|
+
img.setAttribute("class", "cm-image");
|
|
1911
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1912
|
+
return img;
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
|
|
1916
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
1917
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
1918
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1919
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration7, ViewPlugin as ViewPlugin6, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1920
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1921
|
+
var link = (options = {}) => {
|
|
1922
|
+
const extensions = [
|
|
1923
|
+
ViewPlugin6.fromClass(class {
|
|
1924
|
+
constructor(view) {
|
|
1925
|
+
this.decorations = buildDecorations4(view, options);
|
|
1926
|
+
}
|
|
1927
|
+
update(update2) {
|
|
1928
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1929
|
+
this.decorations = buildDecorations4(update2.view, options);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}, {
|
|
1933
|
+
decorations: (v) => v.decorations
|
|
1934
|
+
})
|
|
1935
|
+
];
|
|
1936
|
+
if (options.onHover) {
|
|
1937
|
+
extensions.push(
|
|
1938
|
+
// https://codemirror.net/examples/tooltip
|
|
1939
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1940
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1941
|
+
hoverTooltip2((view, pos, side) => {
|
|
1942
|
+
const syntax = syntaxTree4(view.state).resolveInner(pos, side);
|
|
1943
|
+
let link2 = null;
|
|
1944
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1945
|
+
link2 = node.name === "Link" ? node : null;
|
|
1946
|
+
}
|
|
1947
|
+
const url = link2 && link2.getChild("URL");
|
|
1948
|
+
if (!url || !link2) {
|
|
1949
|
+
return null;
|
|
1950
|
+
}
|
|
1951
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1952
|
+
return {
|
|
1953
|
+
pos: link2.from,
|
|
1954
|
+
end: link2.to,
|
|
1955
|
+
above: true,
|
|
1956
|
+
create: () => {
|
|
1957
|
+
const el = document.createElement("div");
|
|
1958
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1959
|
+
options.onHover(el, urlText);
|
|
1960
|
+
return {
|
|
1961
|
+
dom: el,
|
|
1962
|
+
offset: {
|
|
1963
|
+
x: 0,
|
|
1964
|
+
y: 4
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1968
|
+
};
|
|
1969
|
+
})
|
|
1970
|
+
);
|
|
1971
|
+
}
|
|
1972
|
+
return extensions;
|
|
1973
|
+
};
|
|
1974
|
+
var LinkButton = class extends WidgetType4 {
|
|
1975
|
+
constructor(_url, _onAttach) {
|
|
1976
|
+
super();
|
|
1977
|
+
this._url = _url;
|
|
1978
|
+
this._onAttach = _onAttach;
|
|
1979
|
+
}
|
|
1980
|
+
eq(other) {
|
|
1981
|
+
return this._url === other._url;
|
|
1982
|
+
}
|
|
1983
|
+
toDOM(view) {
|
|
1984
|
+
const el = document.createElement("span");
|
|
1985
|
+
this._onAttach(el, this._url);
|
|
1986
|
+
return el;
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
var LinkText = class extends WidgetType4 {
|
|
1990
|
+
constructor(_text, _url) {
|
|
1991
|
+
super();
|
|
1992
|
+
this._text = _text;
|
|
1993
|
+
this._url = _url;
|
|
1994
|
+
}
|
|
1995
|
+
eq(other) {
|
|
1996
|
+
return this._url === other._url;
|
|
1997
|
+
}
|
|
1998
|
+
toDOM(view) {
|
|
1999
|
+
const link2 = document.createElement("a");
|
|
2000
|
+
link2.setAttribute("class", "cm-link");
|
|
2001
|
+
link2.textContent = this._text;
|
|
2002
|
+
if (this._url) {
|
|
2003
|
+
link2.setAttribute("rel", "noreferrer");
|
|
2004
|
+
link2.setAttribute("target", "_blank");
|
|
2005
|
+
link2.href = this._url;
|
|
2006
|
+
} else {
|
|
2007
|
+
link2.onclick = () => {
|
|
2008
|
+
view.dispatch({
|
|
2009
|
+
selection: {
|
|
2010
|
+
anchor: view.posAtDOM(link2)
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
return link2;
|
|
2016
|
+
}
|
|
2017
|
+
};
|
|
2018
|
+
var buildDecorations4 = (view, options) => {
|
|
2019
|
+
const builder = new RangeSetBuilder3();
|
|
2020
|
+
const { state } = view;
|
|
2021
|
+
const cursor = state.selection.main.head;
|
|
2022
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2023
|
+
syntaxTree4(state).iterate({
|
|
2024
|
+
enter: (node) => {
|
|
2025
|
+
if (node.name === "Link") {
|
|
2026
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
2027
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
2028
|
+
const urlNode = node.node.getChild("URL");
|
|
2029
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2030
|
+
if (!url) {
|
|
2031
|
+
return false;
|
|
2032
|
+
}
|
|
2033
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2034
|
+
builder.add(node.from, node.to, Decoration7.replace({
|
|
2035
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
2036
|
+
}));
|
|
2037
|
+
}
|
|
2038
|
+
if (options.onRender) {
|
|
2039
|
+
builder.add(node.to, node.to, Decoration7.replace({
|
|
2040
|
+
widget: new LinkButton(url, options.onRender)
|
|
2041
|
+
}));
|
|
2042
|
+
}
|
|
2043
|
+
return false;
|
|
2044
|
+
}
|
|
2045
|
+
},
|
|
2046
|
+
from,
|
|
2047
|
+
to
|
|
2048
|
+
});
|
|
2049
|
+
}
|
|
2050
|
+
return builder.finish();
|
|
2051
|
+
};
|
|
2052
|
+
|
|
2053
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2054
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2055
|
+
import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField4 } from "@codemirror/state";
|
|
2056
|
+
import { Decoration as Decoration8, EditorView as EditorView11, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
2057
|
+
var table = (options = {}) => {
|
|
2058
|
+
return StateField4.define({
|
|
2059
|
+
create: (state) => update(state, options),
|
|
2060
|
+
update: (_, tr) => update(tr.state, options),
|
|
2061
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
2062
|
+
});
|
|
2063
|
+
};
|
|
2064
|
+
var update = (state, options) => {
|
|
2065
|
+
const builder = new RangeSetBuilder4();
|
|
2066
|
+
const cursor = state.selection.main.head;
|
|
2067
|
+
const tables = [];
|
|
2068
|
+
const getTable = () => tables[tables.length - 1];
|
|
2069
|
+
const getRow = () => {
|
|
2070
|
+
const table2 = getTable();
|
|
2061
2071
|
return table2.rows?.[table2.rows.length - 1];
|
|
2062
2072
|
};
|
|
2063
|
-
|
|
2073
|
+
syntaxTree5(state).iterate({
|
|
2064
2074
|
enter: (node) => {
|
|
2065
2075
|
switch (node.name) {
|
|
2066
2076
|
case "Table": {
|
|
@@ -2092,10 +2102,10 @@ var update = (state, options) => {
|
|
|
2092
2102
|
});
|
|
2093
2103
|
tables.forEach((table2) => {
|
|
2094
2104
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2095
|
-
hide && builder.add(table2.from, table2.to,
|
|
2105
|
+
hide && builder.add(table2.from, table2.to, Decoration8.replace({
|
|
2096
2106
|
widget: new TableWidget(table2)
|
|
2097
2107
|
}));
|
|
2098
|
-
builder.add(table2.from, table2.to,
|
|
2108
|
+
builder.add(table2.from, table2.to, Decoration8.mark({
|
|
2099
2109
|
class: "cm-table"
|
|
2100
2110
|
}));
|
|
2101
2111
|
});
|
|
@@ -2138,10 +2148,10 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2138
2148
|
}
|
|
2139
2149
|
};
|
|
2140
2150
|
|
|
2141
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2142
|
-
import { syntaxTree as
|
|
2143
|
-
import { RangeSetBuilder as
|
|
2144
|
-
import { EditorView as EditorView12, Decoration as
|
|
2151
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2152
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2153
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
2154
|
+
import { EditorView as EditorView12, Decoration as Decoration9, WidgetType as WidgetType6, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
|
2145
2155
|
var styles5 = EditorView12.baseTheme({
|
|
2146
2156
|
"& .cm-task": {
|
|
2147
2157
|
color: getToken("extend.colors.blue.500")
|
|
@@ -2188,23 +2198,23 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2188
2198
|
return false;
|
|
2189
2199
|
}
|
|
2190
2200
|
};
|
|
2191
|
-
var checkedDecoration =
|
|
2201
|
+
var checkedDecoration = Decoration9.replace({
|
|
2192
2202
|
widget: new CheckboxWidget(true)
|
|
2193
2203
|
});
|
|
2194
|
-
var uncheckedDecoration =
|
|
2204
|
+
var uncheckedDecoration = Decoration9.replace({
|
|
2195
2205
|
widget: new CheckboxWidget(false)
|
|
2196
2206
|
});
|
|
2197
|
-
var
|
|
2198
|
-
const builder = new
|
|
2207
|
+
var buildDecorations5 = (view) => {
|
|
2208
|
+
const builder = new RangeSetBuilder5();
|
|
2199
2209
|
const { state } = view;
|
|
2200
2210
|
const cursor = state.selection.main.head;
|
|
2201
2211
|
for (const { from, to } of view.visibleRanges) {
|
|
2202
|
-
|
|
2212
|
+
syntaxTree6(state).iterate({
|
|
2203
2213
|
enter: (node) => {
|
|
2204
2214
|
if (node.name === "TaskMarker") {
|
|
2205
2215
|
if (cursor < node.from || cursor > node.to) {
|
|
2206
2216
|
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2207
|
-
builder.add(node.from - 2, node.from - 1,
|
|
2217
|
+
builder.add(node.from - 2, node.from - 1, Decoration9.mark({
|
|
2208
2218
|
class: "cm-task"
|
|
2209
2219
|
}));
|
|
2210
2220
|
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
@@ -2219,13 +2229,13 @@ var buildDecorations4 = (view) => {
|
|
|
2219
2229
|
};
|
|
2220
2230
|
var tasklist = (options = {}) => {
|
|
2221
2231
|
return [
|
|
2222
|
-
|
|
2232
|
+
ViewPlugin7.fromClass(class {
|
|
2223
2233
|
constructor(view) {
|
|
2224
|
-
this.decorations =
|
|
2234
|
+
this.decorations = buildDecorations5(view);
|
|
2225
2235
|
}
|
|
2226
2236
|
update(update2) {
|
|
2227
2237
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2228
|
-
this.decorations =
|
|
2238
|
+
this.decorations = buildDecorations5(update2.view);
|
|
2229
2239
|
}
|
|
2230
2240
|
}
|
|
2231
2241
|
}, {
|
|
@@ -2235,6 +2245,40 @@ var tasklist = (options = {}) => {
|
|
|
2235
2245
|
];
|
|
2236
2246
|
};
|
|
2237
2247
|
|
|
2248
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
2249
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
2250
|
+
var mention = ({ onSearch }) => {
|
|
2251
|
+
return autocompletion2({
|
|
2252
|
+
// TODO(burdon): Not working.
|
|
2253
|
+
activateOnTyping: true,
|
|
2254
|
+
// activateOnTypingDelay: 100,
|
|
2255
|
+
// selectOnOpen: true,
|
|
2256
|
+
closeOnBlur: false,
|
|
2257
|
+
// defaultKeymap: false,
|
|
2258
|
+
icons: false,
|
|
2259
|
+
override: [
|
|
2260
|
+
(context) => {
|
|
2261
|
+
console.log(context);
|
|
2262
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
2263
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
2264
|
+
return null;
|
|
2265
|
+
}
|
|
2266
|
+
return {
|
|
2267
|
+
from: match.from,
|
|
2268
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
2269
|
+
label: `@${value}`
|
|
2270
|
+
}))
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
]
|
|
2274
|
+
});
|
|
2275
|
+
};
|
|
2276
|
+
|
|
2277
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2278
|
+
var outliner = (options = {}) => {
|
|
2279
|
+
return [];
|
|
2280
|
+
};
|
|
2281
|
+
|
|
2238
2282
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2239
2283
|
import { keymap as keymap5 } from "@codemirror/view";
|
|
2240
2284
|
var defaultItems = [
|
|
@@ -2913,6 +2957,7 @@ export {
|
|
|
2913
2957
|
defaultTextSlots,
|
|
2914
2958
|
defaultTheme,
|
|
2915
2959
|
getToken,
|
|
2960
|
+
heading2 as heading,
|
|
2916
2961
|
hr,
|
|
2917
2962
|
image,
|
|
2918
2963
|
link,
|