@dxos/react-ui-editor 0.4.5-main.f8d6c4e → 0.4.5
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 +464 -572
- 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 +7 -5
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +2 -0
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts +2 -0
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts +2 -0
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +2 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/cursor-line-margin.d.ts +8 -0
- package/dist/types/src/extensions/cursor-line-margin.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +1 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts +5 -0
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -4
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts +1 -11
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/layout.d.ts +2 -2
- package/dist/types/src/styles/layout.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/package.json +29 -26
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +29 -37
- package/src/components/TextEditor/hooks.stories.tsx +5 -17
- package/src/components/Toolbar/Toolbar.stories.tsx +4 -7
- package/src/components/Toolbar/Toolbar.tsx +79 -47
- package/src/extensions/cursor-line-margin.ts +92 -0
- package/src/extensions/index.ts +1 -0
- package/src/extensions/markdown/decorate.ts +301 -0
- package/src/extensions/markdown/formatting.test.ts +17 -0
- package/src/extensions/markdown/formatting.ts +67 -76
- package/src/extensions/markdown/index.ts +1 -4
- package/src/extensions/markdown/link.ts +23 -185
- package/src/index.ts +2 -0
- package/src/styles/layout.ts +3 -2
- package/src/translations.ts +5 -3
- package/dist/types/src/extensions/markdown/code.d.ts +0 -2
- package/dist/types/src/extensions/markdown/code.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/heading.d.ts +0 -6
- package/dist/types/src/extensions/markdown/heading.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/hr.d.ts +0 -2
- package/dist/types/src/extensions/markdown/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/tasklist.d.ts +0 -3
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +0 -1
- package/src/extensions/markdown/code.ts +0 -162
- package/src/extensions/markdown/heading.ts +0 -59
- package/src/extensions/markdown/hr.ts +0 -71
- package/src/extensions/markdown/tasklist.ts +0 -110
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
// packages/ui/react-ui-editor/src/translations.ts
|
|
2
|
+
var translationKey = "react-ui-editor";
|
|
3
|
+
var translations_default = [
|
|
4
|
+
{
|
|
5
|
+
"en-US": {
|
|
6
|
+
[translationKey]: {
|
|
7
|
+
"strong label": "Bold",
|
|
8
|
+
"emphasis label": "Italics",
|
|
9
|
+
"strikethrough label": "Strikethrough",
|
|
10
|
+
"code label": "Code",
|
|
11
|
+
"link label": "Link",
|
|
12
|
+
"list-bullet label": "Bullet list",
|
|
13
|
+
"list-ordered label": "Numbered list",
|
|
14
|
+
"list-task label": "Task list",
|
|
15
|
+
"blockquote label": "Block quote",
|
|
16
|
+
"codeblock label": "Code block",
|
|
17
|
+
"comment label": "Create comment",
|
|
18
|
+
"heading label": "Heading level",
|
|
19
|
+
"table label": "Create table"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
];
|
|
24
|
+
|
|
1
25
|
// packages/ui/react-ui-editor/src/index.ts
|
|
2
26
|
import { keymap as keymap8 } from "@codemirror/view";
|
|
3
27
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
@@ -8,7 +32,7 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
8
32
|
|
|
9
33
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
10
34
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
11
|
-
import { EditorView as
|
|
35
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
12
36
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
13
37
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
38
|
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2, useMemo as useMemo2 } from "react";
|
|
@@ -102,8 +126,8 @@ var annotations = (options = {}) => {
|
|
|
102
126
|
annotationsState
|
|
103
127
|
], (state) => {
|
|
104
128
|
const annotations2 = state.field(annotationsState);
|
|
105
|
-
const decorations = annotations2.map((
|
|
106
|
-
const range = Cursor.getRangeFromCursor(state,
|
|
129
|
+
const decorations = annotations2.map((annotation2) => {
|
|
130
|
+
const range = Cursor.getRangeFromCursor(state, annotation2.cursor);
|
|
107
131
|
return range && annotationMark.range(range.from, range.to);
|
|
108
132
|
}).filter(isNotFalsy);
|
|
109
133
|
return Decoration.set(decorations);
|
|
@@ -765,10 +789,10 @@ var blast = (options = defaultOptions) => {
|
|
|
765
789
|
const getPoint = (view, pos) => {
|
|
766
790
|
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
767
791
|
const element = document.elementFromPoint(x, y);
|
|
768
|
-
const { offsetLeft: left = 0, offsetTop:
|
|
792
|
+
const { offsetLeft: left = 0, offsetTop: top = 0 } = view.scrollDOM.parentElement ?? {};
|
|
769
793
|
const point = {
|
|
770
794
|
x: x - left,
|
|
771
|
-
y: y -
|
|
795
|
+
y: y - top
|
|
772
796
|
};
|
|
773
797
|
return {
|
|
774
798
|
element,
|
|
@@ -1116,8 +1140,8 @@ var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue)
|
|
|
1116
1140
|
|
|
1117
1141
|
// packages/ui/react-ui-editor/src/styles/layout.ts
|
|
1118
1142
|
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
|
1119
|
-
var editorFillLayoutRoot = "
|
|
1120
|
-
var editorFillLayoutEditor = "
|
|
1143
|
+
var editorFillLayoutRoot = "bs-full overflow-hidden grid";
|
|
1144
|
+
var editorFillLayoutEditor = "bs-full overflow-hidden [&>.cm-scroller]:bs-full [&>.cm-scroller]:overflow-y-auto";
|
|
1121
1145
|
var editorHalfViewportOverscrollContent = "after:block after:min-bs-[50dvh] after:pointer-events-none";
|
|
1122
1146
|
|
|
1123
1147
|
// packages/ui/react-ui-editor/src/util.ts
|
|
@@ -1553,15 +1577,66 @@ var useComments = (view, id, comments2 = []) => {
|
|
|
1553
1577
|
]);
|
|
1554
1578
|
};
|
|
1555
1579
|
|
|
1556
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1580
|
+
// packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts
|
|
1581
|
+
import { Facet as Facet4, Transaction } from "@codemirror/state";
|
|
1557
1582
|
import { EditorView as EditorView7 } from "@codemirror/view";
|
|
1583
|
+
var cursorLineMarginFacet = Facet4.define({
|
|
1584
|
+
combine: (input) => input[0] ?? 3
|
|
1585
|
+
});
|
|
1586
|
+
var annotation = "cursorLineMargin";
|
|
1587
|
+
var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
|
|
1588
|
+
var cursorLineMargin = EditorView7.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
|
|
1589
|
+
if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
const s = state;
|
|
1593
|
+
const { main } = s.selection;
|
|
1594
|
+
const cursorLineMargin2 = s.facet(cursorLineMarginFacet);
|
|
1595
|
+
const rect = view.dom.getBoundingClientRect();
|
|
1596
|
+
const viewportTop = rect.top - view.documentTop;
|
|
1597
|
+
const viewportBottom = rect.bottom - view.documentTop;
|
|
1598
|
+
const mainLine = lineAtPos(s, main.head);
|
|
1599
|
+
const _visTopLine = lineAtPos(s, view.lineBlockAtHeight(viewportTop).from);
|
|
1600
|
+
const botLineBlk = view.lineBlockAtHeight(viewportBottom);
|
|
1601
|
+
const visBotLineDoc = lineAtPos(s, Math.min(botLineBlk.to, s.doc.length));
|
|
1602
|
+
const visBotLine = botLineBlk.bottom >= viewportBottom ? visBotLineDoc : visBotLineDoc + Math.floor((viewportBottom - botLineBlk.bottom) / view.defaultLineHeight);
|
|
1603
|
+
const needsScrollTop = false;
|
|
1604
|
+
const needsScrollBot = mainLine >= visBotLine - cursorLineMargin2;
|
|
1605
|
+
if (needsScrollTop && needsScrollBot) {
|
|
1606
|
+
console.warn("is cursorScrollMargin too large for the editor size?");
|
|
1607
|
+
return;
|
|
1608
|
+
}
|
|
1609
|
+
if (!needsScrollTop && !needsScrollBot) {
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
if (selectionSet) {
|
|
1613
|
+
const { head } = startState.selection.main;
|
|
1614
|
+
const oldMainLine = lineAtPos(startState, head);
|
|
1615
|
+
if (needsScrollTop && oldMainLine < mainLine) {
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
if (needsScrollBot && oldMainLine > mainLine) {
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
view.dispatch({
|
|
1623
|
+
annotations: Transaction.userEvent.of(annotation),
|
|
1624
|
+
effects: EditorView7.scrollIntoView(s.selection.main.head, {
|
|
1625
|
+
y: needsScrollTop ? "start" : "end",
|
|
1626
|
+
yMargin: view.defaultLineHeight * cursorLineMargin2
|
|
1627
|
+
})
|
|
1628
|
+
});
|
|
1629
|
+
});
|
|
1630
|
+
|
|
1631
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1632
|
+
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1558
1633
|
var listener = ({ onFocus, onChange }) => {
|
|
1559
1634
|
const extensions = [];
|
|
1560
|
-
onFocus && extensions.push(
|
|
1635
|
+
onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
|
|
1561
1636
|
onFocus(focused);
|
|
1562
1637
|
return null;
|
|
1563
1638
|
}));
|
|
1564
|
-
onChange && extensions.push(
|
|
1639
|
+
onChange && extensions.push(EditorView8.updateListener.of((update2) => {
|
|
1565
1640
|
onChange(update2.state.doc.toString());
|
|
1566
1641
|
}));
|
|
1567
1642
|
return extensions;
|
|
@@ -1576,7 +1651,7 @@ import { languages } from "@codemirror/language-data";
|
|
|
1576
1651
|
import { searchKeymap } from "@codemirror/search";
|
|
1577
1652
|
import { EditorState } from "@codemirror/state";
|
|
1578
1653
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1579
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1654
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1580
1655
|
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
1581
1656
|
|
|
1582
1657
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
@@ -1770,7 +1845,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1770
1845
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1771
1846
|
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
1772
1847
|
return [
|
|
1773
|
-
lineWrapping &&
|
|
1848
|
+
lineWrapping && EditorView9.lineWrapping,
|
|
1774
1849
|
EditorState.allowMultipleSelections.of(true),
|
|
1775
1850
|
EditorState.tabSize.of(2),
|
|
1776
1851
|
// https://github.com/codemirror/basic-setup
|
|
@@ -1820,12 +1895,207 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
|
|
|
1820
1895
|
].filter(isNotFalsy3);
|
|
1821
1896
|
};
|
|
1822
1897
|
|
|
1823
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
|
1898
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
1824
1899
|
import { syntaxTree } from "@codemirror/language";
|
|
1825
1900
|
import { RangeSetBuilder } from "@codemirror/state";
|
|
1826
|
-
import {
|
|
1901
|
+
import { EditorView as EditorView10, Decoration as Decoration4, WidgetType as WidgetType2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
|
|
1827
1902
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1828
|
-
var
|
|
1903
|
+
var FencedCodeBoundary = class extends WidgetType2 {
|
|
1904
|
+
constructor(_className) {
|
|
1905
|
+
super();
|
|
1906
|
+
this._className = _className;
|
|
1907
|
+
}
|
|
1908
|
+
toDOM() {
|
|
1909
|
+
const el = document.createElement("span");
|
|
1910
|
+
el.innerHTML = " ";
|
|
1911
|
+
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1912
|
+
return el;
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1916
|
+
toDOM() {
|
|
1917
|
+
const el = document.createElement("span");
|
|
1918
|
+
el.className = "cm-hr";
|
|
1919
|
+
return el;
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
var LinkButton = class extends WidgetType2 {
|
|
1923
|
+
constructor(url, render) {
|
|
1924
|
+
super();
|
|
1925
|
+
this.url = url;
|
|
1926
|
+
this.render = render;
|
|
1927
|
+
}
|
|
1928
|
+
eq(other) {
|
|
1929
|
+
return this.url === other.url;
|
|
1930
|
+
}
|
|
1931
|
+
toDOM(view) {
|
|
1932
|
+
const el = document.createElement("span");
|
|
1933
|
+
this.render(el, this.url);
|
|
1934
|
+
return el;
|
|
1935
|
+
}
|
|
1936
|
+
};
|
|
1937
|
+
var CheckboxWidget = class extends WidgetType2 {
|
|
1938
|
+
constructor(_checked) {
|
|
1939
|
+
super();
|
|
1940
|
+
this._checked = _checked;
|
|
1941
|
+
}
|
|
1942
|
+
eq(other) {
|
|
1943
|
+
return this._checked === other._checked;
|
|
1944
|
+
}
|
|
1945
|
+
toDOM(view) {
|
|
1946
|
+
const input = document.createElement("input");
|
|
1947
|
+
input.className = "cm-task-checkbox";
|
|
1948
|
+
input.type = "checkbox";
|
|
1949
|
+
input.checked = this._checked;
|
|
1950
|
+
if (view.state.readOnly) {
|
|
1951
|
+
input.setAttribute("disabled", "true");
|
|
1952
|
+
} else {
|
|
1953
|
+
input.onmousedown = (event) => {
|
|
1954
|
+
const pos = view.posAtDOM(input);
|
|
1955
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
1956
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
1957
|
+
view.dispatch({
|
|
1958
|
+
changes: {
|
|
1959
|
+
from: pos + 1,
|
|
1960
|
+
to: pos + 2,
|
|
1961
|
+
insert: this._checked ? " " : "x"
|
|
1962
|
+
}
|
|
1963
|
+
});
|
|
1964
|
+
event.preventDefault();
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1968
|
+
return input;
|
|
1969
|
+
}
|
|
1970
|
+
ignoreEvent() {
|
|
1971
|
+
return false;
|
|
1972
|
+
}
|
|
1973
|
+
};
|
|
1974
|
+
var hide = Decoration4.replace({});
|
|
1975
|
+
var fencedCodeTop = Decoration4.replace({
|
|
1976
|
+
widget: new FencedCodeBoundary("cm-codeblock-end cm-codeblock-first")
|
|
1977
|
+
});
|
|
1978
|
+
var fencedCodeBottom = Decoration4.replace({
|
|
1979
|
+
widget: new FencedCodeBoundary("cm-codeblock-end cm-codeblock-last")
|
|
1980
|
+
});
|
|
1981
|
+
var horizontalRule = Decoration4.replace({
|
|
1982
|
+
widget: new HorizontalRuleWidget()
|
|
1983
|
+
});
|
|
1984
|
+
var checkedTask = Decoration4.replace({
|
|
1985
|
+
widget: new CheckboxWidget(true)
|
|
1986
|
+
});
|
|
1987
|
+
var uncheckedTask = Decoration4.replace({
|
|
1988
|
+
widget: new CheckboxWidget(false)
|
|
1989
|
+
});
|
|
1990
|
+
var editingRange = (state, range) => {
|
|
1991
|
+
const { readOnly, selection: { main: { head } } } = state;
|
|
1992
|
+
return !readOnly && head >= range.from && head <= range.to;
|
|
1993
|
+
};
|
|
1994
|
+
var MarksByParent = /* @__PURE__ */ new Set([
|
|
1995
|
+
"CodeMark",
|
|
1996
|
+
"EmphasisMark",
|
|
1997
|
+
"StrikethroughMark",
|
|
1998
|
+
"SubscriptMark",
|
|
1999
|
+
"SuperscriptMark"
|
|
2000
|
+
]);
|
|
2001
|
+
var buildDecorations = (view, options) => {
|
|
2002
|
+
const builder = new RangeSetBuilder();
|
|
2003
|
+
const { state } = view;
|
|
2004
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2005
|
+
syntaxTree(state).iterate({
|
|
2006
|
+
from,
|
|
2007
|
+
to,
|
|
2008
|
+
enter: (node) => {
|
|
2009
|
+
if (node.name === "FencedCode") {
|
|
2010
|
+
const editing = editingRange(state, node);
|
|
2011
|
+
for (const block of view.viewportLineBlocks) {
|
|
2012
|
+
if (block.to < node.from) {
|
|
2013
|
+
continue;
|
|
2014
|
+
}
|
|
2015
|
+
if (block.from > node.to) {
|
|
2016
|
+
break;
|
|
2017
|
+
}
|
|
2018
|
+
const first = block.from <= node.from;
|
|
2019
|
+
const last = block.to >= node.to;
|
|
2020
|
+
if (!editing && (first || last)) {
|
|
2021
|
+
builder.add(block.from, block.to, first ? fencedCodeTop : fencedCodeBottom);
|
|
2022
|
+
} else {
|
|
2023
|
+
builder.add(block.from, block.from, Decoration4.line({
|
|
2024
|
+
class: mx2("cm-code cm-codeblock-line", first && "cm-codeblock-first", last && "cm-codeblock-last")
|
|
2025
|
+
}));
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
return false;
|
|
2029
|
+
} else if (node.name === "Link") {
|
|
2030
|
+
const marks = node.node.getChildren("LinkMark");
|
|
2031
|
+
const urlNode = node.node.getChild("URL");
|
|
2032
|
+
const editing = editingRange(state, node);
|
|
2033
|
+
if (urlNode && marks.length >= 2) {
|
|
2034
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
2035
|
+
if (!editing) {
|
|
2036
|
+
builder.add(node.from, marks[0].to, hide);
|
|
2037
|
+
}
|
|
2038
|
+
builder.add(marks[0].to, marks[1].from, Decoration4.mark({
|
|
2039
|
+
tagName: "a",
|
|
2040
|
+
attributes: {
|
|
2041
|
+
class: "cm-link",
|
|
2042
|
+
href: url,
|
|
2043
|
+
rel: "noreferrer",
|
|
2044
|
+
target: "_blank"
|
|
2045
|
+
}
|
|
2046
|
+
}));
|
|
2047
|
+
if (!editing) {
|
|
2048
|
+
builder.add(marks[1].from, node.to, options.renderLinkButton ? Decoration4.replace({
|
|
2049
|
+
widget: new LinkButton(url, options.renderLinkButton)
|
|
2050
|
+
}) : hide);
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
} else if (node.name === "HeaderMark") {
|
|
2054
|
+
const parent = node.node.parent;
|
|
2055
|
+
if (/^ATX/.test(parent.name) && !editingRange(state, state.doc.lineAt(node.from))) {
|
|
2056
|
+
const next = state.doc.sliceString(node.to, node.to + 1);
|
|
2057
|
+
builder.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
2058
|
+
}
|
|
2059
|
+
} else if (node.name === "HorizontalRule") {
|
|
2060
|
+
if (!editingRange(state, node)) {
|
|
2061
|
+
builder.add(node.from, node.to, horizontalRule);
|
|
2062
|
+
}
|
|
2063
|
+
} else if (node.name === "TaskMarker") {
|
|
2064
|
+
if (!editingRange(state, node)) {
|
|
2065
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2066
|
+
builder.add(node.from - 2, node.from - 1, Decoration4.mark({
|
|
2067
|
+
class: "cm-task"
|
|
2068
|
+
}));
|
|
2069
|
+
builder.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
2070
|
+
}
|
|
2071
|
+
} else if (MarksByParent.has(node.name)) {
|
|
2072
|
+
if (!editingRange(state, node.node.parent)) {
|
|
2073
|
+
builder.add(node.from, node.to, hide);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
});
|
|
2078
|
+
}
|
|
2079
|
+
return builder.finish();
|
|
2080
|
+
};
|
|
2081
|
+
var decorateMarkdown = (options = {}) => {
|
|
2082
|
+
return [
|
|
2083
|
+
ViewPlugin3.fromClass(class {
|
|
2084
|
+
constructor(view) {
|
|
2085
|
+
this.decorations = buildDecorations(view, options);
|
|
2086
|
+
}
|
|
2087
|
+
update(update2) {
|
|
2088
|
+
if (update2.docChanged || update2.selectionSet || update2.viewportChanged) {
|
|
2089
|
+
this.decorations = buildDecorations(update2.view, options);
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
}, {
|
|
2093
|
+
decorations: (value) => value.decorations
|
|
2094
|
+
}),
|
|
2095
|
+
formattingStyles
|
|
2096
|
+
];
|
|
2097
|
+
};
|
|
2098
|
+
var formattingStyles = EditorView10.baseTheme({
|
|
1829
2099
|
"& .cm-code": {
|
|
1830
2100
|
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1831
2101
|
},
|
|
@@ -1873,82 +2143,28 @@ var styles4 = EditorView9.baseTheme({
|
|
|
1873
2143
|
"&::after": {
|
|
1874
2144
|
background: getToken("extend.semanticColors.input.dark")
|
|
1875
2145
|
}
|
|
2146
|
+
},
|
|
2147
|
+
"& .cm-hr": {
|
|
2148
|
+
display: "inline-block",
|
|
2149
|
+
width: "100%",
|
|
2150
|
+
height: "0",
|
|
2151
|
+
verticalAlign: "middle",
|
|
2152
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2153
|
+
},
|
|
2154
|
+
"& .cm-task": {
|
|
2155
|
+
color: getToken("extend.colors.blue.500")
|
|
2156
|
+
},
|
|
2157
|
+
"& .cm-task-checkbox": {
|
|
2158
|
+
marginLeft: "4px",
|
|
2159
|
+
marginRight: "4px"
|
|
1876
2160
|
}
|
|
1877
2161
|
});
|
|
1878
|
-
var getLineRange = (lines, from, to) => {
|
|
1879
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1880
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1881
|
-
return [
|
|
1882
|
-
start,
|
|
1883
|
-
end
|
|
1884
|
-
];
|
|
1885
|
-
};
|
|
1886
|
-
var LineWidget = class extends WidgetType2 {
|
|
1887
|
-
constructor(_className) {
|
|
1888
|
-
super();
|
|
1889
|
-
this._className = _className;
|
|
1890
|
-
}
|
|
1891
|
-
toDOM() {
|
|
1892
|
-
const el = document.createElement("span");
|
|
1893
|
-
el.innerHTML = " ";
|
|
1894
|
-
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1895
|
-
return el;
|
|
1896
|
-
}
|
|
1897
|
-
};
|
|
1898
|
-
var top = new LineWidget("cm-codeblock-end cm-codeblock-first");
|
|
1899
|
-
var bottom = new LineWidget("cm-codeblock-end cm-codeblock-last");
|
|
1900
|
-
var buildDecorations = (view) => {
|
|
1901
|
-
const builder = new RangeSetBuilder();
|
|
1902
|
-
const { state } = view;
|
|
1903
|
-
const blocks = view.viewportLineBlocks;
|
|
1904
|
-
const cursor = state.selection.main.head;
|
|
1905
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1906
|
-
syntaxTree(state).iterate({
|
|
1907
|
-
enter: (node) => {
|
|
1908
|
-
if (node.name === "FencedCode") {
|
|
1909
|
-
const editing = !view.state.readOnly && cursor >= node.from && cursor <= node.to;
|
|
1910
|
-
const range = getLineRange(blocks, node.from, node.to);
|
|
1911
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1912
|
-
const block = blocks[i];
|
|
1913
|
-
if (!editing && (i === range[0] || i === range[1])) {
|
|
1914
|
-
builder.add(block.from, block.to, Decoration4.replace({
|
|
1915
|
-
widget: i === range[0] ? top : bottom
|
|
1916
|
-
}));
|
|
1917
|
-
} else {
|
|
1918
|
-
builder.add(block.from, block.from, Decoration4.line({
|
|
1919
|
-
class: mx2("cm-code cm-codeblock-line", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1920
|
-
}));
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
1923
|
-
}
|
|
1924
|
-
},
|
|
1925
|
-
from,
|
|
1926
|
-
to
|
|
1927
|
-
});
|
|
1928
|
-
}
|
|
1929
|
-
return builder.finish();
|
|
1930
|
-
};
|
|
1931
|
-
var code2 = () => {
|
|
1932
|
-
return [
|
|
1933
|
-
ViewPlugin3.fromClass(class {
|
|
1934
|
-
constructor(view) {
|
|
1935
|
-
this.decorations = buildDecorations(view);
|
|
1936
|
-
}
|
|
1937
|
-
update(update2) {
|
|
1938
|
-
this.decorations = buildDecorations(update2.view);
|
|
1939
|
-
}
|
|
1940
|
-
}, {
|
|
1941
|
-
decorations: (value) => value.decorations
|
|
1942
|
-
}),
|
|
1943
|
-
styles4
|
|
1944
|
-
];
|
|
1945
|
-
};
|
|
1946
2162
|
|
|
1947
2163
|
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1948
2164
|
import { snippet } from "@codemirror/autocomplete";
|
|
1949
2165
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1950
|
-
import {
|
|
1951
|
-
import {
|
|
2166
|
+
import { EditorSelection } from "@codemirror/state";
|
|
2167
|
+
import { EditorView as EditorView11, keymap as keymap5 } from "@codemirror/view";
|
|
1952
2168
|
import { useState, useMemo } from "react";
|
|
1953
2169
|
var compareFormatting = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
|
|
1954
2170
|
var Inline;
|
|
@@ -1969,6 +2185,7 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
1969
2185
|
const changes = [];
|
|
1970
2186
|
let prevBlock = -1;
|
|
1971
2187
|
for (const range of ranges) {
|
|
2188
|
+
let sawBlock = false;
|
|
1972
2189
|
syntaxTree2(state).iterate({
|
|
1973
2190
|
from: range.from,
|
|
1974
2191
|
to: range.to,
|
|
@@ -1976,6 +2193,7 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
1976
2193
|
if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
|
|
1977
2194
|
return;
|
|
1978
2195
|
}
|
|
2196
|
+
sawBlock = true;
|
|
1979
2197
|
prevBlock = node.from;
|
|
1980
2198
|
const blockType = Textblocks[node.name];
|
|
1981
2199
|
const isHeading = /heading(\d)/.exec(blockType);
|
|
@@ -2020,12 +2238,22 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
2020
2238
|
}
|
|
2021
2239
|
}
|
|
2022
2240
|
});
|
|
2241
|
+
let line;
|
|
2242
|
+
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state.doc.lineAt(range.from)).text)) {
|
|
2243
|
+
changes.push({
|
|
2244
|
+
from: line.from,
|
|
2245
|
+
to: line.to,
|
|
2246
|
+
insert: "#".repeat(level) + " "
|
|
2247
|
+
});
|
|
2248
|
+
}
|
|
2023
2249
|
}
|
|
2024
2250
|
if (!changes.length) {
|
|
2025
2251
|
return false;
|
|
2026
2252
|
}
|
|
2253
|
+
const changeSet = state.changes(changes);
|
|
2027
2254
|
dispatch(state.update({
|
|
2028
|
-
changes,
|
|
2255
|
+
changes: changeSet,
|
|
2256
|
+
selection: state.selection.map(changeSet, 1),
|
|
2029
2257
|
userEvent: "format.setHeading",
|
|
2030
2258
|
scrollIntoView: true
|
|
2031
2259
|
}));
|
|
@@ -2097,10 +2325,16 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2097
2325
|
const closeStart = node.to - size;
|
|
2098
2326
|
if (markType === type) {
|
|
2099
2327
|
if (openEnd <= from && closeStart >= from) {
|
|
2100
|
-
startCovered = openEnd === from
|
|
2328
|
+
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2329
|
+
from: node.from,
|
|
2330
|
+
to: openEnd
|
|
2331
|
+
} : true;
|
|
2101
2332
|
}
|
|
2102
2333
|
if (openEnd <= to && closeStart >= to) {
|
|
2103
|
-
endCovered = closeStart === to
|
|
2334
|
+
endCovered = !enable && closeStart === skipMarkers(to, node.node, 1, closeStart) ? {
|
|
2335
|
+
from: closeStart,
|
|
2336
|
+
to: node.to
|
|
2337
|
+
} : true;
|
|
2104
2338
|
}
|
|
2105
2339
|
}
|
|
2106
2340
|
if (markType === type || type === 3 && enable) {
|
|
@@ -2149,22 +2383,16 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2149
2383
|
});
|
|
2150
2384
|
}
|
|
2151
2385
|
} else {
|
|
2152
|
-
if (startCovered === "
|
|
2153
|
-
changes2.push(
|
|
2154
|
-
from: from - marker.length,
|
|
2155
|
-
to: from
|
|
2156
|
-
});
|
|
2386
|
+
if (typeof startCovered === "object") {
|
|
2387
|
+
changes2.push(startCovered);
|
|
2157
2388
|
} else if (startCovered) {
|
|
2158
2389
|
changes2.push({
|
|
2159
2390
|
from: skipSpaces(rangeStart, state.doc, -1, blockStart),
|
|
2160
2391
|
insert: marker
|
|
2161
2392
|
});
|
|
2162
2393
|
}
|
|
2163
|
-
if (endCovered === "
|
|
2164
|
-
changes2.push(
|
|
2165
|
-
from: to,
|
|
2166
|
-
to: to + marker.length
|
|
2167
|
-
});
|
|
2394
|
+
if (typeof endCovered === "object") {
|
|
2395
|
+
changes2.push(endCovered);
|
|
2168
2396
|
} else if (endCovered) {
|
|
2169
2397
|
changes2.push({
|
|
2170
2398
|
from: skipSpaces(rangeEnd, state.doc, 1, blockEnd),
|
|
@@ -2175,6 +2403,15 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2175
2403
|
}
|
|
2176
2404
|
}
|
|
2177
2405
|
});
|
|
2406
|
+
if (blockStart < 0 && range.empty && enable && !/\S/.test(state.doc.lineAt(range.from).text)) {
|
|
2407
|
+
return {
|
|
2408
|
+
changes: {
|
|
2409
|
+
from: range.head,
|
|
2410
|
+
insert: marker + marker
|
|
2411
|
+
},
|
|
2412
|
+
range: EditorSelection.cursor(range.head + marker.length)
|
|
2413
|
+
};
|
|
2414
|
+
}
|
|
2178
2415
|
const changeSet = state.changes(changes2.concat(changesAtEnd));
|
|
2179
2416
|
return {
|
|
2180
2417
|
changes: changeSet,
|
|
@@ -2220,6 +2457,19 @@ var skipSpaces = (pos, doc, dir, limit) => {
|
|
|
2220
2457
|
}
|
|
2221
2458
|
return pos;
|
|
2222
2459
|
};
|
|
2460
|
+
var skipMarkers = (pos, tree, dir, limit) => {
|
|
2461
|
+
for (; ; ) {
|
|
2462
|
+
const next = tree.resolve(pos, dir);
|
|
2463
|
+
if (!IgnoreInline.has(next.name)) {
|
|
2464
|
+
return pos;
|
|
2465
|
+
}
|
|
2466
|
+
const moveTo = dir < 0 ? next.from : next.to;
|
|
2467
|
+
if (limit != null && (dir < 0 ? moveTo < limit : moveTo > limit)) {
|
|
2468
|
+
return pos;
|
|
2469
|
+
}
|
|
2470
|
+
pos = moveTo;
|
|
2471
|
+
}
|
|
2472
|
+
};
|
|
2223
2473
|
var snippets = {
|
|
2224
2474
|
codeblock: snippet([
|
|
2225
2475
|
//
|
|
@@ -2498,8 +2748,10 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
2498
2748
|
renumberListItems(next.firstChild, last.counter + 1, changes, state.doc);
|
|
2499
2749
|
}
|
|
2500
2750
|
}
|
|
2751
|
+
const changeSet = state.changes(changes);
|
|
2501
2752
|
dispatch(state.update({
|
|
2502
|
-
changes,
|
|
2753
|
+
changes: changeSet,
|
|
2754
|
+
selection: state.selection.map(changeSet, 1),
|
|
2503
2755
|
userEvent: "format.list.add",
|
|
2504
2756
|
scrollIntoView: true
|
|
2505
2757
|
}));
|
|
@@ -2593,6 +2845,7 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2593
2845
|
const lines = [];
|
|
2594
2846
|
let lastBlock = -1;
|
|
2595
2847
|
for (const { from, to } of state.selection.ranges) {
|
|
2848
|
+
const sawBlock = false;
|
|
2596
2849
|
syntaxTree2(state).iterate({
|
|
2597
2850
|
from,
|
|
2598
2851
|
to,
|
|
@@ -2602,9 +2855,9 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2602
2855
|
return false;
|
|
2603
2856
|
}
|
|
2604
2857
|
lastBlock = node.from;
|
|
2605
|
-
let
|
|
2606
|
-
if (
|
|
2607
|
-
const prevLine = state.doc.line(
|
|
2858
|
+
let line2 = state.doc.lineAt(node.from);
|
|
2859
|
+
if (line2.number > 1) {
|
|
2860
|
+
const prevLine = state.doc.line(line2.number - 1);
|
|
2608
2861
|
if (/^[>\s]*$/.test(prevLine.text)) {
|
|
2609
2862
|
if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
|
|
2610
2863
|
lines.push(prevLine);
|
|
@@ -2612,14 +2865,14 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2612
2865
|
}
|
|
2613
2866
|
}
|
|
2614
2867
|
for (; ; ) {
|
|
2615
|
-
lines.push(
|
|
2616
|
-
if (
|
|
2868
|
+
lines.push(line2);
|
|
2869
|
+
if (line2.to >= node.to) {
|
|
2617
2870
|
break;
|
|
2618
2871
|
}
|
|
2619
|
-
|
|
2872
|
+
line2 = state.doc.line(line2.number + 1);
|
|
2620
2873
|
}
|
|
2621
|
-
if (!enable &&
|
|
2622
|
-
const nextLine = state.doc.line(
|
|
2874
|
+
if (!enable && line2.number < state.doc.lines) {
|
|
2875
|
+
const nextLine = state.doc.line(line2.number + 1);
|
|
2623
2876
|
if (/^[>\s]*$/.test(nextLine.text)) {
|
|
2624
2877
|
lines.push(nextLine);
|
|
2625
2878
|
}
|
|
@@ -2628,6 +2881,10 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2628
2881
|
}
|
|
2629
2882
|
}
|
|
2630
2883
|
});
|
|
2884
|
+
let line;
|
|
2885
|
+
if (!sawBlock && enable && from === to && !/\S/.test((line = state.doc.lineAt(from)).text)) {
|
|
2886
|
+
lines.push(line);
|
|
2887
|
+
}
|
|
2631
2888
|
}
|
|
2632
2889
|
const changes = [];
|
|
2633
2890
|
for (const line of lines) {
|
|
@@ -2649,8 +2906,10 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2649
2906
|
if (!changes.length) {
|
|
2650
2907
|
return false;
|
|
2651
2908
|
}
|
|
2909
|
+
const changeSet = state.changes(changes);
|
|
2652
2910
|
dispatch(state.update({
|
|
2653
|
-
changes,
|
|
2911
|
+
changes: changeSet,
|
|
2912
|
+
selection: state.selection.map(changeSet, 1),
|
|
2654
2913
|
userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
|
|
2655
2914
|
scrollIntoView: true
|
|
2656
2915
|
}));
|
|
@@ -2782,56 +3041,7 @@ var formatting = (options = {}) => {
|
|
|
2782
3041
|
key: "meta-b",
|
|
2783
3042
|
run: toggleStrong
|
|
2784
3043
|
}
|
|
2785
|
-
])
|
|
2786
|
-
styling()
|
|
2787
|
-
];
|
|
2788
|
-
};
|
|
2789
|
-
var styling = () => {
|
|
2790
|
-
const buildDecorations7 = (view) => {
|
|
2791
|
-
const builder = new RangeSetBuilder2();
|
|
2792
|
-
const { state } = view;
|
|
2793
|
-
const cursor = state.selection.main.head;
|
|
2794
|
-
const replace = (node, marks) => {
|
|
2795
|
-
if (cursor <= node.from || cursor >= node.to) {
|
|
2796
|
-
for (const mark2 of marks) {
|
|
2797
|
-
builder.add(mark2.from, mark2.to, Decoration5.replace({}));
|
|
2798
|
-
}
|
|
2799
|
-
}
|
|
2800
|
-
};
|
|
2801
|
-
for (const { from, to } of view.visibleRanges) {
|
|
2802
|
-
syntaxTree2(state).iterate({
|
|
2803
|
-
enter: (node) => {
|
|
2804
|
-
switch (node.name) {
|
|
2805
|
-
case "Emphasis":
|
|
2806
|
-
case "StrongEmphasis": {
|
|
2807
|
-
const marks = node.node.getChildren("EmphasisMark");
|
|
2808
|
-
replace(node, marks);
|
|
2809
|
-
break;
|
|
2810
|
-
}
|
|
2811
|
-
case "Strikethrough": {
|
|
2812
|
-
const marks = node.node.getChildren("StrikethroughMark");
|
|
2813
|
-
replace(node, marks);
|
|
2814
|
-
break;
|
|
2815
|
-
}
|
|
2816
|
-
}
|
|
2817
|
-
},
|
|
2818
|
-
from,
|
|
2819
|
-
to
|
|
2820
|
-
});
|
|
2821
|
-
}
|
|
2822
|
-
return builder.finish();
|
|
2823
|
-
};
|
|
2824
|
-
return [
|
|
2825
|
-
ViewPlugin4.fromClass(class {
|
|
2826
|
-
constructor(view) {
|
|
2827
|
-
this.decorations = buildDecorations7(view);
|
|
2828
|
-
}
|
|
2829
|
-
update(update2) {
|
|
2830
|
-
this.decorations = buildDecorations7(update2.view);
|
|
2831
|
-
}
|
|
2832
|
-
}, {
|
|
2833
|
-
decorations: (value) => value.decorations
|
|
2834
|
-
})
|
|
3044
|
+
])
|
|
2835
3045
|
];
|
|
2836
3046
|
};
|
|
2837
3047
|
var InlineMarker = {
|
|
@@ -2881,7 +3091,7 @@ var getFormatting = (state) => {
|
|
|
2881
3091
|
null,
|
|
2882
3092
|
null
|
|
2883
3093
|
];
|
|
2884
|
-
let
|
|
3094
|
+
let link = false;
|
|
2885
3095
|
let blockQuote = null;
|
|
2886
3096
|
let listStyle = null;
|
|
2887
3097
|
const stack = [];
|
|
@@ -2943,7 +3153,7 @@ var getFormatting = (state) => {
|
|
|
2943
3153
|
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2944
3154
|
stack.push(name);
|
|
2945
3155
|
} else if (name === "Link") {
|
|
2946
|
-
|
|
3156
|
+
link = true;
|
|
2947
3157
|
} else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
|
|
2948
3158
|
if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
2949
3159
|
stack[stack.length - 1] = "TaskList";
|
|
@@ -3018,13 +3228,13 @@ var getFormatting = (state) => {
|
|
|
3018
3228
|
emphasis: inline[1] ?? false,
|
|
3019
3229
|
strong: inline[0] ?? false,
|
|
3020
3230
|
strikethrough: inline[2] ?? false,
|
|
3021
|
-
link
|
|
3231
|
+
link,
|
|
3022
3232
|
listStyle: listStyle || null
|
|
3023
3233
|
};
|
|
3024
3234
|
};
|
|
3025
3235
|
var useFormattingState = () => {
|
|
3026
3236
|
const [state, setState] = useState(null);
|
|
3027
|
-
const observer = useMemo(() =>
|
|
3237
|
+
const observer = useMemo(() => EditorView11.updateListener.of((update2) => {
|
|
3028
3238
|
if (update2.docChanged || update2.selectionSet) {
|
|
3029
3239
|
const newState = getFormatting(update2.state);
|
|
3030
3240
|
if (!state || !compareFormatting(state, newState)) {
|
|
@@ -3038,117 +3248,14 @@ var useFormattingState = () => {
|
|
|
3038
3248
|
];
|
|
3039
3249
|
};
|
|
3040
3250
|
|
|
3041
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
3042
|
-
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3043
|
-
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
3044
|
-
import { Decoration as Decoration6, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
3045
|
-
var buildDecorations2 = (view) => {
|
|
3046
|
-
const builder = new RangeSetBuilder3();
|
|
3047
|
-
const { state } = view;
|
|
3048
|
-
const cursor = state.selection.main.head;
|
|
3049
|
-
for (const { from, to } of view.visibleRanges) {
|
|
3050
|
-
syntaxTree3(state).iterate({
|
|
3051
|
-
enter: (node) => {
|
|
3052
|
-
switch (node.name) {
|
|
3053
|
-
case "ATXHeading1":
|
|
3054
|
-
case "ATXHeading2":
|
|
3055
|
-
case "ATXHeading3":
|
|
3056
|
-
case "ATXHeading4":
|
|
3057
|
-
case "ATXHeading5":
|
|
3058
|
-
case "ATXHeading6": {
|
|
3059
|
-
const mark2 = node.node.getChild("HeaderMark");
|
|
3060
|
-
if (mark2) {
|
|
3061
|
-
if (!view.hasFocus || view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
3062
|
-
builder.add(mark2.from, mark2.to + 1, Decoration6.replace({}));
|
|
3063
|
-
}
|
|
3064
|
-
}
|
|
3065
|
-
}
|
|
3066
|
-
}
|
|
3067
|
-
},
|
|
3068
|
-
from,
|
|
3069
|
-
to
|
|
3070
|
-
});
|
|
3071
|
-
}
|
|
3072
|
-
return builder.finish();
|
|
3073
|
-
};
|
|
3074
|
-
var heading2 = () => {
|
|
3075
|
-
return [
|
|
3076
|
-
ViewPlugin5.fromClass(class {
|
|
3077
|
-
constructor(view) {
|
|
3078
|
-
this.decorations = buildDecorations2(view);
|
|
3079
|
-
}
|
|
3080
|
-
update(update2) {
|
|
3081
|
-
this.decorations = buildDecorations2(update2.view);
|
|
3082
|
-
}
|
|
3083
|
-
}, {
|
|
3084
|
-
decorations: (value) => value.decorations
|
|
3085
|
-
})
|
|
3086
|
-
];
|
|
3087
|
-
};
|
|
3088
|
-
|
|
3089
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
3090
|
-
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
3091
|
-
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
3092
|
-
import { Decoration as Decoration7, EditorView as EditorView11, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
3093
|
-
var styles5 = EditorView11.baseTheme({
|
|
3094
|
-
"& .cm-hr": {
|
|
3095
|
-
// Note that block-level decorations should not have vertical margins,
|
|
3096
|
-
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
3097
|
-
}
|
|
3098
|
-
});
|
|
3099
|
-
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
3100
|
-
toDOM() {
|
|
3101
|
-
const el = document.createElement("div");
|
|
3102
|
-
el.className = "cm-hr";
|
|
3103
|
-
return el;
|
|
3104
|
-
}
|
|
3105
|
-
};
|
|
3106
|
-
var decoration = Decoration7.replace({
|
|
3107
|
-
widget: new HorizontalRuleWidget()
|
|
3108
|
-
});
|
|
3109
|
-
var buildDecorations3 = (view) => {
|
|
3110
|
-
const builder = new RangeSetBuilder4();
|
|
3111
|
-
const { state } = view;
|
|
3112
|
-
const cursor = state.selection.main.head;
|
|
3113
|
-
for (const { from, to } of view.visibleRanges) {
|
|
3114
|
-
syntaxTree4(state).iterate({
|
|
3115
|
-
enter: (node) => {
|
|
3116
|
-
if (node.name === "HorizontalRule") {
|
|
3117
|
-
if (cursor <= node.from || cursor >= node.to) {
|
|
3118
|
-
builder.add(node.from, node.to, decoration);
|
|
3119
|
-
}
|
|
3120
|
-
}
|
|
3121
|
-
},
|
|
3122
|
-
from,
|
|
3123
|
-
to
|
|
3124
|
-
});
|
|
3125
|
-
}
|
|
3126
|
-
return builder.finish();
|
|
3127
|
-
};
|
|
3128
|
-
var hr = () => {
|
|
3129
|
-
return [
|
|
3130
|
-
ViewPlugin6.fromClass(class {
|
|
3131
|
-
constructor(view) {
|
|
3132
|
-
this.decorations = buildDecorations3(view);
|
|
3133
|
-
}
|
|
3134
|
-
update(update2) {
|
|
3135
|
-
this.decorations = buildDecorations3(update2.view);
|
|
3136
|
-
}
|
|
3137
|
-
}, {
|
|
3138
|
-
decorations: (value) => value.decorations
|
|
3139
|
-
}),
|
|
3140
|
-
styles5
|
|
3141
|
-
];
|
|
3142
|
-
};
|
|
3143
|
-
|
|
3144
3251
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3145
|
-
import { syntaxTree as
|
|
3252
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3146
3253
|
import { StateField as StateField4 } from "@codemirror/state";
|
|
3147
|
-
import { Decoration as
|
|
3254
|
+
import { Decoration as Decoration5, EditorView as EditorView12, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
3148
3255
|
var image = (options = {}) => {
|
|
3149
3256
|
return StateField4.define({
|
|
3150
3257
|
create: (state) => {
|
|
3151
|
-
return
|
|
3258
|
+
return Decoration5.set(buildDecorations2(0, state.doc.length, state));
|
|
3152
3259
|
},
|
|
3153
3260
|
update: (value, tr) => {
|
|
3154
3261
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -3168,26 +3275,26 @@ var image = (options = {}) => {
|
|
|
3168
3275
|
filterFrom: from,
|
|
3169
3276
|
filterTo: to,
|
|
3170
3277
|
filter: () => false,
|
|
3171
|
-
add:
|
|
3278
|
+
add: buildDecorations2(from, to, tr.state)
|
|
3172
3279
|
});
|
|
3173
3280
|
},
|
|
3174
3281
|
provide: (field) => EditorView12.decorations.from(field)
|
|
3175
3282
|
});
|
|
3176
3283
|
};
|
|
3177
|
-
var
|
|
3284
|
+
var buildDecorations2 = (from, to, state) => {
|
|
3178
3285
|
const decorations = [];
|
|
3179
3286
|
const cursor = state.selection.main.head;
|
|
3180
|
-
|
|
3287
|
+
syntaxTree3(state).iterate({
|
|
3181
3288
|
enter: (node) => {
|
|
3182
3289
|
if (node.name === "Image") {
|
|
3183
3290
|
const urlNode = node.node.getChild("URL");
|
|
3184
3291
|
if (urlNode) {
|
|
3185
|
-
const
|
|
3292
|
+
const hide2 = state.readOnly || cursor < node.from || cursor > node.to;
|
|
3186
3293
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
3187
|
-
decorations.push(
|
|
3294
|
+
decorations.push(Decoration5.replace({
|
|
3188
3295
|
block: true,
|
|
3189
3296
|
widget: new ImageWidget(url)
|
|
3190
|
-
}).range(
|
|
3297
|
+
}).range(hide2 ? node.from : node.to, node.to));
|
|
3191
3298
|
}
|
|
3192
3299
|
}
|
|
3193
3300
|
},
|
|
@@ -3196,7 +3303,7 @@ var buildDecorations4 = (from, to, state) => {
|
|
|
3196
3303
|
});
|
|
3197
3304
|
return decorations;
|
|
3198
3305
|
};
|
|
3199
|
-
var ImageWidget = class extends
|
|
3306
|
+
var ImageWidget = class extends WidgetType3 {
|
|
3200
3307
|
constructor(_url) {
|
|
3201
3308
|
super();
|
|
3202
3309
|
this._url = _url;
|
|
@@ -3214,146 +3321,43 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
3214
3321
|
};
|
|
3215
3322
|
|
|
3216
3323
|
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
3217
|
-
import { syntaxTree as
|
|
3218
|
-
import {
|
|
3219
|
-
import { hoverTooltip as hoverTooltip2, Decoration as Decoration9, ViewPlugin as ViewPlugin7, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
3324
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
3325
|
+
import { hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
|
3220
3326
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
3221
|
-
var
|
|
3222
|
-
const
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
}
|
|
3231
|
-
}
|
|
3232
|
-
}, {
|
|
3233
|
-
decorations: (value) => value.decorations
|
|
3234
|
-
})
|
|
3235
|
-
];
|
|
3236
|
-
if (options.onHover) {
|
|
3237
|
-
extensions.push(
|
|
3238
|
-
// https://codemirror.net/examples/tooltip
|
|
3239
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
3240
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
3241
|
-
hoverTooltip2((view, pos, side) => {
|
|
3242
|
-
const syntax = syntaxTree6(view.state).resolveInner(pos, side);
|
|
3243
|
-
let link2 = null;
|
|
3244
|
-
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
3245
|
-
link2 = node.name === "Link" ? node : null;
|
|
3246
|
-
}
|
|
3247
|
-
const url = link2 && link2.getChild("URL");
|
|
3248
|
-
if (!url || !link2) {
|
|
3249
|
-
return null;
|
|
3250
|
-
}
|
|
3251
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
3252
|
-
return {
|
|
3253
|
-
pos: link2.from,
|
|
3254
|
-
end: link2.to,
|
|
3255
|
-
above: true,
|
|
3256
|
-
create: () => {
|
|
3257
|
-
const el = document.createElement("div");
|
|
3258
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
3259
|
-
options.onHover(el, urlText);
|
|
3260
|
-
return {
|
|
3261
|
-
dom: el,
|
|
3262
|
-
offset: {
|
|
3263
|
-
x: 0,
|
|
3264
|
-
y: 4
|
|
3265
|
-
}
|
|
3266
|
-
};
|
|
3267
|
-
}
|
|
3268
|
-
};
|
|
3269
|
-
})
|
|
3270
|
-
);
|
|
3271
|
-
}
|
|
3272
|
-
return extensions;
|
|
3273
|
-
};
|
|
3274
|
-
var LinkButton = class extends WidgetType5 {
|
|
3275
|
-
constructor(_url, _onAttach) {
|
|
3276
|
-
super();
|
|
3277
|
-
this._url = _url;
|
|
3278
|
-
this._onAttach = _onAttach;
|
|
3279
|
-
}
|
|
3280
|
-
eq(other) {
|
|
3281
|
-
return this._url === other._url;
|
|
3282
|
-
}
|
|
3283
|
-
toDOM(view) {
|
|
3284
|
-
const el = document.createElement("span");
|
|
3285
|
-
this._onAttach(el, this._url);
|
|
3286
|
-
return el;
|
|
3287
|
-
}
|
|
3288
|
-
};
|
|
3289
|
-
var LinkText = class extends WidgetType5 {
|
|
3290
|
-
constructor(_text, _url) {
|
|
3291
|
-
super();
|
|
3292
|
-
this._text = _text;
|
|
3293
|
-
this._url = _url;
|
|
3294
|
-
}
|
|
3295
|
-
eq(other) {
|
|
3296
|
-
return this._url === other._url;
|
|
3327
|
+
var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
|
|
3328
|
+
const syntax = syntaxTree4(view.state).resolveInner(pos, side);
|
|
3329
|
+
let link = null;
|
|
3330
|
+
for (let i = 0, node = syntax; !link && node && i < 5; node = node.parent, i++) {
|
|
3331
|
+
link = node.name === "Link" ? node : null;
|
|
3332
|
+
}
|
|
3333
|
+
const url = link && link.getChild("URL");
|
|
3334
|
+
if (!url || !link) {
|
|
3335
|
+
return null;
|
|
3297
3336
|
}
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
}
|
|
3337
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
3338
|
+
return {
|
|
3339
|
+
pos: link.from,
|
|
3340
|
+
end: link.to,
|
|
3341
|
+
above: true,
|
|
3342
|
+
create: () => {
|
|
3343
|
+
const el = document.createElement("div");
|
|
3344
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
3345
|
+
render(el, urlText);
|
|
3346
|
+
return {
|
|
3347
|
+
dom: el,
|
|
3348
|
+
offset: {
|
|
3349
|
+
x: 0,
|
|
3350
|
+
y: 4
|
|
3351
|
+
}
|
|
3313
3352
|
};
|
|
3314
3353
|
}
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
};
|
|
3318
|
-
var buildDecorations5 = (view, options) => {
|
|
3319
|
-
const builder = new RangeSetBuilder5();
|
|
3320
|
-
const { state } = view;
|
|
3321
|
-
const cursor = state.selection.main.head;
|
|
3322
|
-
for (const { from, to } of view.visibleRanges) {
|
|
3323
|
-
syntaxTree6(state).iterate({
|
|
3324
|
-
enter: (node) => {
|
|
3325
|
-
if (node.name === "Link") {
|
|
3326
|
-
const marks = node.node.getChildren("LinkMark");
|
|
3327
|
-
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
3328
|
-
const urlNode = node.node.getChild("URL");
|
|
3329
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
3330
|
-
if (!url) {
|
|
3331
|
-
return false;
|
|
3332
|
-
}
|
|
3333
|
-
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
3334
|
-
builder.add(node.from, node.to, Decoration9.replace({
|
|
3335
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
3336
|
-
}));
|
|
3337
|
-
}
|
|
3338
|
-
if (options.onRender) {
|
|
3339
|
-
builder.add(node.to, node.to, Decoration9.replace({
|
|
3340
|
-
widget: new LinkButton(url, options.onRender)
|
|
3341
|
-
}));
|
|
3342
|
-
}
|
|
3343
|
-
return false;
|
|
3344
|
-
}
|
|
3345
|
-
},
|
|
3346
|
-
from,
|
|
3347
|
-
to
|
|
3348
|
-
});
|
|
3349
|
-
}
|
|
3350
|
-
return builder.finish();
|
|
3351
|
-
};
|
|
3354
|
+
};
|
|
3355
|
+
});
|
|
3352
3356
|
|
|
3353
3357
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
3354
|
-
import { syntaxTree as
|
|
3355
|
-
import { RangeSetBuilder as
|
|
3356
|
-
import { Decoration as
|
|
3358
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
3359
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField5 } from "@codemirror/state";
|
|
3360
|
+
import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3357
3361
|
var table = (options = {}) => {
|
|
3358
3362
|
return StateField5.define({
|
|
3359
3363
|
create: (state) => update(state, options),
|
|
@@ -3362,7 +3366,7 @@ var table = (options = {}) => {
|
|
|
3362
3366
|
});
|
|
3363
3367
|
};
|
|
3364
3368
|
var update = (state, options) => {
|
|
3365
|
-
const builder = new
|
|
3369
|
+
const builder = new RangeSetBuilder2();
|
|
3366
3370
|
const cursor = state.selection.main.head;
|
|
3367
3371
|
const tables = [];
|
|
3368
3372
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -3370,7 +3374,7 @@ var update = (state, options) => {
|
|
|
3370
3374
|
const table2 = getTable();
|
|
3371
3375
|
return table2.rows?.[table2.rows.length - 1];
|
|
3372
3376
|
};
|
|
3373
|
-
|
|
3377
|
+
syntaxTree5(state).iterate({
|
|
3374
3378
|
enter: (node) => {
|
|
3375
3379
|
switch (node.name) {
|
|
3376
3380
|
case "Table": {
|
|
@@ -3401,17 +3405,17 @@ var update = (state, options) => {
|
|
|
3401
3405
|
}
|
|
3402
3406
|
});
|
|
3403
3407
|
tables.forEach((table2) => {
|
|
3404
|
-
const
|
|
3405
|
-
|
|
3408
|
+
const hide2 = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
3409
|
+
hide2 && builder.add(table2.from, table2.to, Decoration6.replace({
|
|
3406
3410
|
widget: new TableWidget(table2)
|
|
3407
3411
|
}));
|
|
3408
|
-
builder.add(table2.from, table2.to,
|
|
3412
|
+
builder.add(table2.from, table2.to, Decoration6.mark({
|
|
3409
3413
|
class: "cm-table"
|
|
3410
3414
|
}));
|
|
3411
3415
|
});
|
|
3412
3416
|
return builder.finish();
|
|
3413
3417
|
};
|
|
3414
|
-
var TableWidget = class extends
|
|
3418
|
+
var TableWidget = class extends WidgetType4 {
|
|
3415
3419
|
constructor(_table) {
|
|
3416
3420
|
super();
|
|
3417
3421
|
this._table = _table;
|
|
@@ -3448,103 +3452,6 @@ var TableWidget = class extends WidgetType6 {
|
|
|
3448
3452
|
}
|
|
3449
3453
|
};
|
|
3450
3454
|
|
|
3451
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
3452
|
-
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
3453
|
-
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
3454
|
-
import { EditorView as EditorView14, Decoration as Decoration11, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
3455
|
-
var styles6 = EditorView14.baseTheme({
|
|
3456
|
-
"& .cm-task": {
|
|
3457
|
-
color: getToken("extend.colors.blue.500")
|
|
3458
|
-
},
|
|
3459
|
-
"& .cm-task-checkbox": {
|
|
3460
|
-
marginLeft: "4px",
|
|
3461
|
-
marginRight: "4px"
|
|
3462
|
-
}
|
|
3463
|
-
});
|
|
3464
|
-
var CheckboxWidget = class extends WidgetType7 {
|
|
3465
|
-
constructor(_checked) {
|
|
3466
|
-
super();
|
|
3467
|
-
this._checked = _checked;
|
|
3468
|
-
}
|
|
3469
|
-
eq(other) {
|
|
3470
|
-
return this._checked === other._checked;
|
|
3471
|
-
}
|
|
3472
|
-
toDOM(view) {
|
|
3473
|
-
const input = document.createElement("input");
|
|
3474
|
-
input.className = "cm-task-checkbox";
|
|
3475
|
-
input.type = "checkbox";
|
|
3476
|
-
input.checked = this._checked;
|
|
3477
|
-
if (view.state.readOnly) {
|
|
3478
|
-
input.setAttribute("disabled", "true");
|
|
3479
|
-
} else {
|
|
3480
|
-
input.onmousedown = (event) => {
|
|
3481
|
-
const pos = view.posAtDOM(input);
|
|
3482
|
-
const text = view.state.sliceDoc(pos, pos + 3);
|
|
3483
|
-
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
3484
|
-
view.dispatch({
|
|
3485
|
-
changes: {
|
|
3486
|
-
from: pos + 1,
|
|
3487
|
-
to: pos + 2,
|
|
3488
|
-
insert: this._checked ? " " : "x"
|
|
3489
|
-
}
|
|
3490
|
-
});
|
|
3491
|
-
event.preventDefault();
|
|
3492
|
-
}
|
|
3493
|
-
};
|
|
3494
|
-
}
|
|
3495
|
-
return input;
|
|
3496
|
-
}
|
|
3497
|
-
ignoreEvent() {
|
|
3498
|
-
return false;
|
|
3499
|
-
}
|
|
3500
|
-
};
|
|
3501
|
-
var checkedDecoration = Decoration11.replace({
|
|
3502
|
-
widget: new CheckboxWidget(true)
|
|
3503
|
-
});
|
|
3504
|
-
var uncheckedDecoration = Decoration11.replace({
|
|
3505
|
-
widget: new CheckboxWidget(false)
|
|
3506
|
-
});
|
|
3507
|
-
var buildDecorations6 = (view) => {
|
|
3508
|
-
const builder = new RangeSetBuilder7();
|
|
3509
|
-
const { state } = view;
|
|
3510
|
-
const cursor = state.selection.main.head;
|
|
3511
|
-
for (const { from, to } of view.visibleRanges) {
|
|
3512
|
-
syntaxTree8(state).iterate({
|
|
3513
|
-
enter: (node) => {
|
|
3514
|
-
if (node.name === "TaskMarker") {
|
|
3515
|
-
if (cursor < node.from || cursor > node.to) {
|
|
3516
|
-
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
3517
|
-
builder.add(node.from - 2, node.from - 1, Decoration11.mark({
|
|
3518
|
-
class: "cm-task"
|
|
3519
|
-
}));
|
|
3520
|
-
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
3521
|
-
}
|
|
3522
|
-
}
|
|
3523
|
-
},
|
|
3524
|
-
from,
|
|
3525
|
-
to
|
|
3526
|
-
});
|
|
3527
|
-
}
|
|
3528
|
-
return builder.finish();
|
|
3529
|
-
};
|
|
3530
|
-
var tasklist = (options = {}) => {
|
|
3531
|
-
return [
|
|
3532
|
-
ViewPlugin8.fromClass(class {
|
|
3533
|
-
constructor(view) {
|
|
3534
|
-
this.decorations = buildDecorations6(view);
|
|
3535
|
-
}
|
|
3536
|
-
update(update2) {
|
|
3537
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
3538
|
-
this.decorations = buildDecorations6(update2.view);
|
|
3539
|
-
}
|
|
3540
|
-
}
|
|
3541
|
-
}, {
|
|
3542
|
-
decorations: (value) => value.decorations
|
|
3543
|
-
}),
|
|
3544
|
-
styles6
|
|
3545
|
-
];
|
|
3546
|
-
};
|
|
3547
|
-
|
|
3548
3455
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
3549
3456
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
3550
3457
|
var mention = ({ onSearch }) => {
|
|
@@ -3575,10 +3482,10 @@ var mention = ({ onSearch }) => {
|
|
|
3575
3482
|
};
|
|
3576
3483
|
|
|
3577
3484
|
// packages/ui/react-ui-editor/src/extensions/modes.ts
|
|
3578
|
-
import { Facet as
|
|
3485
|
+
import { Facet as Facet5 } from "@codemirror/state";
|
|
3579
3486
|
import { keymap as keymap6 } from "@codemirror/view";
|
|
3580
3487
|
import { vim } from "@replit/codemirror-vim";
|
|
3581
|
-
var editorMode =
|
|
3488
|
+
var editorMode = Facet5.define({
|
|
3582
3489
|
combine: (modes) => modes[0] ?? {}
|
|
3583
3490
|
});
|
|
3584
3491
|
var EditorModes = {
|
|
@@ -3942,7 +3849,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
3942
3849
|
selection,
|
|
3943
3850
|
extensions: [
|
|
3944
3851
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
3945
|
-
|
|
3852
|
+
EditorView14.exceptionSink.of((err) => {
|
|
3946
3853
|
log3.catch(err, void 0, {
|
|
3947
3854
|
F: __dxlog_file4,
|
|
3948
3855
|
L: 113,
|
|
@@ -3952,17 +3859,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
3952
3859
|
}),
|
|
3953
3860
|
// Theme.
|
|
3954
3861
|
// TODO(burdon): Make configurable.
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3862
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3863
|
+
EditorView14.theme(theme ?? {}),
|
|
3864
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3865
|
+
EditorView14.editorAttributes.of({
|
|
3959
3866
|
class: slots.editor?.className ?? ""
|
|
3960
3867
|
}),
|
|
3961
|
-
|
|
3868
|
+
EditorView14.contentAttributes.of({
|
|
3962
3869
|
class: slots.content?.className ?? ""
|
|
3963
3870
|
}),
|
|
3964
3871
|
// Focus.
|
|
3965
|
-
|
|
3872
|
+
EditorView14.updateListener.of((update2) => {
|
|
3966
3873
|
update2.transactions.forEach((transaction) => {
|
|
3967
3874
|
if (transaction.isUserEvent("focus.container")) {
|
|
3968
3875
|
rootRef.current?.focus();
|
|
@@ -3970,7 +3877,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
3970
3877
|
});
|
|
3971
3878
|
}),
|
|
3972
3879
|
// State.
|
|
3973
|
-
|
|
3880
|
+
EditorView14.editable.of(!readonly),
|
|
3974
3881
|
EditorState2.readOnly.of(!!readonly),
|
|
3975
3882
|
// Storage and replication.
|
|
3976
3883
|
// NOTE: This must come before user extensions.
|
|
@@ -3979,7 +3886,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
3979
3886
|
...extensions
|
|
3980
3887
|
].filter(isNotFalsy4)
|
|
3981
3888
|
});
|
|
3982
|
-
const newView = new
|
|
3889
|
+
const newView = new EditorView14({
|
|
3983
3890
|
state,
|
|
3984
3891
|
parent: rootRef.current,
|
|
3985
3892
|
scrollTo,
|
|
@@ -4096,32 +4003,12 @@ var defaultMarkdownSlots = {
|
|
|
4096
4003
|
import { ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic, Quotes } from "@phosphor-icons/react";
|
|
4097
4004
|
import { createContext } from "@radix-ui/react-context";
|
|
4098
4005
|
import React2 from "react";
|
|
4099
|
-
import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, useTranslation } from "@dxos/react-ui";
|
|
4006
|
+
import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
|
|
4100
4007
|
import { getSize } from "@dxos/react-ui-theme";
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
{
|
|
4106
|
-
"en-US": {
|
|
4107
|
-
[translationKey]: {
|
|
4108
|
-
"strong label": "Strong",
|
|
4109
|
-
"emphasis label": "Emphasis",
|
|
4110
|
-
"strikethrough label": "Strike-through",
|
|
4111
|
-
"code label": "Code",
|
|
4112
|
-
"list-bullet label": "Bullet list",
|
|
4113
|
-
"list-ordered label": "Numbered list",
|
|
4114
|
-
"list-task label": "Task list",
|
|
4115
|
-
"blockquote label": "Block quote",
|
|
4116
|
-
"codeblock label": "Code block",
|
|
4117
|
-
"comment label": "Create comment",
|
|
4118
|
-
"heading label": "Heading level"
|
|
4119
|
-
}
|
|
4120
|
-
}
|
|
4121
|
-
}
|
|
4122
|
-
];
|
|
4123
|
-
|
|
4124
|
-
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
4008
|
+
var tooltipProps = {
|
|
4009
|
+
side: "top",
|
|
4010
|
+
classNames: "z-10"
|
|
4011
|
+
};
|
|
4125
4012
|
var HeadingIcons = {
|
|
4126
4013
|
"0": Paragraph,
|
|
4127
4014
|
"1": TextHOne,
|
|
@@ -4150,7 +4037,9 @@ var ToolbarRoot = ({ children, onAction, classNames, state }) => {
|
|
|
4150
4037
|
var buttonStyles = "min-bs-0 p-2";
|
|
4151
4038
|
var iconStyles = getSize(5);
|
|
4152
4039
|
var ToolbarButton = ({ Icon, children, ...props }) => {
|
|
4153
|
-
return /* @__PURE__ */ React2.createElement(
|
|
4040
|
+
return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
4041
|
+
asChild: true
|
|
4042
|
+
}, /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroupItem, {
|
|
4154
4043
|
variant: "ghost",
|
|
4155
4044
|
...props,
|
|
4156
4045
|
classNames: buttonStyles
|
|
@@ -4158,7 +4047,7 @@ var ToolbarButton = ({ Icon, children, ...props }) => {
|
|
|
4158
4047
|
className: iconStyles
|
|
4159
4048
|
}), /* @__PURE__ */ React2.createElement("span", {
|
|
4160
4049
|
className: "sr-only"
|
|
4161
|
-
}, children));
|
|
4050
|
+
}, children))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4162
4051
|
};
|
|
4163
4052
|
var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
4164
4053
|
role: "separator",
|
|
@@ -4171,13 +4060,15 @@ var MarkdownHeading = () => {
|
|
|
4171
4060
|
const header = blockType && /heading(\d)/.exec(blockType);
|
|
4172
4061
|
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
|
4173
4062
|
const HeadingIcon = HeadingIcons[value ?? "0"];
|
|
4174
|
-
return /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
4063
|
+
return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
4175
4064
|
disabled: value === null,
|
|
4176
4065
|
value: value ?? "0",
|
|
4177
4066
|
onValueChange: (value2) => onAction?.({
|
|
4178
4067
|
type: "heading",
|
|
4179
4068
|
data: parseInt(value2)
|
|
4180
4069
|
})
|
|
4070
|
+
}, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
4071
|
+
asChild: true
|
|
4181
4072
|
}, /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
|
|
4182
4073
|
asChild: true
|
|
4183
4074
|
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
|
|
@@ -4187,7 +4078,7 @@ var MarkdownHeading = () => {
|
|
|
4187
4078
|
className: "sr-only"
|
|
4188
4079
|
}, t("heading label")), /* @__PURE__ */ React2.createElement(HeadingIcon, {
|
|
4189
4080
|
className: iconStyles
|
|
4190
|
-
}))), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.ScrollUpButton, null), /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
4081
|
+
})))), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.ScrollUpButton, null), /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
4191
4082
|
value: "0"
|
|
4192
4083
|
}, /* @__PURE__ */ React2.createElement(Paragraph, {
|
|
4193
4084
|
className: iconStyles
|
|
@@ -4213,7 +4104,7 @@ var MarkdownHeading = () => {
|
|
|
4213
4104
|
className: iconStyles
|
|
4214
4105
|
}), level === 6 && /* @__PURE__ */ React2.createElement(TextHSix, {
|
|
4215
4106
|
className: iconStyles
|
|
4216
|
-
})))), /* @__PURE__ */ React2.createElement(Select.ScrollDownButton, null), /* @__PURE__ */ React2.createElement(Select.Arrow, null))));
|
|
4107
|
+
})))), /* @__PURE__ */ React2.createElement(Select.ScrollDownButton, null), /* @__PURE__ */ React2.createElement(Select.Arrow, null)))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4217
4108
|
};
|
|
4218
4109
|
var markdownStyles = [
|
|
4219
4110
|
{
|
|
@@ -4301,8 +4192,7 @@ var markdownBlocks = [
|
|
|
4301
4192
|
{
|
|
4302
4193
|
type: "codeblock",
|
|
4303
4194
|
Icon: CodeBlock,
|
|
4304
|
-
getState: (state) => state.blockType === "codeblock"
|
|
4305
|
-
disabled: (state) => !state.blankLine
|
|
4195
|
+
getState: (state) => state.blockType === "codeblock"
|
|
4306
4196
|
},
|
|
4307
4197
|
{
|
|
4308
4198
|
type: "table",
|
|
@@ -4333,7 +4223,9 @@ var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragmen
|
|
|
4333
4223
|
var MarkdownExtended = () => {
|
|
4334
4224
|
const { onAction } = useToolbarContext("MarkdownStyles");
|
|
4335
4225
|
const { t } = useTranslation(translationKey);
|
|
4336
|
-
return /* @__PURE__ */ React2.createElement(
|
|
4226
|
+
return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
4227
|
+
asChild: true
|
|
4228
|
+
}, /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
|
|
4337
4229
|
variant: "ghost",
|
|
4338
4230
|
"data-testid": "editor.toolbar.comment",
|
|
4339
4231
|
onClick: () => onAction?.({
|
|
@@ -4344,7 +4236,7 @@ var MarkdownExtended = () => {
|
|
|
4344
4236
|
className: iconStyles
|
|
4345
4237
|
}), /* @__PURE__ */ React2.createElement("span", {
|
|
4346
4238
|
className: "sr-only"
|
|
4347
|
-
}, t("comment label")));
|
|
4239
|
+
}, t("comment label")))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("comment label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4348
4240
|
};
|
|
4349
4241
|
var Toolbar = {
|
|
4350
4242
|
Root: ToolbarRoot,
|
|
@@ -4535,7 +4427,7 @@ var useEditorView = (id) => {
|
|
|
4535
4427
|
|
|
4536
4428
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4537
4429
|
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4538
|
-
import { EditorView as
|
|
4430
|
+
import { EditorView as EditorView15 } from "@codemirror/view";
|
|
4539
4431
|
import { useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
|
|
4540
4432
|
import { log as log5 } from "@dxos/log";
|
|
4541
4433
|
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
@@ -4552,7 +4444,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
4552
4444
|
selection,
|
|
4553
4445
|
extensions: [
|
|
4554
4446
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4555
|
-
|
|
4447
|
+
EditorView15.exceptionSink.of((err) => {
|
|
4556
4448
|
log5.catch(err, void 0, {
|
|
4557
4449
|
F: __dxlog_file6,
|
|
4558
4450
|
L: 60,
|
|
@@ -4561,12 +4453,12 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
4561
4453
|
});
|
|
4562
4454
|
}),
|
|
4563
4455
|
extensions,
|
|
4564
|
-
|
|
4456
|
+
EditorView15.updateListener.of(() => {
|
|
4565
4457
|
onUpdate.current?.();
|
|
4566
4458
|
})
|
|
4567
4459
|
].filter(isNotFalsy5)
|
|
4568
4460
|
});
|
|
4569
|
-
view2 = new
|
|
4461
|
+
view2 = new EditorView15({
|
|
4570
4462
|
parent: parentRef.current,
|
|
4571
4463
|
scrollTo,
|
|
4572
4464
|
state,
|
|
@@ -4624,19 +4516,19 @@ var createDataExtensions = ({ readonly = false } = {}) => {
|
|
|
4624
4516
|
return [
|
|
4625
4517
|
//
|
|
4626
4518
|
EditorState3.readOnly.of(readonly),
|
|
4627
|
-
|
|
4519
|
+
EditorView15.editable.of(!readonly)
|
|
4628
4520
|
];
|
|
4629
4521
|
};
|
|
4630
4522
|
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
4631
4523
|
return [
|
|
4632
4524
|
//
|
|
4633
|
-
|
|
4634
|
-
theme &&
|
|
4635
|
-
|
|
4636
|
-
|
|
4525
|
+
EditorView15.baseTheme(defaultTheme),
|
|
4526
|
+
theme && EditorView15.theme(theme),
|
|
4527
|
+
EditorView15.darkTheme.of(themeMode === "dark"),
|
|
4528
|
+
EditorView15.editorAttributes.of({
|
|
4637
4529
|
class: slots?.editor?.className ?? ""
|
|
4638
4530
|
}),
|
|
4639
|
-
|
|
4531
|
+
EditorView15.contentAttributes.of({
|
|
4640
4532
|
class: slots?.content?.className ?? ""
|
|
4641
4533
|
})
|
|
4642
4534
|
].filter(isNotFalsy5);
|
|
@@ -4736,7 +4628,6 @@ export {
|
|
|
4736
4628
|
awarenessProvider,
|
|
4737
4629
|
blast,
|
|
4738
4630
|
callbackWrapper,
|
|
4739
|
-
code2 as code,
|
|
4740
4631
|
codeTheme,
|
|
4741
4632
|
comments,
|
|
4742
4633
|
compareFormatting,
|
|
@@ -4745,6 +4636,9 @@ export {
|
|
|
4745
4636
|
createDataExtensions,
|
|
4746
4637
|
createMarkdownExtensions,
|
|
4747
4638
|
createThemeExtensions,
|
|
4639
|
+
cursorLineMargin,
|
|
4640
|
+
cursorLineMarginFacet,
|
|
4641
|
+
decorateMarkdown,
|
|
4748
4642
|
defaultMarkdownSlots,
|
|
4749
4643
|
defaultOptions,
|
|
4750
4644
|
defaultSlots,
|
|
@@ -4759,12 +4653,10 @@ export {
|
|
|
4759
4653
|
formatting,
|
|
4760
4654
|
getFormatting,
|
|
4761
4655
|
getToken,
|
|
4762
|
-
heading2 as heading,
|
|
4763
|
-
hr,
|
|
4764
4656
|
image,
|
|
4765
4657
|
insertTable,
|
|
4766
4658
|
keymap8 as keymap,
|
|
4767
|
-
|
|
4659
|
+
linkTooltip,
|
|
4768
4660
|
listener,
|
|
4769
4661
|
logChanges,
|
|
4770
4662
|
markdownHighlightStyle,
|
|
@@ -4786,7 +4678,6 @@ export {
|
|
|
4786
4678
|
setStyle,
|
|
4787
4679
|
table,
|
|
4788
4680
|
tags2 as tags,
|
|
4789
|
-
tasklist,
|
|
4790
4681
|
textTheme,
|
|
4791
4682
|
toggleBlockquote,
|
|
4792
4683
|
toggleCodeblock,
|
|
@@ -4796,6 +4687,7 @@ export {
|
|
|
4796
4687
|
toggleStrikethrough,
|
|
4797
4688
|
toggleStrong,
|
|
4798
4689
|
toggleStyle,
|
|
4690
|
+
translations_default as translations,
|
|
4799
4691
|
typewriter,
|
|
4800
4692
|
useActionHandler,
|
|
4801
4693
|
useComments,
|