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