@dxos/react-ui-editor 0.3.11-main.fc97a54 → 0.3.11-main.ff3a851
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 +163 -1196
- 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/hooks.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +4 -8
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +3 -5
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +1 -5
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +10 -55
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/package.json +25 -25
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +3 -3
- package/src/components/TextEditor/hooks.stories.tsx +1 -6
- package/src/components/Toolbar/Toolbar.stories.tsx +4 -16
- package/src/components/Toolbar/Toolbar.tsx +30 -128
- package/src/extensions/comments.ts +4 -14
- package/src/extensions/markdown/formatting.ts +69 -1118
- package/src/hooks/useActionHandler.ts +16 -47
- package/src/themes/default.ts +2 -2
- package/dist/types/src/extensions/markdown/formatting.test.d.ts +0 -3
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +0 -1
- package/src/extensions/markdown/formatting.test.ts +0 -482
|
@@ -8,10 +8,10 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
8
8
|
|
|
9
9
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
10
10
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
11
|
-
import { EditorView as
|
|
11
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
15
15
|
import { log as log2 } from "@dxos/log";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
17
|
import { focusRing, mx as mx3 } from "@dxos/react-ui-theme";
|
|
@@ -1074,25 +1074,11 @@ var logChanges = (trs) => {
|
|
|
1074
1074
|
|
|
1075
1075
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1076
1076
|
var styles2 = EditorView5.baseTheme({
|
|
1077
|
-
"&
|
|
1078
|
-
mixBlendMode: "darken"
|
|
1079
|
-
},
|
|
1080
|
-
"&dark .cm-comment, &dark .cm-comment-current": {
|
|
1081
|
-
mixBlendMode: "plus-lighter"
|
|
1082
|
-
},
|
|
1083
|
-
"&light .cm-comment": {
|
|
1077
|
+
"& .cm-comment": {
|
|
1084
1078
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1085
1079
|
},
|
|
1086
|
-
"&
|
|
1080
|
+
"& .cm-comment-current": {
|
|
1087
1081
|
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")
|
|
1096
1082
|
}
|
|
1097
1083
|
});
|
|
1098
1084
|
var commentMark = Decoration2.mark({
|
|
@@ -1301,11 +1287,7 @@ var createComment = (view) => {
|
|
|
1301
1287
|
to
|
|
1302
1288
|
});
|
|
1303
1289
|
if (cursor) {
|
|
1304
|
-
const id = options.onCreate?.(
|
|
1305
|
-
cursor,
|
|
1306
|
-
from,
|
|
1307
|
-
location: view.coordsAtPos(from)
|
|
1308
|
-
});
|
|
1290
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1309
1291
|
if (id) {
|
|
1310
1292
|
view.dispatch({
|
|
1311
1293
|
effects: setSelection.of({
|
|
@@ -1833,836 +1815,89 @@ var code2 = () => {
|
|
|
1833
1815
|
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1834
1816
|
import { snippet } from "@codemirror/autocomplete";
|
|
1835
1817
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1836
|
-
import { RangeSetBuilder as RangeSetBuilder2
|
|
1837
|
-
import { Decoration as Decoration4,
|
|
1838
|
-
|
|
1839
|
-
|
|
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;
|
|
1818
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1819
|
+
import { Decoration as Decoration4, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1820
|
+
var setHeading = (level) => (view) => {
|
|
1821
|
+
const { selection: { ranges }, doc } = view.state;
|
|
1855
1822
|
const changes = [];
|
|
1856
|
-
let prevBlock = -1;
|
|
1857
1823
|
for (const range of ranges) {
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
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
|
-
}
|
|
1908
|
-
});
|
|
1824
|
+
const { number } = doc.lineAt(range.anchor);
|
|
1825
|
+
const { from, to } = doc.line(number);
|
|
1826
|
+
const line = doc.sliceString(from, to);
|
|
1827
|
+
const [_, marks, spaces] = line.match(/(#+)(\s+)/) ?? [];
|
|
1828
|
+
const current = marks?.length ?? 0;
|
|
1829
|
+
if (level !== current) {
|
|
1830
|
+
changes.push({
|
|
1831
|
+
from,
|
|
1832
|
+
to: from + current + (spaces?.length ?? 0),
|
|
1833
|
+
insert: "#".repeat(level) + (level > 0 ? " " : "")
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1909
1836
|
}
|
|
1910
|
-
if (
|
|
1911
|
-
|
|
1837
|
+
if (changes.length) {
|
|
1838
|
+
view.dispatch({
|
|
1839
|
+
changes
|
|
1840
|
+
});
|
|
1912
1841
|
}
|
|
1913
|
-
dispatch(state.update({
|
|
1914
|
-
changes,
|
|
1915
|
-
userEvent: "format.setHeading",
|
|
1916
|
-
scrollIntoView: true
|
|
1917
|
-
}));
|
|
1918
1842
|
return true;
|
|
1919
1843
|
};
|
|
1920
|
-
var
|
|
1921
|
-
const
|
|
1922
|
-
const
|
|
1923
|
-
if (
|
|
1924
|
-
|
|
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
|
-
}
|
|
1844
|
+
var toggleStyle = (mark2) => (view) => {
|
|
1845
|
+
const { ranges } = view.state.selection;
|
|
1846
|
+
for (const range of ranges) {
|
|
1847
|
+
if (range.from === range.to) {
|
|
1848
|
+
return false;
|
|
1946
1849
|
}
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
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
|
-
}
|
|
2018
|
-
}
|
|
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
|
-
}
|
|
1850
|
+
view.dispatch({
|
|
1851
|
+
changes: [
|
|
1852
|
+
{
|
|
1853
|
+
from: range.from,
|
|
1854
|
+
insert: mark2
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
from: range.to,
|
|
1858
|
+
insert: mark2
|
|
2061
1859
|
}
|
|
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
|
-
}));
|
|
2074
|
-
return true;
|
|
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
1862
|
}
|
|
2092
|
-
return
|
|
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;
|
|
1863
|
+
return true;
|
|
2108
1864
|
};
|
|
2109
1865
|
var snippets = {
|
|
2110
1866
|
codeblock: snippet([
|
|
2111
|
-
|
|
2112
|
-
"
|
|
2113
|
-
"#{}",
|
|
1867
|
+
"```#{lang}",
|
|
1868
|
+
" #{}",
|
|
2114
1869
|
"```"
|
|
2115
1870
|
].join("\n")),
|
|
2116
1871
|
table: snippet([
|
|
2117
|
-
//
|
|
2118
1872
|
"| #{col1} | #{col2} |",
|
|
2119
1873
|
"| ---- | ---- |",
|
|
2120
1874
|
"| #{val1} | #{val2} |",
|
|
2121
|
-
"| #{val3} | #{val4} |"
|
|
2122
|
-
""
|
|
1875
|
+
"| #{val3} | #{val4} |"
|
|
2123
1876
|
].join("\n"))
|
|
2124
1877
|
};
|
|
1878
|
+
var insertCodeblock = (view) => {
|
|
1879
|
+
const { selection: { main }, doc } = view.state;
|
|
1880
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1881
|
+
const { from } = doc.line(number);
|
|
1882
|
+
snippets.codeblock(view, null, from, from);
|
|
1883
|
+
};
|
|
2125
1884
|
var insertTable = (view) => {
|
|
2126
1885
|
const { selection: { main }, doc } = view.state;
|
|
2127
1886
|
const { number } = doc.lineAt(main.anchor);
|
|
2128
1887
|
const { from } = doc.line(number);
|
|
2129
1888
|
snippets.table(view, null, from, from);
|
|
2130
1889
|
};
|
|
2131
|
-
var
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
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);
|
|
1890
|
+
var toggleBold = toggleStyle("**");
|
|
1891
|
+
var toggleItalic = toggleStyle("_");
|
|
1892
|
+
var toggleStrikethrough = toggleStyle("~~");
|
|
1893
|
+
var toggleList = (view) => {
|
|
2659
1894
|
};
|
|
2660
1895
|
var formatting = (options = {}) => {
|
|
2661
1896
|
return [
|
|
2662
1897
|
keymap5.of([
|
|
2663
1898
|
{
|
|
2664
1899
|
key: "meta-b",
|
|
2665
|
-
run:
|
|
1900
|
+
run: toggleBold
|
|
2666
1901
|
}
|
|
2667
1902
|
]),
|
|
2668
1903
|
styling()
|
|
@@ -2716,209 +1951,6 @@ var styling = () => {
|
|
|
2716
1951
|
})
|
|
2717
1952
|
];
|
|
2718
1953
|
};
|
|
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
|
-
};
|
|
2922
1954
|
|
|
2923
1955
|
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
2924
1956
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
@@ -2971,8 +2003,8 @@ var heading2 = () => {
|
|
|
2971
2003
|
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
2972
2004
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2973
2005
|
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2974
|
-
import { Decoration as Decoration6, EditorView as
|
|
2975
|
-
var styles4 =
|
|
2006
|
+
import { Decoration as Decoration6, EditorView as EditorView9, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
2007
|
+
var styles4 = EditorView9.baseTheme({
|
|
2976
2008
|
"& .cm-hr": {
|
|
2977
2009
|
// Note that block-level decorations should not have vertical margins,
|
|
2978
2010
|
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
@@ -3026,7 +2058,7 @@ var hr = () => {
|
|
|
3026
2058
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3027
2059
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
3028
2060
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
3029
|
-
import { Decoration as Decoration7, EditorView as
|
|
2061
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3030
2062
|
var image = (options = {}) => {
|
|
3031
2063
|
return StateField3.define({
|
|
3032
2064
|
create: (state) => {
|
|
@@ -3053,7 +2085,7 @@ var image = (options = {}) => {
|
|
|
3053
2085
|
add: buildDecorations4(from, to, tr.state)
|
|
3054
2086
|
});
|
|
3055
2087
|
},
|
|
3056
|
-
provide: (field) =>
|
|
2088
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
3057
2089
|
});
|
|
3058
2090
|
};
|
|
3059
2091
|
var buildDecorations4 = (from, to, state) => {
|
|
@@ -3235,12 +2267,12 @@ var buildDecorations5 = (view, options) => {
|
|
|
3235
2267
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
3236
2268
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
3237
2269
|
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
|
|
3238
|
-
import { Decoration as Decoration9, EditorView as
|
|
2270
|
+
import { Decoration as Decoration9, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
3239
2271
|
var table = (options = {}) => {
|
|
3240
2272
|
return StateField4.define({
|
|
3241
2273
|
create: (state) => update(state, options),
|
|
3242
2274
|
update: (_, tr) => update(tr.state, options),
|
|
3243
|
-
provide: (field) =>
|
|
2275
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
3244
2276
|
});
|
|
3245
2277
|
};
|
|
3246
2278
|
var update = (state, options) => {
|
|
@@ -3333,8 +2365,8 @@ var TableWidget = class extends WidgetType6 {
|
|
|
3333
2365
|
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
3334
2366
|
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
3335
2367
|
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
3336
|
-
import { EditorView as
|
|
3337
|
-
var styles5 =
|
|
2368
|
+
import { EditorView as EditorView12, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
2369
|
+
var styles5 = EditorView12.baseTheme({
|
|
3338
2370
|
"& .cm-task": {
|
|
3339
2371
|
color: getToken("extend.colors.blue.500")
|
|
3340
2372
|
},
|
|
@@ -3559,11 +2591,11 @@ var defaultTheme = {
|
|
|
3559
2591
|
fontSize: "16px"
|
|
3560
2592
|
},
|
|
3561
2593
|
"&light .cm-content": {
|
|
3562
|
-
color: get3(tokens, "extend.
|
|
2594
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
3563
2595
|
caretColor: "black"
|
|
3564
2596
|
},
|
|
3565
2597
|
"&dark .cm-content": {
|
|
3566
|
-
color: get3(tokens, "extend.
|
|
2598
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
3567
2599
|
caretColor: "white"
|
|
3568
2600
|
},
|
|
3569
2601
|
//
|
|
@@ -3767,7 +2799,7 @@ var EditorModes = [
|
|
|
3767
2799
|
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
3768
2800
|
const { themeMode } = useThemeContext();
|
|
3769
2801
|
const rootRef = useRef(null);
|
|
3770
|
-
const [view, setView] =
|
|
2802
|
+
const [view, setView] = useState(null);
|
|
3771
2803
|
useImperativeHandle(forwardedRef, () => view, [
|
|
3772
2804
|
view
|
|
3773
2805
|
]);
|
|
@@ -3796,7 +2828,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
3796
2828
|
selection,
|
|
3797
2829
|
extensions: [
|
|
3798
2830
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
3799
|
-
|
|
2831
|
+
EditorView13.exceptionSink.of((err) => {
|
|
3800
2832
|
log2.catch(err, void 0, {
|
|
3801
2833
|
F: __dxlog_file3,
|
|
3802
2834
|
L: 134,
|
|
@@ -3806,17 +2838,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
3806
2838
|
}),
|
|
3807
2839
|
// Theme.
|
|
3808
2840
|
// TODO(burdon): Make configurable.
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
2841
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2842
|
+
EditorView13.theme(theme ?? {}),
|
|
2843
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2844
|
+
EditorView13.editorAttributes.of({
|
|
3813
2845
|
class: slots.editor?.className ?? ""
|
|
3814
2846
|
}),
|
|
3815
|
-
|
|
2847
|
+
EditorView13.contentAttributes.of({
|
|
3816
2848
|
class: slots.content?.className ?? ""
|
|
3817
2849
|
}),
|
|
3818
2850
|
// State.
|
|
3819
|
-
|
|
2851
|
+
EditorView13.editable.of(!readonly),
|
|
3820
2852
|
EditorState2.readOnly.of(!!readonly),
|
|
3821
2853
|
// Storage and replication.
|
|
3822
2854
|
// NOTE: This must come before user extensions.
|
|
@@ -3827,7 +2859,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
3827
2859
|
...extensions
|
|
3828
2860
|
].filter(isNotFalsy3)
|
|
3829
2861
|
});
|
|
3830
|
-
const newView = new
|
|
2862
|
+
const newView = new EditorView13({
|
|
3831
2863
|
state,
|
|
3832
2864
|
parent: rootRef.current,
|
|
3833
2865
|
scrollTo,
|
|
@@ -3934,49 +2966,35 @@ var defaultMarkdownSlots = {
|
|
|
3934
2966
|
};
|
|
3935
2967
|
|
|
3936
2968
|
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
3937
|
-
import { CaretRight, ChatText, Code,
|
|
2969
|
+
import { At, CaretRight, ChatText, Code, Image, Link, ListBullets, ListChecks, ListNumbers, TextStrikethrough, Table as Table2, TextB, TextItalic } from "@phosphor-icons/react";
|
|
3938
2970
|
import { createContext } from "@radix-ui/react-context";
|
|
3939
2971
|
import React2 from "react";
|
|
3940
2972
|
import { Button, DensityProvider, Select } from "@dxos/react-ui";
|
|
3941
|
-
import { getSize
|
|
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
|
-
};
|
|
2973
|
+
import { getSize } from "@dxos/react-ui-theme";
|
|
3951
2974
|
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
3952
|
-
var ToolbarRoot = ({ children, onAction
|
|
2975
|
+
var ToolbarRoot = ({ children, onAction }) => {
|
|
3953
2976
|
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
3954
|
-
onAction
|
|
3955
|
-
state
|
|
2977
|
+
onAction
|
|
3956
2978
|
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
3957
2979
|
density: "fine"
|
|
3958
2980
|
}, /* @__PURE__ */ React2.createElement("div", {
|
|
3959
2981
|
role: "toolbar",
|
|
3960
|
-
className: "flex w-full shrink-0 p-
|
|
2982
|
+
className: "flex w-full shrink-0 p-2 gap-4 items-center whitespace-nowrap overflow-hidden"
|
|
3961
2983
|
}, children)));
|
|
3962
2984
|
};
|
|
3963
|
-
var ToolbarButton = ({ Icon, onClick, title
|
|
3964
|
-
const { onAction
|
|
3965
|
-
const
|
|
3966
|
-
|
|
3967
|
-
const handleClick = (event) => {
|
|
3968
|
-
const action = onClick(state);
|
|
2985
|
+
var ToolbarButton = ({ Icon, onClick, title }) => {
|
|
2986
|
+
const { onAction } = useToolbarContext("ToolbarButton");
|
|
2987
|
+
const handleClick = () => {
|
|
2988
|
+
const action = onClick();
|
|
3969
2989
|
if (action) {
|
|
3970
2990
|
onAction?.(action);
|
|
3971
|
-
event.preventDefault();
|
|
3972
2991
|
}
|
|
3973
2992
|
};
|
|
3974
2993
|
return /* @__PURE__ */ React2.createElement(Button, {
|
|
3975
2994
|
variant: "ghost",
|
|
3976
|
-
classNames:
|
|
3977
|
-
|
|
3978
|
-
title
|
|
3979
|
-
disabled
|
|
2995
|
+
classNames: "p-2",
|
|
2996
|
+
onClick: handleClick,
|
|
2997
|
+
title
|
|
3980
2998
|
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
3981
2999
|
className: getSize(5)
|
|
3982
3000
|
}));
|
|
@@ -3985,21 +3003,16 @@ var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
|
3985
3003
|
className: "grow"
|
|
3986
3004
|
});
|
|
3987
3005
|
var MarkdownHeading = () => {
|
|
3988
|
-
const { onAction
|
|
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"];
|
|
3006
|
+
const { onAction } = useToolbarContext("MarkdownFormatting");
|
|
3993
3007
|
return /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
onValueChange: (value2) => onAction?.({
|
|
3008
|
+
defaultValue: "0",
|
|
3009
|
+
onValueChange: (value) => onAction?.({
|
|
3997
3010
|
type: "heading",
|
|
3998
|
-
data: parseInt(
|
|
3011
|
+
data: parseInt(value)
|
|
3999
3012
|
})
|
|
4000
|
-
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton,
|
|
4001
|
-
|
|
4002
|
-
})
|
|
3013
|
+
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
|
|
3014
|
+
classNames: "w-[8rem]"
|
|
3015
|
+
}), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
4003
3016
|
value: "0"
|
|
4004
3017
|
}, "Paragraph"), [
|
|
4005
3018
|
1,
|
|
@@ -4017,39 +3030,21 @@ var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
|
|
|
4017
3030
|
role: "none"
|
|
4018
3031
|
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4019
3032
|
Icon: TextB,
|
|
4020
|
-
title: "
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
onClick: (s) => ({
|
|
4024
|
-
type: "strong",
|
|
4025
|
-
data: s ? !s.strong : null
|
|
3033
|
+
title: "Bold",
|
|
3034
|
+
onClick: () => ({
|
|
3035
|
+
type: "bold"
|
|
4026
3036
|
})
|
|
4027
3037
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4028
3038
|
Icon: TextItalic,
|
|
4029
|
-
title: "
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
onClick: (s) => ({
|
|
4033
|
-
type: "emphasis",
|
|
4034
|
-
data: s ? !s.emphasis : null
|
|
3039
|
+
title: "Italic",
|
|
3040
|
+
onClick: () => ({
|
|
3041
|
+
type: "italic"
|
|
4035
3042
|
})
|
|
4036
3043
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4037
3044
|
Icon: TextStrikethrough,
|
|
4038
3045
|
title: "Strike-through",
|
|
4039
|
-
|
|
4040
|
-
|
|
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
|
|
3046
|
+
onClick: () => ({
|
|
3047
|
+
type: "strikethrough"
|
|
4053
3048
|
})
|
|
4054
3049
|
}));
|
|
4055
3050
|
var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
@@ -4057,51 +3052,39 @@ var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
|
4057
3052
|
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4058
3053
|
Icon: ListBullets,
|
|
4059
3054
|
title: "Bullet list",
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
type: "list-bullet",
|
|
4063
|
-
data: s ? s.listStyle !== "bullet" : null
|
|
3055
|
+
onClick: () => ({
|
|
3056
|
+
type: "list"
|
|
4064
3057
|
})
|
|
4065
3058
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4066
3059
|
Icon: ListNumbers,
|
|
4067
3060
|
title: "Numbered list",
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
type: "list-ordered",
|
|
4071
|
-
data: s ? s.listStyle !== "ordered" : null
|
|
3061
|
+
onClick: () => ({
|
|
3062
|
+
type: "list-ordered"
|
|
4072
3063
|
})
|
|
4073
3064
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4074
3065
|
Icon: ListChecks,
|
|
4075
3066
|
title: "Task list",
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
type: "list-tasks",
|
|
4079
|
-
data: s ? s.listStyle !== "task" : null
|
|
3067
|
+
onClick: () => ({
|
|
3068
|
+
type: "list-tasks"
|
|
4080
3069
|
})
|
|
4081
3070
|
}));
|
|
4082
3071
|
var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
4083
3072
|
role: "none"
|
|
4084
3073
|
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4085
3074
|
Icon: CaretRight,
|
|
4086
|
-
title: "Block
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
type: "blockquote",
|
|
4090
|
-
data: s ? !s.blockQuote : null
|
|
3075
|
+
title: "Block quite",
|
|
3076
|
+
onClick: () => ({
|
|
3077
|
+
type: "blockquote"
|
|
4091
3078
|
})
|
|
4092
3079
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4093
|
-
Icon:
|
|
3080
|
+
Icon: Code,
|
|
4094
3081
|
title: "Code block",
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
onClick: (s) => ({
|
|
4098
|
-
type: "codeblock",
|
|
4099
|
-
data: s ? s.blockType !== "codeblock" : null
|
|
3082
|
+
onClick: () => ({
|
|
3083
|
+
type: "codeblock"
|
|
4100
3084
|
})
|
|
4101
3085
|
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4102
3086
|
Icon: Table2,
|
|
4103
3087
|
title: "Table",
|
|
4104
|
-
disable: (s) => !s.blankLine,
|
|
4105
3088
|
onClick: () => ({
|
|
4106
3089
|
type: "table"
|
|
4107
3090
|
})
|
|
@@ -4111,10 +3094,20 @@ var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
|
4111
3094
|
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4112
3095
|
Icon: Link,
|
|
4113
3096
|
title: "Link",
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
3097
|
+
onClick: () => ({
|
|
3098
|
+
type: "link"
|
|
3099
|
+
})
|
|
3100
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3101
|
+
Icon: At,
|
|
3102
|
+
title: "Mention",
|
|
3103
|
+
onClick: () => ({
|
|
3104
|
+
type: "mention"
|
|
3105
|
+
})
|
|
3106
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3107
|
+
Icon: Image,
|
|
3108
|
+
title: "Image",
|
|
3109
|
+
onClick: () => ({
|
|
3110
|
+
type: "image"
|
|
4118
3111
|
})
|
|
4119
3112
|
}));
|
|
4120
3113
|
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));
|
|
@@ -4250,52 +3243,45 @@ var useActionHandler = (view) => {
|
|
|
4250
3243
|
if (!view) {
|
|
4251
3244
|
return;
|
|
4252
3245
|
}
|
|
4253
|
-
let inlineType, listType;
|
|
4254
3246
|
switch (action.type) {
|
|
4255
3247
|
case "heading":
|
|
4256
3248
|
setHeading(parseInt(action.data))(view);
|
|
4257
3249
|
break;
|
|
4258
|
-
case "
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
case "
|
|
4262
|
-
|
|
4263
|
-
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
3250
|
+
case "bold":
|
|
3251
|
+
toggleBold(view);
|
|
3252
|
+
break;
|
|
3253
|
+
case "italic":
|
|
3254
|
+
toggleItalic(view);
|
|
4264
3255
|
break;
|
|
4265
|
-
case "
|
|
4266
|
-
|
|
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);
|
|
3256
|
+
case "strikethrough":
|
|
3257
|
+
toggleStrikethrough(view);
|
|
4270
3258
|
break;
|
|
4271
|
-
case "
|
|
4272
|
-
(
|
|
3259
|
+
case "list":
|
|
3260
|
+
toggleList(view);
|
|
4273
3261
|
break;
|
|
4274
3262
|
case "codeblock":
|
|
4275
|
-
(
|
|
3263
|
+
insertCodeblock(view);
|
|
4276
3264
|
break;
|
|
4277
3265
|
case "table":
|
|
4278
3266
|
insertTable(view);
|
|
4279
3267
|
break;
|
|
4280
|
-
case "link":
|
|
4281
|
-
(action.data === false ? removeLink : addLink)(view);
|
|
4282
|
-
break;
|
|
4283
3268
|
case "comment":
|
|
4284
3269
|
createComment(view);
|
|
4285
3270
|
break;
|
|
4286
3271
|
}
|
|
4287
3272
|
setTimeout(() => {
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
3273
|
+
view.focus();
|
|
3274
|
+
view.dispatch({
|
|
3275
|
+
selection: view.state.selection
|
|
3276
|
+
});
|
|
4291
3277
|
});
|
|
4292
3278
|
};
|
|
4293
3279
|
};
|
|
4294
3280
|
|
|
4295
3281
|
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
4296
|
-
import { useState as
|
|
3282
|
+
import { useState as useState2 } from "react";
|
|
4297
3283
|
var useEditorView = () => {
|
|
4298
|
-
const [view, setView] =
|
|
3284
|
+
const [view, setView] = useState2(null);
|
|
4299
3285
|
return [
|
|
4300
3286
|
(ref) => {
|
|
4301
3287
|
setView(ref);
|
|
@@ -4305,15 +3291,15 @@ var useEditorView = () => {
|
|
|
4305
3291
|
};
|
|
4306
3292
|
|
|
4307
3293
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4308
|
-
import { EditorSelection
|
|
4309
|
-
import { EditorView as
|
|
4310
|
-
import { useEffect as useEffect3, useRef as useRef2, useState as
|
|
3294
|
+
import { EditorSelection, EditorState as EditorState3 } from "@codemirror/state";
|
|
3295
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
3296
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
4311
3297
|
import { log as log4 } from "@dxos/log";
|
|
4312
3298
|
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
4313
3299
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4314
3300
|
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}) => {
|
|
4315
3301
|
const onUpdate = useRef2();
|
|
4316
|
-
const [view, setView] =
|
|
3302
|
+
const [view, setView] = useState3();
|
|
4317
3303
|
const parentRef = useRef2(null);
|
|
4318
3304
|
useEffect3(() => {
|
|
4319
3305
|
if (parentRef.current) {
|
|
@@ -4322,7 +3308,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
4322
3308
|
selection,
|
|
4323
3309
|
extensions: [
|
|
4324
3310
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4325
|
-
|
|
3311
|
+
EditorView14.exceptionSink.of((err) => {
|
|
4326
3312
|
log4.catch(err, void 0, {
|
|
4327
3313
|
F: __dxlog_file5,
|
|
4328
3314
|
L: 57,
|
|
@@ -4331,12 +3317,12 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
4331
3317
|
});
|
|
4332
3318
|
}),
|
|
4333
3319
|
extensions,
|
|
4334
|
-
|
|
3320
|
+
EditorView14.updateListener.of(() => {
|
|
4335
3321
|
onUpdate.current?.();
|
|
4336
3322
|
})
|
|
4337
3323
|
].filter(isNotFalsy4)
|
|
4338
3324
|
});
|
|
4339
|
-
const view2 = new
|
|
3325
|
+
const view2 = new EditorView14({
|
|
4340
3326
|
parent: parentRef.current,
|
|
4341
3327
|
scrollTo,
|
|
4342
3328
|
state,
|
|
@@ -4360,7 +3346,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
4360
3346
|
useEffect3(() => {
|
|
4361
3347
|
if (view) {
|
|
4362
3348
|
if (!selection && !view.state.selection.main.anchor) {
|
|
4363
|
-
selection =
|
|
3349
|
+
selection = EditorSelection.single(view.state.doc.line(1).to);
|
|
4364
3350
|
}
|
|
4365
3351
|
if (selection || scrollTo) {
|
|
4366
3352
|
onUpdate.current = () => {
|
|
@@ -4393,19 +3379,19 @@ var createDataExtensions = ({ readonly = false } = {}) => {
|
|
|
4393
3379
|
return [
|
|
4394
3380
|
//
|
|
4395
3381
|
EditorState3.readOnly.of(readonly),
|
|
4396
|
-
|
|
3382
|
+
EditorView14.editable.of(!readonly)
|
|
4397
3383
|
];
|
|
4398
3384
|
};
|
|
4399
3385
|
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
4400
3386
|
return [
|
|
4401
3387
|
//
|
|
4402
|
-
|
|
4403
|
-
theme &&
|
|
4404
|
-
|
|
4405
|
-
|
|
3388
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3389
|
+
theme && EditorView14.theme(theme),
|
|
3390
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3391
|
+
EditorView14.editorAttributes.of({
|
|
4406
3392
|
class: slots?.editor?.className ?? ""
|
|
4407
3393
|
}),
|
|
4408
|
-
|
|
3394
|
+
EditorView14.contentAttributes.of({
|
|
4409
3395
|
class: slots?.content?.className ?? ""
|
|
4410
3396
|
})
|
|
4411
3397
|
].filter(isNotFalsy4);
|
|
@@ -4413,7 +3399,7 @@ var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
|
4413
3399
|
|
|
4414
3400
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
4415
3401
|
import get4 from "lodash.get";
|
|
4416
|
-
import { useEffect as useEffect4, useState as
|
|
3402
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
4417
3403
|
import { generateName } from "@dxos/display-name";
|
|
4418
3404
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
4419
3405
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
@@ -4421,7 +3407,7 @@ import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
|
4421
3407
|
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
4422
3408
|
var useTextModel = (props) => {
|
|
4423
3409
|
const { identity, space, text } = props;
|
|
4424
|
-
const [model, setModel] =
|
|
3410
|
+
const [model, setModel] = useState4();
|
|
4425
3411
|
useEffect4(() => setModel(createModel(props)), [
|
|
4426
3412
|
identity,
|
|
4427
3413
|
space,
|
|
@@ -4430,7 +3416,7 @@ var useTextModel = (props) => {
|
|
|
4430
3416
|
return model;
|
|
4431
3417
|
};
|
|
4432
3418
|
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
4433
|
-
const [content, setContent] =
|
|
3419
|
+
const [content, setContent] = useState4(defaultContent ?? "");
|
|
4434
3420
|
return {
|
|
4435
3421
|
id,
|
|
4436
3422
|
content,
|
|
@@ -4490,8 +3476,6 @@ export {
|
|
|
4490
3476
|
Cursor,
|
|
4491
3477
|
Doc,
|
|
4492
3478
|
EditorModes,
|
|
4493
|
-
Inline,
|
|
4494
|
-
List,
|
|
4495
3479
|
MarkdownEditor,
|
|
4496
3480
|
RemoteSelectionsDecorator,
|
|
4497
3481
|
SpaceAwarenessProvider,
|
|
@@ -4500,11 +3484,6 @@ export {
|
|
|
4500
3484
|
Toolbar,
|
|
4501
3485
|
YText,
|
|
4502
3486
|
YXmlFragment,
|
|
4503
|
-
addBlockquote,
|
|
4504
|
-
addCodeblock,
|
|
4505
|
-
addLink,
|
|
4506
|
-
addList,
|
|
4507
|
-
addStyle,
|
|
4508
3487
|
autocomplete,
|
|
4509
3488
|
automerge,
|
|
4510
3489
|
awareness,
|
|
@@ -4514,7 +3493,6 @@ export {
|
|
|
4514
3493
|
code2 as code,
|
|
4515
3494
|
codeTheme,
|
|
4516
3495
|
comments,
|
|
4517
|
-
compareFormatting,
|
|
4518
3496
|
createBasicBundle,
|
|
4519
3497
|
createComment,
|
|
4520
3498
|
createDataExtensions,
|
|
@@ -4527,11 +3505,11 @@ export {
|
|
|
4527
3505
|
defaultTheme,
|
|
4528
3506
|
focusComment,
|
|
4529
3507
|
formatting,
|
|
4530
|
-
getFormatting,
|
|
4531
3508
|
getToken,
|
|
4532
3509
|
heading2 as heading,
|
|
4533
3510
|
hr,
|
|
4534
3511
|
image,
|
|
3512
|
+
insertCodeblock,
|
|
4535
3513
|
insertTable,
|
|
4536
3514
|
keymap7 as keymap,
|
|
4537
3515
|
link,
|
|
@@ -4544,33 +3522,22 @@ export {
|
|
|
4544
3522
|
mention,
|
|
4545
3523
|
modelState,
|
|
4546
3524
|
outliner,
|
|
4547
|
-
removeBlockquote,
|
|
4548
|
-
removeCodeblock,
|
|
4549
|
-
removeLink,
|
|
4550
|
-
removeList,
|
|
4551
|
-
removeStyle,
|
|
4552
|
-
setBlockquote,
|
|
4553
3525
|
setComments,
|
|
4554
3526
|
setHeading,
|
|
4555
3527
|
setSelection,
|
|
4556
|
-
setStyle,
|
|
4557
3528
|
table,
|
|
4558
3529
|
tags2 as tags,
|
|
4559
3530
|
tasklist,
|
|
4560
3531
|
textTheme,
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
toggleEmphasis,
|
|
4564
|
-
toggleInlineCode,
|
|
3532
|
+
toggleBold,
|
|
3533
|
+
toggleItalic,
|
|
4565
3534
|
toggleList,
|
|
4566
3535
|
toggleStrikethrough,
|
|
4567
|
-
toggleStrong,
|
|
4568
3536
|
toggleStyle,
|
|
4569
3537
|
typewriter,
|
|
4570
3538
|
useActionHandler,
|
|
4571
3539
|
useComments,
|
|
4572
3540
|
useEditorView,
|
|
4573
|
-
useFormattingState,
|
|
4574
3541
|
useInMemoryTextModel,
|
|
4575
3542
|
useTextEditor,
|
|
4576
3543
|
useTextModel,
|