@dxos/react-ui-editor 0.3.11-next.e28df4f → 0.3.11-next.f4c1077
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 +1218 -171
- package/dist/lib/browser/index.mjs.map +3 -3
- 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/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +8 -4
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +5 -3
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +5 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +55 -10
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.test.d.ts +3 -0
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -0
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +12 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/package.json +25 -25
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +3 -3
- package/src/components/TextEditor/TextEditor.tsx +3 -4
- package/src/components/TextEditor/hooks.stories.tsx +6 -1
- package/src/components/Toolbar/Toolbar.stories.tsx +16 -4
- package/src/components/Toolbar/Toolbar.tsx +128 -30
- package/src/extensions/awareness.ts +4 -1
- package/src/extensions/blast.ts +4 -1
- package/src/extensions/comments.ts +14 -4
- package/src/extensions/markdown/formatting.test.ts +482 -0
- package/src/extensions/markdown/formatting.ts +1118 -69
- package/src/extensions/markdown/link.ts +8 -2
- package/src/hooks/useActionHandler.ts +47 -16
- package/src/hooks/useTextModel.ts +17 -1
- package/src/index.ts +1 -1
- package/src/themes/default.ts +7 -4
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +0 -26
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +0 -1
- package/src/components/TextEditor/comments.stories.tsx +0 -357
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
// packages/ui/react-ui-editor/src/index.ts
|
|
2
2
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
3
3
|
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
4
|
+
import { keymap as keymap7 } from "@codemirror/view";
|
|
4
5
|
|
|
5
6
|
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
6
7
|
import { tags as tags2 } from "@lezer/highlight";
|
|
7
8
|
|
|
8
9
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
10
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
|
-
import { EditorView as
|
|
11
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
11
12
|
import { vim } from "@replit/codemirror-vim";
|
|
12
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
13
|
-
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
|
|
14
15
|
import { log as log2 } from "@dxos/log";
|
|
15
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
16
|
-
import {
|
|
17
|
+
import { focusRing, mx as mx3 } from "@dxos/react-ui-theme";
|
|
17
18
|
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
18
19
|
|
|
19
20
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
@@ -782,7 +783,7 @@ var Blaster = class {
|
|
|
782
783
|
initialize() {
|
|
783
784
|
invariant(!this._canvas && !this._ctx, void 0, {
|
|
784
785
|
F: __dxlog_file,
|
|
785
|
-
L:
|
|
786
|
+
L: 141,
|
|
786
787
|
S: this,
|
|
787
788
|
A: [
|
|
788
789
|
"!this._canvas && !this._ctx",
|
|
@@ -819,7 +820,7 @@ var Blaster = class {
|
|
|
819
820
|
start() {
|
|
820
821
|
invariant(this._canvas && this._ctx, void 0, {
|
|
821
822
|
F: __dxlog_file,
|
|
822
|
-
L:
|
|
823
|
+
L: 180,
|
|
823
824
|
S: this,
|
|
824
825
|
A: [
|
|
825
826
|
"this._canvas && this._ctx",
|
|
@@ -1073,11 +1074,25 @@ var logChanges = (trs) => {
|
|
|
1073
1074
|
|
|
1074
1075
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1075
1076
|
var styles2 = EditorView5.baseTheme({
|
|
1076
|
-
"& .cm-comment": {
|
|
1077
|
+
"&light .cm-comment, &light .cm-comment-current": {
|
|
1078
|
+
mixBlendMode: "darken"
|
|
1079
|
+
},
|
|
1080
|
+
"&dark .cm-comment, &dark .cm-comment-current": {
|
|
1081
|
+
mixBlendMode: "plus-lighter"
|
|
1082
|
+
},
|
|
1083
|
+
"&light .cm-comment": {
|
|
1077
1084
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1078
1085
|
},
|
|
1079
|
-
"& .cm-comment-current": {
|
|
1086
|
+
"&light .cm-comment-current": {
|
|
1080
1087
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1088
|
+
},
|
|
1089
|
+
"&dark .cm-comment": {
|
|
1090
|
+
color: getToken("extend.colors.yellow.50"),
|
|
1091
|
+
backgroundColor: getToken("extend.colors.yellow.900")
|
|
1092
|
+
},
|
|
1093
|
+
"&dark .cm-comment-current": {
|
|
1094
|
+
color: getToken("extend.colors.yellow.100"),
|
|
1095
|
+
backgroundColor: getToken("extend.colors.yellow.950")
|
|
1081
1096
|
}
|
|
1082
1097
|
});
|
|
1083
1098
|
var commentMark = Decoration2.mark({
|
|
@@ -1286,7 +1301,11 @@ var createComment = (view) => {
|
|
|
1286
1301
|
to
|
|
1287
1302
|
});
|
|
1288
1303
|
if (cursor) {
|
|
1289
|
-
const id = options.onCreate?.(
|
|
1304
|
+
const id = options.onCreate?.({
|
|
1305
|
+
cursor,
|
|
1306
|
+
from,
|
|
1307
|
+
location: view.coordsAtPos(from)
|
|
1308
|
+
});
|
|
1290
1309
|
if (id) {
|
|
1291
1310
|
view.dispatch({
|
|
1292
1311
|
effects: setSelection.of({
|
|
@@ -1814,89 +1833,836 @@ var code2 = () => {
|
|
|
1814
1833
|
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1815
1834
|
import { snippet } from "@codemirror/autocomplete";
|
|
1816
1835
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1817
|
-
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1818
|
-
import { Decoration as Decoration4, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1819
|
-
|
|
1820
|
-
|
|
1836
|
+
import { RangeSetBuilder as RangeSetBuilder2, EditorSelection } from "@codemirror/state";
|
|
1837
|
+
import { Decoration as Decoration4, EditorView as EditorView9, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1838
|
+
import { useState, useMemo } from "react";
|
|
1839
|
+
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;
|
|
1840
|
+
var Inline;
|
|
1841
|
+
(function(Inline2) {
|
|
1842
|
+
Inline2[Inline2["Strong"] = 0] = "Strong";
|
|
1843
|
+
Inline2[Inline2["Emphasis"] = 1] = "Emphasis";
|
|
1844
|
+
Inline2[Inline2["Strikethrough"] = 2] = "Strikethrough";
|
|
1845
|
+
Inline2[Inline2["Code"] = 3] = "Code";
|
|
1846
|
+
})(Inline || (Inline = {}));
|
|
1847
|
+
var List;
|
|
1848
|
+
(function(List2) {
|
|
1849
|
+
List2[List2["Ordered"] = 0] = "Ordered";
|
|
1850
|
+
List2[List2["Bullet"] = 1] = "Bullet";
|
|
1851
|
+
List2[List2["Task"] = 2] = "Task";
|
|
1852
|
+
})(List || (List = {}));
|
|
1853
|
+
var setHeading = (level) => ({ state, dispatch }) => {
|
|
1854
|
+
const { selection: { ranges }, doc } = state;
|
|
1821
1855
|
const changes = [];
|
|
1856
|
+
let prevBlock = -1;
|
|
1822
1857
|
for (const range of ranges) {
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
from
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1858
|
+
syntaxTree2(state).iterate({
|
|
1859
|
+
from: range.from,
|
|
1860
|
+
to: range.to,
|
|
1861
|
+
enter: (node) => {
|
|
1862
|
+
if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
|
|
1863
|
+
return;
|
|
1864
|
+
}
|
|
1865
|
+
prevBlock = node.from;
|
|
1866
|
+
const blockType = Textblocks[node.name];
|
|
1867
|
+
const isHeading = /heading(\d)/.exec(blockType);
|
|
1868
|
+
const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
|
|
1869
|
+
if (curLevel < 0 || curLevel === level) {
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
if (curLevel === 0) {
|
|
1873
|
+
changes.push({
|
|
1874
|
+
from: node.from,
|
|
1875
|
+
insert: "#".repeat(level) + " "
|
|
1876
|
+
});
|
|
1877
|
+
} else if (node.name === "SetextHeading1" || node.name === "SetextHeading2") {
|
|
1878
|
+
const nextLine = doc.lineAt(node.to);
|
|
1879
|
+
if (level) {
|
|
1880
|
+
changes.push({
|
|
1881
|
+
from: node.from,
|
|
1882
|
+
insert: "#".repeat(level) + " "
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
changes.push({
|
|
1886
|
+
from: nextLine.from - 1,
|
|
1887
|
+
to: nextLine.to
|
|
1888
|
+
});
|
|
1889
|
+
} else {
|
|
1890
|
+
if (level === 0) {
|
|
1891
|
+
changes.push({
|
|
1892
|
+
from: node.from,
|
|
1893
|
+
to: Math.min(node.to, node.from + curLevel + 1)
|
|
1894
|
+
});
|
|
1895
|
+
} else if (level < curLevel) {
|
|
1896
|
+
changes.push({
|
|
1897
|
+
from: node.from,
|
|
1898
|
+
to: node.from + (curLevel - level)
|
|
1899
|
+
});
|
|
1900
|
+
} else {
|
|
1901
|
+
changes.push({
|
|
1902
|
+
from: node.from,
|
|
1903
|
+
insert: "#".repeat(level - curLevel)
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1839
1908
|
});
|
|
1840
1909
|
}
|
|
1910
|
+
if (!changes.length) {
|
|
1911
|
+
return false;
|
|
1912
|
+
}
|
|
1913
|
+
dispatch(state.update({
|
|
1914
|
+
changes,
|
|
1915
|
+
userEvent: "format.setHeading",
|
|
1916
|
+
scrollIntoView: true
|
|
1917
|
+
}));
|
|
1841
1918
|
return true;
|
|
1842
1919
|
};
|
|
1843
|
-
var
|
|
1844
|
-
const
|
|
1845
|
-
|
|
1846
|
-
if (
|
|
1847
|
-
|
|
1920
|
+
var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
1921
|
+
const marker = inlineMarkerText(type);
|
|
1922
|
+
const changes = state.changeByRange((range) => {
|
|
1923
|
+
if (!enable && range.empty) {
|
|
1924
|
+
const after = state.doc.sliceString(range.head, range.head + 6);
|
|
1925
|
+
const found = after.indexOf(marker);
|
|
1926
|
+
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
1927
|
+
const before = state.doc.sliceString(range.head - 6, range.head);
|
|
1928
|
+
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
1929
|
+
...before.slice(before.length - found)
|
|
1930
|
+
].reverse().join("") === after.slice(0, found)) {
|
|
1931
|
+
return {
|
|
1932
|
+
changes: [
|
|
1933
|
+
{
|
|
1934
|
+
from: range.head - marker.length - found,
|
|
1935
|
+
to: range.head - found
|
|
1936
|
+
},
|
|
1937
|
+
{
|
|
1938
|
+
from: range.head + found,
|
|
1939
|
+
to: range.head + found + marker.length
|
|
1940
|
+
}
|
|
1941
|
+
],
|
|
1942
|
+
range: EditorSelection.cursor(range.from - marker.length)
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1848
1946
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1947
|
+
const changes2 = [];
|
|
1948
|
+
const changesAtEnd = [];
|
|
1949
|
+
let blockStart = -1;
|
|
1950
|
+
let blockEnd = -1;
|
|
1951
|
+
let startCovered = false;
|
|
1952
|
+
let endCovered = false;
|
|
1953
|
+
let { from, to } = range;
|
|
1954
|
+
syntaxTree2(state).iterate({
|
|
1955
|
+
from,
|
|
1956
|
+
to,
|
|
1957
|
+
enter: (node) => {
|
|
1958
|
+
const { name } = node;
|
|
1959
|
+
if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
|
|
1960
|
+
blockStart = blockContentStart(node);
|
|
1961
|
+
blockEnd = blockContentEnd(node, state.doc);
|
|
1962
|
+
startCovered = endCovered = false;
|
|
1963
|
+
} else if (name === "Link" || name === "Image" && enable) {
|
|
1964
|
+
if (from < node.from && to > node.from && to <= node.to) {
|
|
1965
|
+
to = node.to;
|
|
1966
|
+
} else if (to > node.to && from >= node.from && from < node.to) {
|
|
1967
|
+
from = node.from;
|
|
1968
|
+
}
|
|
1969
|
+
} else if (IgnoreInline.has(name) && enable) {
|
|
1970
|
+
if (node.from < from && node.to > from) {
|
|
1971
|
+
if (to === from) {
|
|
1972
|
+
to = node.to;
|
|
1973
|
+
}
|
|
1974
|
+
from = node.to;
|
|
1975
|
+
}
|
|
1976
|
+
if (node.from < to && node.to > to) {
|
|
1977
|
+
to = node.from;
|
|
1978
|
+
}
|
|
1979
|
+
} else if (Object.hasOwn(InlineMarker, name)) {
|
|
1980
|
+
const markType = InlineMarker[name];
|
|
1981
|
+
const size = inlineMarkerText(markType).length;
|
|
1982
|
+
const openEnd = node.from + size;
|
|
1983
|
+
const closeStart = node.to - size;
|
|
1984
|
+
if (markType === type) {
|
|
1985
|
+
if (openEnd <= from && closeStart >= from) {
|
|
1986
|
+
startCovered = openEnd === from ? "adjacent" : true;
|
|
1987
|
+
}
|
|
1988
|
+
if (openEnd <= to && closeStart >= to) {
|
|
1989
|
+
endCovered = closeStart === to ? "adjacent" : true;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
if (markType === type || type === 3 && enable) {
|
|
1993
|
+
if (node.from >= from && openEnd <= to) {
|
|
1994
|
+
changes2.push({
|
|
1995
|
+
from: node.from,
|
|
1996
|
+
to: openEnd
|
|
1997
|
+
});
|
|
1998
|
+
if (markType !== type && closeStart >= to) {
|
|
1999
|
+
changesAtEnd.push({
|
|
2000
|
+
from: skipSpaces(Math.min(to, blockEnd), state.doc, 1, blockEnd),
|
|
2001
|
+
insert: inlineMarkerText(markType)
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
if (closeStart >= from && node.to <= to) {
|
|
2006
|
+
changes2.push({
|
|
2007
|
+
from: closeStart,
|
|
2008
|
+
to: node.to
|
|
2009
|
+
});
|
|
2010
|
+
if (markType !== type && openEnd <= from) {
|
|
2011
|
+
changes2.push({
|
|
2012
|
+
from: skipSpaces(Math.max(from, blockStart), state.doc, -1, blockStart),
|
|
2013
|
+
insert: inlineMarkerText(markType)
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
1858
2018
|
}
|
|
1859
|
-
|
|
2019
|
+
},
|
|
2020
|
+
leave: (node) => {
|
|
2021
|
+
if (Object.hasOwn(Textblocks, node.name) && Textblocks[node.name] !== "codeblock") {
|
|
2022
|
+
const rangeStart = Math.max(from, blockStart);
|
|
2023
|
+
const rangeEnd = Math.min(to, blockEnd);
|
|
2024
|
+
if (enable) {
|
|
2025
|
+
if (!startCovered) {
|
|
2026
|
+
changes2.push({
|
|
2027
|
+
from: rangeStart,
|
|
2028
|
+
insert: marker
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
2031
|
+
if (!endCovered) {
|
|
2032
|
+
changes2.push({
|
|
2033
|
+
from: rangeEnd,
|
|
2034
|
+
insert: marker
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2037
|
+
} else {
|
|
2038
|
+
if (startCovered === "adjacent") {
|
|
2039
|
+
changes2.push({
|
|
2040
|
+
from: from - marker.length,
|
|
2041
|
+
to: from
|
|
2042
|
+
});
|
|
2043
|
+
} else if (startCovered) {
|
|
2044
|
+
changes2.push({
|
|
2045
|
+
from: skipSpaces(rangeStart, state.doc, -1, blockStart),
|
|
2046
|
+
insert: marker
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
if (endCovered === "adjacent") {
|
|
2050
|
+
changes2.push({
|
|
2051
|
+
from: to,
|
|
2052
|
+
to: to + marker.length
|
|
2053
|
+
});
|
|
2054
|
+
} else if (endCovered) {
|
|
2055
|
+
changes2.push({
|
|
2056
|
+
from: skipSpaces(rangeEnd, state.doc, 1, blockEnd),
|
|
2057
|
+
insert: marker
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
1860
2063
|
});
|
|
1861
|
-
|
|
2064
|
+
const changeSet = state.changes(changes2.concat(changesAtEnd));
|
|
2065
|
+
return {
|
|
2066
|
+
changes: changeSet,
|
|
2067
|
+
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
2068
|
+
};
|
|
2069
|
+
});
|
|
2070
|
+
dispatch(state.update(changes, {
|
|
2071
|
+
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
2072
|
+
scrollIntoView: true
|
|
2073
|
+
}));
|
|
1862
2074
|
return true;
|
|
1863
2075
|
};
|
|
2076
|
+
var addStyle = (style) => setStyle(style, true);
|
|
2077
|
+
var removeStyle = (style) => setStyle(style, false);
|
|
2078
|
+
var toggleStyle = (style) => (arg) => {
|
|
2079
|
+
const form = getFormatting(arg.state);
|
|
2080
|
+
return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
|
|
2081
|
+
};
|
|
2082
|
+
var toggleStrong = toggleStyle(0);
|
|
2083
|
+
var toggleEmphasis = toggleStyle(1);
|
|
2084
|
+
var toggleStrikethrough = toggleStyle(2);
|
|
2085
|
+
var toggleInlineCode = toggleStyle(3);
|
|
2086
|
+
var inlineMarkerText = (type) => type === 0 ? "**" : type === 2 ? "~~" : type === 1 ? "*" : "`";
|
|
2087
|
+
var blockContentStart = (node) => {
|
|
2088
|
+
const atx = /^ATXHeading(\d)/.exec(node.name);
|
|
2089
|
+
if (atx) {
|
|
2090
|
+
return Math.min(node.to, node.from + +atx[1] + 1);
|
|
2091
|
+
}
|
|
2092
|
+
return node.from;
|
|
2093
|
+
};
|
|
2094
|
+
var blockContentEnd = (node, doc) => {
|
|
2095
|
+
const setext = /^SetextHeading(\d)/.exec(node.name);
|
|
2096
|
+
const lastLine = doc.lineAt(node.to);
|
|
2097
|
+
if (setext || /^[\s>]*$/.exec(lastLine.text)) {
|
|
2098
|
+
return lastLine.from - 1;
|
|
2099
|
+
}
|
|
2100
|
+
return node.to;
|
|
2101
|
+
};
|
|
2102
|
+
var skipSpaces = (pos, doc, dir, limit) => {
|
|
2103
|
+
const line = doc.lineAt(pos);
|
|
2104
|
+
while (pos !== limit && line.text[pos - line.from - (dir < 0 ? 1 : 0)] === " ") {
|
|
2105
|
+
pos += dir;
|
|
2106
|
+
}
|
|
2107
|
+
return pos;
|
|
2108
|
+
};
|
|
1864
2109
|
var snippets = {
|
|
1865
2110
|
codeblock: snippet([
|
|
1866
|
-
|
|
1867
|
-
"
|
|
2111
|
+
//
|
|
2112
|
+
"```#{}",
|
|
2113
|
+
"#{}",
|
|
1868
2114
|
"```"
|
|
1869
2115
|
].join("\n")),
|
|
1870
2116
|
table: snippet([
|
|
2117
|
+
//
|
|
1871
2118
|
"| #{col1} | #{col2} |",
|
|
1872
2119
|
"| ---- | ---- |",
|
|
1873
2120
|
"| #{val1} | #{val2} |",
|
|
1874
|
-
"| #{val3} | #{val4} |"
|
|
2121
|
+
"| #{val3} | #{val4} |",
|
|
2122
|
+
""
|
|
1875
2123
|
].join("\n"))
|
|
1876
2124
|
};
|
|
1877
|
-
var insertCodeblock = (view) => {
|
|
1878
|
-
const { selection: { main }, doc } = view.state;
|
|
1879
|
-
const { number } = doc.lineAt(main.anchor);
|
|
1880
|
-
const { from } = doc.line(number);
|
|
1881
|
-
snippets.codeblock(view, null, from, from);
|
|
1882
|
-
};
|
|
1883
2125
|
var insertTable = (view) => {
|
|
1884
2126
|
const { selection: { main }, doc } = view.state;
|
|
1885
2127
|
const { number } = doc.lineAt(main.anchor);
|
|
1886
2128
|
const { from } = doc.line(number);
|
|
1887
2129
|
snippets.table(view, null, from, from);
|
|
1888
2130
|
};
|
|
1889
|
-
var
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
2131
|
+
var removeLinkInner = (from, to, changes, state) => {
|
|
2132
|
+
syntaxTree2(state).iterate({
|
|
2133
|
+
from,
|
|
2134
|
+
to,
|
|
2135
|
+
enter: (node) => {
|
|
2136
|
+
if (node.name === "Link" && node.from < to && node.to > from) {
|
|
2137
|
+
node.node.cursor().iterate((node2) => {
|
|
2138
|
+
const { name } = node2;
|
|
2139
|
+
if (name === "LinkMark" || name === "LinkLabel") {
|
|
2140
|
+
changes.push({
|
|
2141
|
+
from: node2.from,
|
|
2142
|
+
to: node2.to
|
|
2143
|
+
});
|
|
2144
|
+
} else if (name === "LinkTitle" || name === "URL") {
|
|
2145
|
+
changes.push({
|
|
2146
|
+
from: skipSpaces(node2.from, state.doc, -1),
|
|
2147
|
+
to: skipSpaces(node2.to, state.doc, 1)
|
|
2148
|
+
});
|
|
2149
|
+
}
|
|
2150
|
+
});
|
|
2151
|
+
return false;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
});
|
|
2155
|
+
};
|
|
2156
|
+
var removeLink = ({ state, dispatch }) => {
|
|
2157
|
+
const changes = [];
|
|
2158
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2159
|
+
removeLinkInner(from, to, changes, state);
|
|
2160
|
+
}
|
|
2161
|
+
if (!changes) {
|
|
2162
|
+
return false;
|
|
2163
|
+
}
|
|
2164
|
+
dispatch(state.update({
|
|
2165
|
+
changes,
|
|
2166
|
+
userEvent: "format.link.remove",
|
|
2167
|
+
scrollIntoView: true
|
|
2168
|
+
}));
|
|
2169
|
+
return true;
|
|
2170
|
+
};
|
|
2171
|
+
var addLink = ({ state, dispatch }) => {
|
|
2172
|
+
const changes = state.changeByRange((range) => {
|
|
2173
|
+
let { from, to } = range;
|
|
2174
|
+
const cutStyles = [];
|
|
2175
|
+
let okay = null;
|
|
2176
|
+
syntaxTree2(state).iterate({
|
|
2177
|
+
from,
|
|
2178
|
+
to,
|
|
2179
|
+
enter: (node) => {
|
|
2180
|
+
if (Object.hasOwn(Textblocks, node.name)) {
|
|
2181
|
+
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state.doc);
|
|
2182
|
+
} else if (Object.hasOwn(InlineMarker, node.name)) {
|
|
2183
|
+
const sNode = node.node;
|
|
2184
|
+
if (node.from < from && node.to <= to) {
|
|
2185
|
+
if (sNode.firstChild.to === from) {
|
|
2186
|
+
from = node.from;
|
|
2187
|
+
} else {
|
|
2188
|
+
cutStyles.push(sNode);
|
|
2189
|
+
}
|
|
2190
|
+
} else if (node.from >= from && node.to > to) {
|
|
2191
|
+
if (sNode.lastChild.from === to) {
|
|
2192
|
+
to = node.to;
|
|
2193
|
+
} else {
|
|
2194
|
+
cutStyles.push(sNode);
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
});
|
|
2200
|
+
if (okay === null) {
|
|
2201
|
+
const line = state.doc.lineAt(from);
|
|
2202
|
+
okay = to <= line.to && !/\S/.test(line.text.slice(from - line.from));
|
|
2203
|
+
}
|
|
2204
|
+
if (!okay) {
|
|
2205
|
+
return {
|
|
2206
|
+
range
|
|
2207
|
+
};
|
|
2208
|
+
}
|
|
2209
|
+
const changes2 = [];
|
|
2210
|
+
const changesAfter = [];
|
|
2211
|
+
removeLinkInner(from, to, changesAfter, state);
|
|
2212
|
+
let cursorOffset = 1;
|
|
2213
|
+
for (const style of cutStyles) {
|
|
2214
|
+
const type = InlineMarker[style.name];
|
|
2215
|
+
const mark2 = inlineMarkerText(type);
|
|
2216
|
+
if (style.from < from) {
|
|
2217
|
+
changes2.push({
|
|
2218
|
+
from: skipSpaces(from, state.doc, -1),
|
|
2219
|
+
insert: mark2
|
|
2220
|
+
});
|
|
2221
|
+
changesAfter.push({
|
|
2222
|
+
from: skipSpaces(from, state.doc, 1, to),
|
|
2223
|
+
insert: mark2
|
|
2224
|
+
});
|
|
2225
|
+
} else {
|
|
2226
|
+
changes2.push({
|
|
2227
|
+
from: skipSpaces(to, state.doc, -1, from),
|
|
2228
|
+
insert: mark2
|
|
2229
|
+
});
|
|
2230
|
+
const after = skipSpaces(to, state.doc, 1);
|
|
2231
|
+
if (after === to) {
|
|
2232
|
+
cursorOffset += mark2.length;
|
|
2233
|
+
}
|
|
2234
|
+
changesAfter.push({
|
|
2235
|
+
from: after,
|
|
2236
|
+
insert: mark2
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
changes2.push({
|
|
2241
|
+
from,
|
|
2242
|
+
insert: "["
|
|
2243
|
+
}, {
|
|
2244
|
+
from: to,
|
|
2245
|
+
insert: "]()"
|
|
2246
|
+
});
|
|
2247
|
+
const changeSet = state.changes(changes2.concat(changesAfter));
|
|
2248
|
+
return {
|
|
2249
|
+
changes: changeSet,
|
|
2250
|
+
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset)
|
|
2251
|
+
};
|
|
2252
|
+
});
|
|
2253
|
+
if (changes.changes.empty) {
|
|
2254
|
+
return false;
|
|
2255
|
+
}
|
|
2256
|
+
dispatch(state.update(changes, {
|
|
2257
|
+
userEvent: "format.link.add",
|
|
2258
|
+
scrollIntoView: true
|
|
2259
|
+
}));
|
|
2260
|
+
return true;
|
|
2261
|
+
};
|
|
2262
|
+
var addList = (type) => ({ state, dispatch }) => {
|
|
2263
|
+
let lastBlock = -1;
|
|
2264
|
+
let counter = 1;
|
|
2265
|
+
let first = true;
|
|
2266
|
+
let parentColumn = null;
|
|
2267
|
+
const blocks = [];
|
|
2268
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2269
|
+
syntaxTree2(state).iterate({
|
|
2270
|
+
from,
|
|
2271
|
+
to,
|
|
2272
|
+
enter: (node) => {
|
|
2273
|
+
if (Object.hasOwn(Textblocks, node.name) && node.name !== "TableCell" || node.name === "Table") {
|
|
2274
|
+
if (first) {
|
|
2275
|
+
let before = node.node.prevSibling;
|
|
2276
|
+
while (before && /Mark$/.test(before.name)) {
|
|
2277
|
+
before = before.prevSibling;
|
|
2278
|
+
}
|
|
2279
|
+
if (before?.name === (type === 0 ? "OrderedList" : "BulletList")) {
|
|
2280
|
+
const item = before.lastChild;
|
|
2281
|
+
const itemLine = state.doc.lineAt(item.from);
|
|
2282
|
+
const itemText = itemLine.text.slice(item.from - itemLine.from);
|
|
2283
|
+
parentColumn = item.from - itemLine.from + /^\s*/.exec(itemText)[0].length;
|
|
2284
|
+
if (type === 0) {
|
|
2285
|
+
const mark2 = /^\s*(\d+)[.)]/.exec(itemText);
|
|
2286
|
+
if (mark2) {
|
|
2287
|
+
parentColumn += mark2[1].length;
|
|
2288
|
+
counter = +mark2[1] + 1;
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
first = false;
|
|
2293
|
+
}
|
|
2294
|
+
if (node.from === lastBlock) {
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
lastBlock = node.from;
|
|
2298
|
+
blocks.push({
|
|
2299
|
+
node: node.node,
|
|
2300
|
+
counter,
|
|
2301
|
+
parentColumn
|
|
2302
|
+
});
|
|
2303
|
+
counter++;
|
|
2304
|
+
return false;
|
|
2305
|
+
}
|
|
2306
|
+
},
|
|
2307
|
+
leave: (node) => {
|
|
2308
|
+
if (node.name === "BulletList" || node.name === "OrderedList" || node.name === "Blockquote") {
|
|
2309
|
+
counter = 1;
|
|
2310
|
+
parentColumn = null;
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
if (!blocks.length) {
|
|
2316
|
+
const { from, to } = state.doc.lineAt(state.selection.main.anchor);
|
|
2317
|
+
if (from === to) {
|
|
2318
|
+
dispatch(state.update({
|
|
2319
|
+
changes: [
|
|
2320
|
+
{
|
|
2321
|
+
from,
|
|
2322
|
+
insert: type === 1 ? "- " : type === 0 ? "1. " : "- [ ] "
|
|
2323
|
+
}
|
|
2324
|
+
],
|
|
2325
|
+
userEvent: "format.list.add",
|
|
2326
|
+
scrollIntoView: true
|
|
2327
|
+
}));
|
|
2328
|
+
return true;
|
|
2329
|
+
}
|
|
2330
|
+
return false;
|
|
2331
|
+
}
|
|
2332
|
+
const changes = [];
|
|
2333
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
2334
|
+
const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
|
|
2335
|
+
const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
|
|
2336
|
+
let padding = nodeFrom > 0 && !/\s/.test(state.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
|
|
2337
|
+
if (type === 0) {
|
|
2338
|
+
padding += String(counter2).length;
|
|
2339
|
+
}
|
|
2340
|
+
let line = state.doc.lineAt(nodeFrom);
|
|
2341
|
+
const column = nodeFrom - line.from;
|
|
2342
|
+
if (parentColumn2 !== null && parentColumn2 > column) {
|
|
2343
|
+
padding = Math.max(padding, parentColumn2 - column);
|
|
2344
|
+
}
|
|
2345
|
+
let mark2;
|
|
2346
|
+
if (type === 0) {
|
|
2347
|
+
let max = counter2;
|
|
2348
|
+
for (let j = i + 1; j < blocks.length; j++) {
|
|
2349
|
+
if (blocks[j].counter !== max + 1) {
|
|
2350
|
+
break;
|
|
2351
|
+
}
|
|
2352
|
+
max++;
|
|
2353
|
+
}
|
|
2354
|
+
const num = String(counter2);
|
|
2355
|
+
padding = Math.max(String(max).length, padding);
|
|
2356
|
+
mark2 = " ".repeat(Math.max(0, padding - num.length)) + num + ". ";
|
|
2357
|
+
} else {
|
|
2358
|
+
mark2 = " ".repeat(padding) + "- " + (type === 2 ? "[ ] " : "");
|
|
2359
|
+
}
|
|
2360
|
+
changes.push({
|
|
2361
|
+
from: nodeFrom,
|
|
2362
|
+
insert: mark2
|
|
2363
|
+
});
|
|
2364
|
+
while (line.to < node.to) {
|
|
2365
|
+
line = state.doc.lineAt(line.to + 1);
|
|
2366
|
+
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2367
|
+
changes.push({
|
|
2368
|
+
from: line.from + Math.min(open, column),
|
|
2369
|
+
insert: " ".repeat(mark2.length)
|
|
2370
|
+
});
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
if (type === 0) {
|
|
2374
|
+
const last = blocks[blocks.length - 1];
|
|
2375
|
+
let next = last.node.nextSibling;
|
|
2376
|
+
while (next && /Mark$/.test(next.name)) {
|
|
2377
|
+
next = next.nextSibling;
|
|
2378
|
+
}
|
|
2379
|
+
if (next?.name === "OrderedList") {
|
|
2380
|
+
renumberListItems(next.firstChild, last.counter + 1, changes, state.doc);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
dispatch(state.update({
|
|
2384
|
+
changes,
|
|
2385
|
+
userEvent: "format.list.add",
|
|
2386
|
+
scrollIntoView: true
|
|
2387
|
+
}));
|
|
2388
|
+
return true;
|
|
2389
|
+
};
|
|
2390
|
+
var removeList = (type) => ({ state, dispatch }) => {
|
|
2391
|
+
let lastBlock = -1;
|
|
2392
|
+
const changes = [];
|
|
2393
|
+
const stack = [];
|
|
2394
|
+
const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
|
|
2395
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2396
|
+
syntaxTree2(state).iterate({
|
|
2397
|
+
from,
|
|
2398
|
+
to,
|
|
2399
|
+
enter: (node) => {
|
|
2400
|
+
const { name } = node;
|
|
2401
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2402
|
+
stack.push(name);
|
|
2403
|
+
} else if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
2404
|
+
stack[stack.length - 1] = "TaskList";
|
|
2405
|
+
}
|
|
2406
|
+
},
|
|
2407
|
+
leave: (node) => {
|
|
2408
|
+
const { name } = node;
|
|
2409
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2410
|
+
stack.pop();
|
|
2411
|
+
} else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
|
|
2412
|
+
lastBlock = node.from;
|
|
2413
|
+
let line = state.doc.lineAt(node.from);
|
|
2414
|
+
const mark2 = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
|
|
2415
|
+
if (!mark2) {
|
|
2416
|
+
return false;
|
|
2417
|
+
}
|
|
2418
|
+
const column = node.from - line.from;
|
|
2419
|
+
changes.push({
|
|
2420
|
+
from: node.from,
|
|
2421
|
+
to: node.from + mark2[0].length
|
|
2422
|
+
});
|
|
2423
|
+
while (line.to < node.to) {
|
|
2424
|
+
line = state.doc.lineAt(line.to + 1);
|
|
2425
|
+
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2426
|
+
if (open > column) {
|
|
2427
|
+
changes.push({
|
|
2428
|
+
from: line.from + column,
|
|
2429
|
+
to: line.from + Math.min(column + mark2[0].length, open)
|
|
2430
|
+
});
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
if (node.to >= to) {
|
|
2434
|
+
renumberListItems(node.node.nextSibling, 1, changes, state.doc);
|
|
2435
|
+
}
|
|
2436
|
+
return false;
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
});
|
|
2440
|
+
}
|
|
2441
|
+
if (!changes.length) {
|
|
2442
|
+
return false;
|
|
2443
|
+
}
|
|
2444
|
+
dispatch(state.update({
|
|
2445
|
+
changes,
|
|
2446
|
+
userEvent: "format.list.remove",
|
|
2447
|
+
scrollIntoView: true
|
|
2448
|
+
}));
|
|
2449
|
+
return true;
|
|
2450
|
+
};
|
|
2451
|
+
var toggleList = (type) => (target) => {
|
|
2452
|
+
const formatting2 = getFormatting(target.state);
|
|
2453
|
+
const active = formatting2.listStyle === (type === 1 ? "bullet" : type === 0 ? "ordered" : "task");
|
|
2454
|
+
return (active ? removeList(type) : addList(type))(target);
|
|
2455
|
+
};
|
|
2456
|
+
var renumberListItems = (item, counter, changes, doc) => {
|
|
2457
|
+
for (; item; item = item.nextSibling) {
|
|
2458
|
+
if (item.name === "ListItem") {
|
|
2459
|
+
const number = /(\s*)(\d+)[.)]/.exec(doc.sliceString(item.from, item.from + 10));
|
|
2460
|
+
if (!number || +number[2] === counter) {
|
|
2461
|
+
break;
|
|
2462
|
+
}
|
|
2463
|
+
const size = number[1].length + number[2].length;
|
|
2464
|
+
const newNum = String(counter);
|
|
2465
|
+
changes.push({
|
|
2466
|
+
from: item.from + Math.max(0, size - newNum.length),
|
|
2467
|
+
to: item.from + size,
|
|
2468
|
+
insert: newNum
|
|
2469
|
+
});
|
|
2470
|
+
counter++;
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
};
|
|
2474
|
+
var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
2475
|
+
const lines = [];
|
|
2476
|
+
let lastBlock = -1;
|
|
2477
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2478
|
+
syntaxTree2(state).iterate({
|
|
2479
|
+
from,
|
|
2480
|
+
to,
|
|
2481
|
+
enter: (node) => {
|
|
2482
|
+
if (Object.hasOwn(Textblocks, node.name) || node.name === "Table") {
|
|
2483
|
+
if (node.from === lastBlock) {
|
|
2484
|
+
return false;
|
|
2485
|
+
}
|
|
2486
|
+
lastBlock = node.from;
|
|
2487
|
+
let line = state.doc.lineAt(node.from);
|
|
2488
|
+
if (line.number > 1) {
|
|
2489
|
+
const prevLine = state.doc.line(line.number - 1);
|
|
2490
|
+
if (/^[>\s]*$/.test(prevLine.text)) {
|
|
2491
|
+
if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
|
|
2492
|
+
lines.push(prevLine);
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
for (; ; ) {
|
|
2497
|
+
lines.push(line);
|
|
2498
|
+
if (line.to >= node.to) {
|
|
2499
|
+
break;
|
|
2500
|
+
}
|
|
2501
|
+
line = state.doc.line(line.number + 1);
|
|
2502
|
+
}
|
|
2503
|
+
if (!enable && line.number < state.doc.lines) {
|
|
2504
|
+
const nextLine = state.doc.line(line.number + 1);
|
|
2505
|
+
if (/^[>\s]*$/.test(nextLine.text)) {
|
|
2506
|
+
lines.push(nextLine);
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
return false;
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2514
|
+
const changes = [];
|
|
2515
|
+
for (const line of lines) {
|
|
2516
|
+
if (enable) {
|
|
2517
|
+
changes.push({
|
|
2518
|
+
from: line.from,
|
|
2519
|
+
insert: /\S/.test(line.text) ? "> " : ">"
|
|
2520
|
+
});
|
|
2521
|
+
} else {
|
|
2522
|
+
const quote = /((?:[\s>\-+*]|\d+[.)])*?)> ?/.exec(line.text);
|
|
2523
|
+
if (quote) {
|
|
2524
|
+
changes.push({
|
|
2525
|
+
from: line.from + quote[1].length,
|
|
2526
|
+
to: line.from + quote[0].length
|
|
2527
|
+
});
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
if (!changes.length) {
|
|
2532
|
+
return false;
|
|
2533
|
+
}
|
|
2534
|
+
dispatch(state.update({
|
|
2535
|
+
changes,
|
|
2536
|
+
userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
|
|
2537
|
+
scrollIntoView: true
|
|
2538
|
+
}));
|
|
2539
|
+
return true;
|
|
2540
|
+
};
|
|
2541
|
+
var addBlockquote = setBlockquote(true);
|
|
2542
|
+
var removeBlockquote = setBlockquote(false);
|
|
2543
|
+
var toggleBlockquote = (target) => {
|
|
2544
|
+
return (getFormatting(target.state).blockQuote ? removeBlockquote : addBlockquote)(target);
|
|
2545
|
+
};
|
|
2546
|
+
var addCodeblock = (target) => {
|
|
2547
|
+
const { state, dispatch } = target;
|
|
2548
|
+
const { selection } = state;
|
|
2549
|
+
if (selection.ranges.length === 1 && selection.main.empty) {
|
|
2550
|
+
const { head } = selection.main;
|
|
2551
|
+
const line = state.doc.lineAt(head);
|
|
2552
|
+
if (!/\S/.test(line.text) && head === line.from) {
|
|
2553
|
+
snippets.codeblock(target, null, line.from, line.to);
|
|
2554
|
+
return true;
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
const ranges = [];
|
|
2558
|
+
for (const { from, to } of selection.ranges) {
|
|
2559
|
+
let blockFrom = from;
|
|
2560
|
+
let blockTo = to;
|
|
2561
|
+
syntaxTree2(state).iterate({
|
|
2562
|
+
from,
|
|
2563
|
+
to,
|
|
2564
|
+
enter: (node) => {
|
|
2565
|
+
if (Object.hasOwn(Textblocks, node.name)) {
|
|
2566
|
+
if (from >= node.from && to <= node.to) {
|
|
2567
|
+
blockFrom = node.from;
|
|
2568
|
+
blockTo = node.to;
|
|
2569
|
+
} else {
|
|
2570
|
+
blockFrom = Math.min(blockFrom, state.doc.lineAt(node.from).from);
|
|
2571
|
+
blockTo = Math.max(blockTo, state.doc.lineAt(node.to).to);
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
});
|
|
2576
|
+
if (ranges.length && ranges[ranges.length - 1].to >= blockFrom - 1) {
|
|
2577
|
+
ranges[ranges.length - 1].to = blockTo;
|
|
2578
|
+
} else {
|
|
2579
|
+
ranges.push({
|
|
2580
|
+
from: blockFrom,
|
|
2581
|
+
to: blockTo
|
|
2582
|
+
});
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
if (!ranges.length) {
|
|
2586
|
+
return false;
|
|
2587
|
+
}
|
|
2588
|
+
const changes = ranges.map(({ from, to }) => {
|
|
2589
|
+
const column = from - state.doc.lineAt(from).from;
|
|
2590
|
+
return [
|
|
2591
|
+
{
|
|
2592
|
+
from,
|
|
2593
|
+
insert: "```\n" + " ".repeat(column)
|
|
2594
|
+
},
|
|
2595
|
+
{
|
|
2596
|
+
from: to,
|
|
2597
|
+
insert: "\n" + " ".repeat(column) + "```"
|
|
2598
|
+
}
|
|
2599
|
+
];
|
|
2600
|
+
});
|
|
2601
|
+
dispatch(state.update({
|
|
2602
|
+
changes,
|
|
2603
|
+
userEvent: "format.codeblock.add",
|
|
2604
|
+
scrollIntoView: true
|
|
2605
|
+
}));
|
|
2606
|
+
return true;
|
|
2607
|
+
};
|
|
2608
|
+
var removeCodeblock = ({ state, dispatch }) => {
|
|
2609
|
+
const changes = [];
|
|
2610
|
+
let lastBlock = -1;
|
|
2611
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2612
|
+
syntaxTree2(state).iterate({
|
|
2613
|
+
from,
|
|
2614
|
+
to,
|
|
2615
|
+
enter: (node) => {
|
|
2616
|
+
if (Textblocks[node.name] === "codeblock" && lastBlock !== node.from) {
|
|
2617
|
+
lastBlock = node.from;
|
|
2618
|
+
const firstLine = state.doc.lineAt(node.from);
|
|
2619
|
+
if (node.name === "FencedCode") {
|
|
2620
|
+
changes.push({
|
|
2621
|
+
from: node.from,
|
|
2622
|
+
to: firstLine.to + 1 + node.from - firstLine.from
|
|
2623
|
+
});
|
|
2624
|
+
const lastLine = state.doc.lineAt(node.to);
|
|
2625
|
+
if (/^([\s>]|[-*+] |\d+[).])*`+$/.test(lastLine.text)) {
|
|
2626
|
+
changes.push({
|
|
2627
|
+
from: lastLine.from - (lastLine.number === firstLine.number + 1 ? 0 : 1),
|
|
2628
|
+
to: lastLine.to
|
|
2629
|
+
});
|
|
2630
|
+
}
|
|
2631
|
+
} else {
|
|
2632
|
+
const column = node.from - firstLine.from;
|
|
2633
|
+
for (let line = firstLine; ; line = state.doc.line(line.number + 1)) {
|
|
2634
|
+
changes.push({
|
|
2635
|
+
from: line.from + column - 4,
|
|
2636
|
+
to: line.from + column
|
|
2637
|
+
});
|
|
2638
|
+
if (line.to >= node.to) {
|
|
2639
|
+
break;
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
});
|
|
2646
|
+
}
|
|
2647
|
+
if (!changes.length) {
|
|
2648
|
+
return false;
|
|
2649
|
+
}
|
|
2650
|
+
dispatch(state.update({
|
|
2651
|
+
changes,
|
|
2652
|
+
userEvent: "format.codeblock.remove",
|
|
2653
|
+
scrollIntoView: true
|
|
2654
|
+
}));
|
|
2655
|
+
return true;
|
|
2656
|
+
};
|
|
2657
|
+
var toggleCodeblock = (target) => {
|
|
2658
|
+
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
1893
2659
|
};
|
|
1894
2660
|
var formatting = (options = {}) => {
|
|
1895
2661
|
return [
|
|
1896
2662
|
keymap5.of([
|
|
1897
2663
|
{
|
|
1898
2664
|
key: "meta-b",
|
|
1899
|
-
run:
|
|
2665
|
+
run: toggleStrong
|
|
1900
2666
|
}
|
|
1901
2667
|
]),
|
|
1902
2668
|
styling()
|
|
@@ -1950,6 +2716,209 @@ var styling = () => {
|
|
|
1950
2716
|
})
|
|
1951
2717
|
];
|
|
1952
2718
|
};
|
|
2719
|
+
var InlineMarker = {
|
|
2720
|
+
Emphasis: 1,
|
|
2721
|
+
StrongEmphasis: 0,
|
|
2722
|
+
InlineCode: 3,
|
|
2723
|
+
Strikethrough: 2
|
|
2724
|
+
};
|
|
2725
|
+
var IgnoreInline = /* @__PURE__ */ new Set([
|
|
2726
|
+
"Autolink",
|
|
2727
|
+
"CodeMark",
|
|
2728
|
+
"CodeText",
|
|
2729
|
+
"Comment",
|
|
2730
|
+
"EmphasisMark",
|
|
2731
|
+
"Hardbreak",
|
|
2732
|
+
"HeaderMark",
|
|
2733
|
+
"HTMLTag",
|
|
2734
|
+
"LinkMark",
|
|
2735
|
+
"ListMark",
|
|
2736
|
+
"ProcessingInstruction",
|
|
2737
|
+
"QuoteMark",
|
|
2738
|
+
"StrikethroughMark",
|
|
2739
|
+
"SubscriptMark",
|
|
2740
|
+
"SuperscriptMark",
|
|
2741
|
+
"TaskMarker"
|
|
2742
|
+
]);
|
|
2743
|
+
var Textblocks = {
|
|
2744
|
+
ATXHeading1: "heading1",
|
|
2745
|
+
ATXHeading2: "heading2",
|
|
2746
|
+
ATXHeading3: "heading3",
|
|
2747
|
+
ATXHeading4: "heading4",
|
|
2748
|
+
ATXHeading5: "heading5",
|
|
2749
|
+
ATXHeading6: "heading6",
|
|
2750
|
+
CodeBlock: "codeblock",
|
|
2751
|
+
FencedCode: "codeblock",
|
|
2752
|
+
Paragraph: "paragraph",
|
|
2753
|
+
SetextHeading1: "heading1",
|
|
2754
|
+
SetextHeading2: "heading2",
|
|
2755
|
+
TableCell: "tablecell",
|
|
2756
|
+
Task: "paragraph"
|
|
2757
|
+
};
|
|
2758
|
+
var getFormatting = (state) => {
|
|
2759
|
+
let blockType = null;
|
|
2760
|
+
const inline = [
|
|
2761
|
+
null,
|
|
2762
|
+
null,
|
|
2763
|
+
null,
|
|
2764
|
+
null
|
|
2765
|
+
];
|
|
2766
|
+
let link2 = false;
|
|
2767
|
+
let blockQuote = null;
|
|
2768
|
+
let listStyle = null;
|
|
2769
|
+
const stack = [];
|
|
2770
|
+
let currentBlock = null;
|
|
2771
|
+
const advanceInline = (upto) => {
|
|
2772
|
+
if (!currentBlock) {
|
|
2773
|
+
return;
|
|
2774
|
+
}
|
|
2775
|
+
upto = Math.min(upto, currentBlock.end);
|
|
2776
|
+
if (upto <= currentBlock.pos) {
|
|
2777
|
+
return;
|
|
2778
|
+
}
|
|
2779
|
+
for (let i = 0; i < currentBlock.active.length; i++) {
|
|
2780
|
+
if (inline[i] === false) {
|
|
2781
|
+
continue;
|
|
2782
|
+
} else if (currentBlock.active[i]) {
|
|
2783
|
+
inline[i] = true;
|
|
2784
|
+
} else if (/\S/.test(state.doc.sliceString(currentBlock.pos, upto))) {
|
|
2785
|
+
inline[i] = false;
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
currentBlock.pos = upto;
|
|
2789
|
+
};
|
|
2790
|
+
const skipInline = (upto) => {
|
|
2791
|
+
if (currentBlock && upto > currentBlock.pos) {
|
|
2792
|
+
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
2793
|
+
}
|
|
2794
|
+
};
|
|
2795
|
+
const { selection } = state;
|
|
2796
|
+
for (const range of selection.ranges) {
|
|
2797
|
+
if (range.empty && inline.some((v) => v === null)) {
|
|
2798
|
+
const contextSize = Math.min(range.head, 6);
|
|
2799
|
+
const contextBefore = state.doc.sliceString(range.head - contextSize, range.head);
|
|
2800
|
+
let contextAfter = state.doc.sliceString(range.head, range.head + contextSize);
|
|
2801
|
+
for (let i = 0; i < contextSize; i++) {
|
|
2802
|
+
const ch = contextAfter[i];
|
|
2803
|
+
if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
|
|
2804
|
+
contextAfter = contextAfter.slice(0, i);
|
|
2805
|
+
break;
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
for (let i = 0; i < inline.length; i++) {
|
|
2809
|
+
const mark2 = inlineMarkerText(i);
|
|
2810
|
+
const found = contextAfter.indexOf(mark2);
|
|
2811
|
+
if (found > -1) {
|
|
2812
|
+
contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found + mark2.length);
|
|
2813
|
+
if (inline[i] === null) {
|
|
2814
|
+
inline[i] = true;
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
syntaxTree2(state).iterate({
|
|
2820
|
+
from: range.from,
|
|
2821
|
+
to: range.to,
|
|
2822
|
+
enter: (node) => {
|
|
2823
|
+
advanceInline(node.from);
|
|
2824
|
+
const { name } = node;
|
|
2825
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2826
|
+
stack.push(name);
|
|
2827
|
+
} else if (name === "Link") {
|
|
2828
|
+
link2 = true;
|
|
2829
|
+
} else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
|
|
2830
|
+
if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
2831
|
+
stack[stack.length - 1] = "TaskList";
|
|
2832
|
+
}
|
|
2833
|
+
const blockCode = Textblocks[name];
|
|
2834
|
+
if (blockType === null) {
|
|
2835
|
+
blockType = blockCode;
|
|
2836
|
+
} else if (blockType !== blockCode) {
|
|
2837
|
+
blockType = false;
|
|
2838
|
+
}
|
|
2839
|
+
if (blockCode !== "codeblock" && inline.some((i) => i !== false)) {
|
|
2840
|
+
currentBlock = {
|
|
2841
|
+
pos: Math.max(range.from, node.from),
|
|
2842
|
+
end: Math.min(range.to, node.to),
|
|
2843
|
+
active: [
|
|
2844
|
+
false,
|
|
2845
|
+
false,
|
|
2846
|
+
false,
|
|
2847
|
+
false
|
|
2848
|
+
]
|
|
2849
|
+
};
|
|
2850
|
+
}
|
|
2851
|
+
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
2852
|
+
const index = InlineMarker[name];
|
|
2853
|
+
if (range.empty && inline[index] === null) {
|
|
2854
|
+
inline[index] = true;
|
|
2855
|
+
}
|
|
2856
|
+
currentBlock.active[index] = true;
|
|
2857
|
+
} else if (IgnoreInline.has(name)) {
|
|
2858
|
+
skipInline(node.to);
|
|
2859
|
+
}
|
|
2860
|
+
},
|
|
2861
|
+
leave: (node) => {
|
|
2862
|
+
advanceInline(node.to);
|
|
2863
|
+
const { name } = node;
|
|
2864
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2865
|
+
stack.pop();
|
|
2866
|
+
} else if (Object.hasOwn(Textblocks, name)) {
|
|
2867
|
+
let hasList = false;
|
|
2868
|
+
let hasQuote = false;
|
|
2869
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
2870
|
+
if (stack[i] === "Blockquote") {
|
|
2871
|
+
hasQuote = true;
|
|
2872
|
+
} else if (!hasList) {
|
|
2873
|
+
hasList = stack[i] === "TaskList" ? "task" : stack[i] === "BulletList" ? "bullet" : "ordered";
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
if (blockQuote === null) {
|
|
2877
|
+
blockQuote = hasQuote;
|
|
2878
|
+
} else if (!hasQuote && blockQuote) {
|
|
2879
|
+
blockQuote = false;
|
|
2880
|
+
}
|
|
2881
|
+
if (listStyle === null) {
|
|
2882
|
+
listStyle = hasList;
|
|
2883
|
+
} else if (listStyle !== hasList) {
|
|
2884
|
+
listStyle = false;
|
|
2885
|
+
}
|
|
2886
|
+
currentBlock = null;
|
|
2887
|
+
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
2888
|
+
currentBlock.active[InlineMarker[name]] = false;
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
});
|
|
2892
|
+
}
|
|
2893
|
+
const { from, to } = state.doc.lineAt(selection.main.anchor);
|
|
2894
|
+
const blankLine = from === to;
|
|
2895
|
+
return {
|
|
2896
|
+
blankLine,
|
|
2897
|
+
blockType: blockType || null,
|
|
2898
|
+
blockQuote: blockQuote ?? false,
|
|
2899
|
+
code: inline[3] ?? false,
|
|
2900
|
+
emphasis: inline[1] ?? false,
|
|
2901
|
+
strong: inline[0] ?? false,
|
|
2902
|
+
strikethrough: inline[2] ?? false,
|
|
2903
|
+
link: link2,
|
|
2904
|
+
listStyle: listStyle || null
|
|
2905
|
+
};
|
|
2906
|
+
};
|
|
2907
|
+
var useFormattingState = () => {
|
|
2908
|
+
const [state, setState] = useState(null);
|
|
2909
|
+
const observer = useMemo(() => EditorView9.updateListener.of((update2) => {
|
|
2910
|
+
if (update2.docChanged || update2.selectionSet) {
|
|
2911
|
+
const newState = getFormatting(update2.state);
|
|
2912
|
+
if (!state || !compareFormatting(state, newState)) {
|
|
2913
|
+
setState(newState);
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
}), []);
|
|
2917
|
+
return [
|
|
2918
|
+
state,
|
|
2919
|
+
observer
|
|
2920
|
+
];
|
|
2921
|
+
};
|
|
1953
2922
|
|
|
1954
2923
|
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1955
2924
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
@@ -2002,8 +2971,8 @@ var heading2 = () => {
|
|
|
2002
2971
|
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
2003
2972
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2004
2973
|
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2005
|
-
import { Decoration as Decoration6, EditorView as
|
|
2006
|
-
var styles4 =
|
|
2974
|
+
import { Decoration as Decoration6, EditorView as EditorView10, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
2975
|
+
var styles4 = EditorView10.baseTheme({
|
|
2007
2976
|
"& .cm-hr": {
|
|
2008
2977
|
// Note that block-level decorations should not have vertical margins,
|
|
2009
2978
|
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
@@ -2057,7 +3026,7 @@ var hr = () => {
|
|
|
2057
3026
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
2058
3027
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2059
3028
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
2060
|
-
import { Decoration as Decoration7, EditorView as
|
|
3029
|
+
import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
2061
3030
|
var image = (options = {}) => {
|
|
2062
3031
|
return StateField3.define({
|
|
2063
3032
|
create: (state) => {
|
|
@@ -2084,7 +3053,7 @@ var image = (options = {}) => {
|
|
|
2084
3053
|
add: buildDecorations4(from, to, tr.state)
|
|
2085
3054
|
});
|
|
2086
3055
|
},
|
|
2087
|
-
provide: (field) =>
|
|
3056
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
2088
3057
|
});
|
|
2089
3058
|
};
|
|
2090
3059
|
var buildDecorations4 = (from, to, state) => {
|
|
@@ -2266,12 +3235,12 @@ var buildDecorations5 = (view, options) => {
|
|
|
2266
3235
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2267
3236
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
2268
3237
|
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
|
|
2269
|
-
import { Decoration as Decoration9, EditorView as
|
|
3238
|
+
import { Decoration as Decoration9, EditorView as EditorView12, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
2270
3239
|
var table = (options = {}) => {
|
|
2271
3240
|
return StateField4.define({
|
|
2272
3241
|
create: (state) => update(state, options),
|
|
2273
3242
|
update: (_, tr) => update(tr.state, options),
|
|
2274
|
-
provide: (field) =>
|
|
3243
|
+
provide: (field) => EditorView12.decorations.from(field)
|
|
2275
3244
|
});
|
|
2276
3245
|
};
|
|
2277
3246
|
var update = (state, options) => {
|
|
@@ -2364,8 +3333,8 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2364
3333
|
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2365
3334
|
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
2366
3335
|
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
2367
|
-
import { EditorView as
|
|
2368
|
-
var styles5 =
|
|
3336
|
+
import { EditorView as EditorView13, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
3337
|
+
var styles5 = EditorView13.baseTheme({
|
|
2369
3338
|
"& .cm-task": {
|
|
2370
3339
|
color: getToken("extend.colors.blue.500")
|
|
2371
3340
|
},
|
|
@@ -2590,11 +3559,11 @@ var defaultTheme = {
|
|
|
2590
3559
|
fontSize: "16px"
|
|
2591
3560
|
},
|
|
2592
3561
|
"&light .cm-content": {
|
|
2593
|
-
color: get3(tokens, "extend.
|
|
3562
|
+
color: get3(tokens, "extend.semanticColors.base.fg.light", "black"),
|
|
2594
3563
|
caretColor: "black"
|
|
2595
3564
|
},
|
|
2596
3565
|
"&dark .cm-content": {
|
|
2597
|
-
color: get3(tokens, "extend.
|
|
3566
|
+
color: get3(tokens, "extend.semanticColors.base.fg.dark", "white"),
|
|
2598
3567
|
caretColor: "white"
|
|
2599
3568
|
},
|
|
2600
3569
|
//
|
|
@@ -2606,8 +3575,11 @@ var defaultTheme = {
|
|
|
2606
3575
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2607
3576
|
borderLeft: "2px solid white"
|
|
2608
3577
|
},
|
|
2609
|
-
".cm-placeholder": {
|
|
2610
|
-
|
|
3578
|
+
"&light .cm-placeholder": {
|
|
3579
|
+
color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
3580
|
+
},
|
|
3581
|
+
"&dark .cm-placeholder": {
|
|
3582
|
+
color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
2611
3583
|
},
|
|
2612
3584
|
//
|
|
2613
3585
|
// line
|
|
@@ -2795,7 +3767,7 @@ var EditorModes = [
|
|
|
2795
3767
|
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2796
3768
|
const { themeMode } = useThemeContext();
|
|
2797
3769
|
const rootRef = useRef(null);
|
|
2798
|
-
const [view, setView] =
|
|
3770
|
+
const [view, setView] = useState2(null);
|
|
2799
3771
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2800
3772
|
view
|
|
2801
3773
|
]);
|
|
@@ -2824,7 +3796,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2824
3796
|
selection,
|
|
2825
3797
|
extensions: [
|
|
2826
3798
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2827
|
-
|
|
3799
|
+
EditorView14.exceptionSink.of((err) => {
|
|
2828
3800
|
log2.catch(err, void 0, {
|
|
2829
3801
|
F: __dxlog_file3,
|
|
2830
3802
|
L: 134,
|
|
@@ -2834,17 +3806,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2834
3806
|
}),
|
|
2835
3807
|
// Theme.
|
|
2836
3808
|
// TODO(burdon): Make configurable.
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
3809
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3810
|
+
EditorView14.theme(theme ?? {}),
|
|
3811
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3812
|
+
EditorView14.editorAttributes.of({
|
|
2841
3813
|
class: slots.editor?.className ?? ""
|
|
2842
3814
|
}),
|
|
2843
|
-
|
|
3815
|
+
EditorView14.contentAttributes.of({
|
|
2844
3816
|
class: slots.content?.className ?? ""
|
|
2845
3817
|
}),
|
|
2846
3818
|
// State.
|
|
2847
|
-
|
|
3819
|
+
EditorView14.editable.of(!readonly),
|
|
2848
3820
|
EditorState2.readOnly.of(!!readonly),
|
|
2849
3821
|
// Storage and replication.
|
|
2850
3822
|
// NOTE: This must come before user extensions.
|
|
@@ -2855,7 +3827,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2855
3827
|
...extensions
|
|
2856
3828
|
].filter(isNotFalsy3)
|
|
2857
3829
|
});
|
|
2858
|
-
const newView = new
|
|
3830
|
+
const newView = new EditorView14({
|
|
2859
3831
|
state,
|
|
2860
3832
|
parent: rootRef.current,
|
|
2861
3833
|
scrollTo,
|
|
@@ -2948,11 +3920,10 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2948
3920
|
});
|
|
2949
3921
|
var defaultSlots = {
|
|
2950
3922
|
root: {
|
|
2951
|
-
|
|
2952
|
-
className: mx3("flex flex-col grow overflow-y-auto", attentionSurface)
|
|
3923
|
+
className: mx3("grow", focusRing)
|
|
2953
3924
|
},
|
|
2954
3925
|
editor: {
|
|
2955
|
-
className: "
|
|
3926
|
+
className: "bs-full"
|
|
2956
3927
|
}
|
|
2957
3928
|
};
|
|
2958
3929
|
var defaultTextSlots = {
|
|
@@ -2963,35 +3934,49 @@ var defaultMarkdownSlots = {
|
|
|
2963
3934
|
};
|
|
2964
3935
|
|
|
2965
3936
|
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
2966
|
-
import {
|
|
3937
|
+
import { CaretRight, ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic } from "@phosphor-icons/react";
|
|
2967
3938
|
import { createContext } from "@radix-ui/react-context";
|
|
2968
3939
|
import React2 from "react";
|
|
2969
3940
|
import { Button, DensityProvider, Select } from "@dxos/react-ui";
|
|
2970
|
-
import { getSize } from "@dxos/react-ui-theme";
|
|
3941
|
+
import { getSize, mx as mx4 } from "@dxos/react-ui-theme";
|
|
3942
|
+
var HeadingIcons = {
|
|
3943
|
+
"0": Paragraph,
|
|
3944
|
+
"1": TextHOne,
|
|
3945
|
+
"2": TextHTwo,
|
|
3946
|
+
"3": TextHThree,
|
|
3947
|
+
"4": TextHFour,
|
|
3948
|
+
"5": TextHFive,
|
|
3949
|
+
"6": TextHSix
|
|
3950
|
+
};
|
|
2971
3951
|
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
2972
|
-
var ToolbarRoot = ({ children, onAction }) => {
|
|
3952
|
+
var ToolbarRoot = ({ children, onAction, state }) => {
|
|
2973
3953
|
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
2974
|
-
onAction
|
|
3954
|
+
onAction,
|
|
3955
|
+
state
|
|
2975
3956
|
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
2976
3957
|
density: "fine"
|
|
2977
3958
|
}, /* @__PURE__ */ React2.createElement("div", {
|
|
2978
3959
|
role: "toolbar",
|
|
2979
|
-
className: "flex w-full shrink-0 p-
|
|
3960
|
+
className: "flex w-full shrink-0 p-1 gap-4 items-center whitespace-nowrap overflow-hidden"
|
|
2980
3961
|
}, children)));
|
|
2981
3962
|
};
|
|
2982
|
-
var ToolbarButton = ({ Icon, onClick, title }) => {
|
|
2983
|
-
const { onAction } = useToolbarContext("ToolbarButton");
|
|
2984
|
-
const
|
|
2985
|
-
|
|
3963
|
+
var ToolbarButton = ({ Icon, onClick, title, getState, disable }) => {
|
|
3964
|
+
const { onAction, state } = useToolbarContext("ToolbarButton");
|
|
3965
|
+
const active = getState && state ? getState(state) : false;
|
|
3966
|
+
const disabled = disable && state ? disable(state) : false;
|
|
3967
|
+
const handleClick = (event) => {
|
|
3968
|
+
const action = onClick(state);
|
|
2986
3969
|
if (action) {
|
|
2987
3970
|
onAction?.(action);
|
|
3971
|
+
event.preventDefault();
|
|
2988
3972
|
}
|
|
2989
3973
|
};
|
|
2990
3974
|
return /* @__PURE__ */ React2.createElement(Button, {
|
|
2991
3975
|
variant: "ghost",
|
|
2992
|
-
classNames: "p-2",
|
|
2993
|
-
|
|
2994
|
-
title
|
|
3976
|
+
classNames: mx4("p-2", active && "ring-[1px]"),
|
|
3977
|
+
onMouseDown: handleClick,
|
|
3978
|
+
title,
|
|
3979
|
+
disabled
|
|
2995
3980
|
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
2996
3981
|
className: getSize(5)
|
|
2997
3982
|
}));
|
|
@@ -3000,16 +3985,21 @@ var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
|
3000
3985
|
className: "grow"
|
|
3001
3986
|
});
|
|
3002
3987
|
var MarkdownHeading = () => {
|
|
3003
|
-
const { onAction } = useToolbarContext("MarkdownFormatting");
|
|
3988
|
+
const { onAction, state } = useToolbarContext("MarkdownFormatting");
|
|
3989
|
+
const blockType = state ? state.blockType : "paragraph";
|
|
3990
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
|
3991
|
+
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
|
3992
|
+
const HeadingIcon = HeadingIcons[value ?? "0"];
|
|
3004
3993
|
return /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
3005
|
-
|
|
3006
|
-
|
|
3994
|
+
disabled: value === null,
|
|
3995
|
+
value: value ?? "0",
|
|
3996
|
+
onValueChange: (value2) => onAction?.({
|
|
3007
3997
|
type: "heading",
|
|
3008
|
-
data: parseInt(
|
|
3998
|
+
data: parseInt(value2)
|
|
3009
3999
|
})
|
|
3010
|
-
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
|
|
3011
|
-
|
|
3012
|
-
}), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
4000
|
+
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, null, /* @__PURE__ */ React2.createElement(HeadingIcon, {
|
|
4001
|
+
className: getSize(5)
|
|
4002
|
+
})), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3013
4003
|
value: "0"
|
|
3014
4004
|
}, "Paragraph"), [
|
|
3015
4005
|
1,
|
|
@@ -3027,21 +4017,39 @@ var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
|
|
|
3027
4017
|
role: "none"
|
|
3028
4018
|
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3029
4019
|
Icon: TextB,
|
|
3030
|
-
title: "
|
|
3031
|
-
|
|
3032
|
-
|
|
4020
|
+
title: "String",
|
|
4021
|
+
disable: (s) => s.blockType === "codeblock",
|
|
4022
|
+
getState: (s) => s.strong,
|
|
4023
|
+
onClick: (s) => ({
|
|
4024
|
+
type: "strong",
|
|
4025
|
+
data: s ? !s.strong : null
|
|
3033
4026
|
})
|
|
3034
4027
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3035
4028
|
Icon: TextItalic,
|
|
3036
|
-
title: "
|
|
3037
|
-
|
|
3038
|
-
|
|
4029
|
+
title: "Emphasis",
|
|
4030
|
+
disable: (s) => s.blockType === "codeblock",
|
|
4031
|
+
getState: (s) => s.emphasis,
|
|
4032
|
+
onClick: (s) => ({
|
|
4033
|
+
type: "emphasis",
|
|
4034
|
+
data: s ? !s.emphasis : null
|
|
3039
4035
|
})
|
|
3040
4036
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3041
4037
|
Icon: TextStrikethrough,
|
|
3042
4038
|
title: "Strike-through",
|
|
3043
|
-
|
|
3044
|
-
|
|
4039
|
+
disable: (s) => s.blockType === "codeblock",
|
|
4040
|
+
getState: (s) => s.strikethrough,
|
|
4041
|
+
onClick: (s) => ({
|
|
4042
|
+
type: "strikethrough",
|
|
4043
|
+
data: s ? !s.strikethrough : null
|
|
4044
|
+
})
|
|
4045
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4046
|
+
Icon: Code,
|
|
4047
|
+
title: "Inline code",
|
|
4048
|
+
disable: (s) => s.blockType === "codeblock",
|
|
4049
|
+
getState: (s) => s.code,
|
|
4050
|
+
onClick: (s) => ({
|
|
4051
|
+
type: "code",
|
|
4052
|
+
data: s ? !s.code : null
|
|
3045
4053
|
})
|
|
3046
4054
|
}));
|
|
3047
4055
|
var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
@@ -3049,39 +4057,51 @@ var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
|
3049
4057
|
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3050
4058
|
Icon: ListBullets,
|
|
3051
4059
|
title: "Bullet list",
|
|
3052
|
-
|
|
3053
|
-
|
|
4060
|
+
getState: (s) => s.listStyle === "bullet",
|
|
4061
|
+
onClick: (s) => ({
|
|
4062
|
+
type: "list-bullet",
|
|
4063
|
+
data: s ? s.listStyle !== "bullet" : null
|
|
3054
4064
|
})
|
|
3055
4065
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3056
4066
|
Icon: ListNumbers,
|
|
3057
4067
|
title: "Numbered list",
|
|
3058
|
-
|
|
3059
|
-
|
|
4068
|
+
getState: (s) => s.listStyle === "ordered",
|
|
4069
|
+
onClick: (s) => ({
|
|
4070
|
+
type: "list-ordered",
|
|
4071
|
+
data: s ? s.listStyle !== "ordered" : null
|
|
3060
4072
|
})
|
|
3061
4073
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3062
4074
|
Icon: ListChecks,
|
|
3063
4075
|
title: "Task list",
|
|
3064
|
-
|
|
3065
|
-
|
|
4076
|
+
getState: (s) => s.listStyle === "task",
|
|
4077
|
+
onClick: (s) => ({
|
|
4078
|
+
type: "list-tasks",
|
|
4079
|
+
data: s ? s.listStyle !== "task" : null
|
|
3066
4080
|
})
|
|
3067
4081
|
}));
|
|
3068
4082
|
var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3069
4083
|
role: "none"
|
|
3070
4084
|
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3071
4085
|
Icon: CaretRight,
|
|
3072
|
-
title: "Block
|
|
3073
|
-
|
|
3074
|
-
|
|
4086
|
+
title: "Block quote",
|
|
4087
|
+
getState: (s) => s.blockQuote,
|
|
4088
|
+
onClick: (s) => ({
|
|
4089
|
+
type: "blockquote",
|
|
4090
|
+
data: s ? !s.blockQuote : null
|
|
3075
4091
|
})
|
|
3076
4092
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3077
|
-
Icon:
|
|
4093
|
+
Icon: CodeBlock,
|
|
3078
4094
|
title: "Code block",
|
|
3079
|
-
|
|
3080
|
-
|
|
4095
|
+
disable: (s) => !s.blankLine,
|
|
4096
|
+
getState: (s) => s.blockType === "codeblock",
|
|
4097
|
+
onClick: (s) => ({
|
|
4098
|
+
type: "codeblock",
|
|
4099
|
+
data: s ? s.blockType !== "codeblock" : null
|
|
3081
4100
|
})
|
|
3082
4101
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3083
4102
|
Icon: Table2,
|
|
3084
4103
|
title: "Table",
|
|
4104
|
+
disable: (s) => !s.blankLine,
|
|
3085
4105
|
onClick: () => ({
|
|
3086
4106
|
type: "table"
|
|
3087
4107
|
})
|
|
@@ -3091,20 +4111,10 @@ var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
|
3091
4111
|
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3092
4112
|
Icon: Link,
|
|
3093
4113
|
title: "Link",
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
Icon: At,
|
|
3099
|
-
title: "Mention",
|
|
3100
|
-
onClick: () => ({
|
|
3101
|
-
type: "mention"
|
|
3102
|
-
})
|
|
3103
|
-
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3104
|
-
Icon: Image,
|
|
3105
|
-
title: "Image",
|
|
3106
|
-
onClick: () => ({
|
|
3107
|
-
type: "image"
|
|
4114
|
+
getState: (s) => s.link,
|
|
4115
|
+
onClick: (s) => ({
|
|
4116
|
+
type: "link",
|
|
4117
|
+
data: s ? !s.link : null
|
|
3108
4118
|
})
|
|
3109
4119
|
}));
|
|
3110
4120
|
var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null), /* @__PURE__ */ React2.createElement(MarkdownLinks, null));
|
|
@@ -3240,45 +4250,52 @@ var useActionHandler = (view) => {
|
|
|
3240
4250
|
if (!view) {
|
|
3241
4251
|
return;
|
|
3242
4252
|
}
|
|
4253
|
+
let inlineType, listType;
|
|
3243
4254
|
switch (action.type) {
|
|
3244
4255
|
case "heading":
|
|
3245
4256
|
setHeading(parseInt(action.data))(view);
|
|
3246
4257
|
break;
|
|
3247
|
-
case "
|
|
3248
|
-
|
|
3249
|
-
break;
|
|
3250
|
-
case "italic":
|
|
3251
|
-
toggleItalic(view);
|
|
3252
|
-
break;
|
|
4258
|
+
case "strong":
|
|
4259
|
+
case "emphasis":
|
|
3253
4260
|
case "strikethrough":
|
|
3254
|
-
|
|
4261
|
+
case "code":
|
|
4262
|
+
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
4263
|
+
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
3255
4264
|
break;
|
|
3256
|
-
case "list":
|
|
3257
|
-
|
|
4265
|
+
case "list-ordered":
|
|
4266
|
+
case "list-bullet":
|
|
4267
|
+
case "list-tasks":
|
|
4268
|
+
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
4269
|
+
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
4270
|
+
break;
|
|
4271
|
+
case "blockquote":
|
|
4272
|
+
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
3258
4273
|
break;
|
|
3259
4274
|
case "codeblock":
|
|
3260
|
-
|
|
4275
|
+
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
3261
4276
|
break;
|
|
3262
4277
|
case "table":
|
|
3263
4278
|
insertTable(view);
|
|
3264
4279
|
break;
|
|
4280
|
+
case "link":
|
|
4281
|
+
(action.data === false ? removeLink : addLink)(view);
|
|
4282
|
+
break;
|
|
3265
4283
|
case "comment":
|
|
3266
4284
|
createComment(view);
|
|
3267
4285
|
break;
|
|
3268
4286
|
}
|
|
3269
4287
|
setTimeout(() => {
|
|
3270
|
-
view.
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
});
|
|
4288
|
+
if (!view.hasFocus) {
|
|
4289
|
+
view.focus();
|
|
4290
|
+
}
|
|
3274
4291
|
});
|
|
3275
4292
|
};
|
|
3276
4293
|
};
|
|
3277
4294
|
|
|
3278
4295
|
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
3279
|
-
import { useState as
|
|
4296
|
+
import { useState as useState3 } from "react";
|
|
3280
4297
|
var useEditorView = () => {
|
|
3281
|
-
const [view, setView] =
|
|
4298
|
+
const [view, setView] = useState3(null);
|
|
3282
4299
|
return [
|
|
3283
4300
|
(ref) => {
|
|
3284
4301
|
setView(ref);
|
|
@@ -3288,15 +4305,15 @@ var useEditorView = () => {
|
|
|
3288
4305
|
};
|
|
3289
4306
|
|
|
3290
4307
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
3291
|
-
import { EditorSelection, EditorState as EditorState3 } from "@codemirror/state";
|
|
3292
|
-
import { EditorView as
|
|
3293
|
-
import { useEffect as useEffect3, useRef as useRef2, useState as
|
|
4308
|
+
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4309
|
+
import { EditorView as EditorView15 } from "@codemirror/view";
|
|
4310
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
|
|
3294
4311
|
import { log as log4 } from "@dxos/log";
|
|
3295
4312
|
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
3296
4313
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
3297
4314
|
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}) => {
|
|
3298
4315
|
const onUpdate = useRef2();
|
|
3299
|
-
const [view, setView] =
|
|
4316
|
+
const [view, setView] = useState4();
|
|
3300
4317
|
const parentRef = useRef2(null);
|
|
3301
4318
|
useEffect3(() => {
|
|
3302
4319
|
if (parentRef.current) {
|
|
@@ -3305,7 +4322,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
3305
4322
|
selection,
|
|
3306
4323
|
extensions: [
|
|
3307
4324
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
3308
|
-
|
|
4325
|
+
EditorView15.exceptionSink.of((err) => {
|
|
3309
4326
|
log4.catch(err, void 0, {
|
|
3310
4327
|
F: __dxlog_file5,
|
|
3311
4328
|
L: 57,
|
|
@@ -3314,12 +4331,12 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
3314
4331
|
});
|
|
3315
4332
|
}),
|
|
3316
4333
|
extensions,
|
|
3317
|
-
|
|
4334
|
+
EditorView15.updateListener.of(() => {
|
|
3318
4335
|
onUpdate.current?.();
|
|
3319
4336
|
})
|
|
3320
4337
|
].filter(isNotFalsy4)
|
|
3321
4338
|
});
|
|
3322
|
-
const view2 = new
|
|
4339
|
+
const view2 = new EditorView15({
|
|
3323
4340
|
parent: parentRef.current,
|
|
3324
4341
|
scrollTo,
|
|
3325
4342
|
state,
|
|
@@ -3343,7 +4360,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
3343
4360
|
useEffect3(() => {
|
|
3344
4361
|
if (view) {
|
|
3345
4362
|
if (!selection && !view.state.selection.main.anchor) {
|
|
3346
|
-
selection =
|
|
4363
|
+
selection = EditorSelection2.single(view.state.doc.line(1).to);
|
|
3347
4364
|
}
|
|
3348
4365
|
if (selection || scrollTo) {
|
|
3349
4366
|
onUpdate.current = () => {
|
|
@@ -3376,19 +4393,19 @@ var createDataExtensions = ({ readonly = false } = {}) => {
|
|
|
3376
4393
|
return [
|
|
3377
4394
|
//
|
|
3378
4395
|
EditorState3.readOnly.of(readonly),
|
|
3379
|
-
|
|
4396
|
+
EditorView15.editable.of(!readonly)
|
|
3380
4397
|
];
|
|
3381
4398
|
};
|
|
3382
4399
|
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
3383
4400
|
return [
|
|
3384
4401
|
//
|
|
3385
|
-
|
|
3386
|
-
theme &&
|
|
3387
|
-
|
|
3388
|
-
|
|
4402
|
+
EditorView15.baseTheme(defaultTheme),
|
|
4403
|
+
theme && EditorView15.theme(theme),
|
|
4404
|
+
EditorView15.darkTheme.of(themeMode === "dark"),
|
|
4405
|
+
EditorView15.editorAttributes.of({
|
|
3389
4406
|
class: slots?.editor?.className ?? ""
|
|
3390
4407
|
}),
|
|
3391
|
-
|
|
4408
|
+
EditorView15.contentAttributes.of({
|
|
3392
4409
|
class: slots?.content?.className ?? ""
|
|
3393
4410
|
})
|
|
3394
4411
|
].filter(isNotFalsy4);
|
|
@@ -3396,7 +4413,7 @@ var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
|
3396
4413
|
|
|
3397
4414
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
3398
4415
|
import get4 from "lodash.get";
|
|
3399
|
-
import { useEffect as useEffect4, useState as
|
|
4416
|
+
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
3400
4417
|
import { generateName } from "@dxos/display-name";
|
|
3401
4418
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
3402
4419
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
@@ -3404,7 +4421,7 @@ import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
|
3404
4421
|
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
3405
4422
|
var useTextModel = (props) => {
|
|
3406
4423
|
const { identity, space, text } = props;
|
|
3407
|
-
const [model, setModel] =
|
|
4424
|
+
const [model, setModel] = useState5();
|
|
3408
4425
|
useEffect4(() => setModel(createModel(props)), [
|
|
3409
4426
|
identity,
|
|
3410
4427
|
space,
|
|
@@ -3412,10 +4429,19 @@ var useTextModel = (props) => {
|
|
|
3412
4429
|
]);
|
|
3413
4430
|
return model;
|
|
3414
4431
|
};
|
|
4432
|
+
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
4433
|
+
const [content, setContent] = useState5(defaultContent ?? "");
|
|
4434
|
+
return {
|
|
4435
|
+
id,
|
|
4436
|
+
content,
|
|
4437
|
+
setContent,
|
|
4438
|
+
text: () => content
|
|
4439
|
+
};
|
|
4440
|
+
};
|
|
3415
4441
|
var createModel = ({ space, identity, text }) => {
|
|
3416
4442
|
invariant3(isAutomergeObject(text), void 0, {
|
|
3417
4443
|
F: __dxlog_file6,
|
|
3418
|
-
L:
|
|
4444
|
+
L: 50,
|
|
3419
4445
|
S: void 0,
|
|
3420
4446
|
A: [
|
|
3421
4447
|
"isAutomergeObject(text)",
|
|
@@ -3464,6 +4490,8 @@ export {
|
|
|
3464
4490
|
Cursor,
|
|
3465
4491
|
Doc,
|
|
3466
4492
|
EditorModes,
|
|
4493
|
+
Inline,
|
|
4494
|
+
List,
|
|
3467
4495
|
MarkdownEditor,
|
|
3468
4496
|
RemoteSelectionsDecorator,
|
|
3469
4497
|
SpaceAwarenessProvider,
|
|
@@ -3472,6 +4500,11 @@ export {
|
|
|
3472
4500
|
Toolbar,
|
|
3473
4501
|
YText,
|
|
3474
4502
|
YXmlFragment,
|
|
4503
|
+
addBlockquote,
|
|
4504
|
+
addCodeblock,
|
|
4505
|
+
addLink,
|
|
4506
|
+
addList,
|
|
4507
|
+
addStyle,
|
|
3475
4508
|
autocomplete,
|
|
3476
4509
|
automerge,
|
|
3477
4510
|
awareness,
|
|
@@ -3481,6 +4514,7 @@ export {
|
|
|
3481
4514
|
code2 as code,
|
|
3482
4515
|
codeTheme,
|
|
3483
4516
|
comments,
|
|
4517
|
+
compareFormatting,
|
|
3484
4518
|
createBasicBundle,
|
|
3485
4519
|
createComment,
|
|
3486
4520
|
createDataExtensions,
|
|
@@ -3493,12 +4527,13 @@ export {
|
|
|
3493
4527
|
defaultTheme,
|
|
3494
4528
|
focusComment,
|
|
3495
4529
|
formatting,
|
|
4530
|
+
getFormatting,
|
|
3496
4531
|
getToken,
|
|
3497
4532
|
heading2 as heading,
|
|
3498
4533
|
hr,
|
|
3499
4534
|
image,
|
|
3500
|
-
insertCodeblock,
|
|
3501
4535
|
insertTable,
|
|
4536
|
+
keymap7 as keymap,
|
|
3502
4537
|
link,
|
|
3503
4538
|
listener,
|
|
3504
4539
|
logChanges,
|
|
@@ -3509,22 +4544,34 @@ export {
|
|
|
3509
4544
|
mention,
|
|
3510
4545
|
modelState,
|
|
3511
4546
|
outliner,
|
|
4547
|
+
removeBlockquote,
|
|
4548
|
+
removeCodeblock,
|
|
4549
|
+
removeLink,
|
|
4550
|
+
removeList,
|
|
4551
|
+
removeStyle,
|
|
4552
|
+
setBlockquote,
|
|
3512
4553
|
setComments,
|
|
3513
4554
|
setHeading,
|
|
3514
4555
|
setSelection,
|
|
4556
|
+
setStyle,
|
|
3515
4557
|
table,
|
|
3516
4558
|
tags2 as tags,
|
|
3517
4559
|
tasklist,
|
|
3518
4560
|
textTheme,
|
|
3519
|
-
|
|
3520
|
-
|
|
4561
|
+
toggleBlockquote,
|
|
4562
|
+
toggleCodeblock,
|
|
4563
|
+
toggleEmphasis,
|
|
4564
|
+
toggleInlineCode,
|
|
3521
4565
|
toggleList,
|
|
3522
4566
|
toggleStrikethrough,
|
|
4567
|
+
toggleStrong,
|
|
3523
4568
|
toggleStyle,
|
|
3524
4569
|
typewriter,
|
|
3525
4570
|
useActionHandler,
|
|
3526
4571
|
useComments,
|
|
3527
4572
|
useEditorView,
|
|
4573
|
+
useFormattingState,
|
|
4574
|
+
useInMemoryTextModel,
|
|
3528
4575
|
useTextEditor,
|
|
3529
4576
|
useTextModel,
|
|
3530
4577
|
useToolbarContext
|