@dxos/react-ui-editor 0.4.5-main.dd6795b → 0.4.5-main.ec39998
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 +358 -530
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +5 -5
- 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.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts +5 -0
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -4
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts +1 -11
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/package.json +28 -25
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +29 -37
- package/src/components/TextEditor/hooks.stories.tsx +2 -10
- package/src/components/Toolbar/Toolbar.stories.tsx +2 -6
- package/src/components/Toolbar/Toolbar.tsx +0 -1
- package/src/extensions/markdown/decorate.ts +301 -0
- package/src/extensions/markdown/formatting.test.ts +17 -0
- package/src/extensions/markdown/formatting.ts +67 -76
- package/src/extensions/markdown/index.ts +1 -4
- package/src/extensions/markdown/link.ts +23 -185
- package/dist/types/src/extensions/markdown/code.d.ts +0 -2
- package/dist/types/src/extensions/markdown/code.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/heading.d.ts +0 -6
- package/dist/types/src/extensions/markdown/heading.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/hr.d.ts +0 -2
- package/dist/types/src/extensions/markdown/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/tasklist.d.ts +0 -3
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +0 -1
- package/src/extensions/markdown/code.ts +0 -162
- package/src/extensions/markdown/heading.ts +0 -59
- package/src/extensions/markdown/hr.ts +0 -71
- package/src/extensions/markdown/tasklist.ts +0 -110
|
@@ -8,7 +8,7 @@ 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 { useFocusableGroup } from "@fluentui/react-tabster";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
14
|
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2, useMemo as useMemo2 } from "react";
|
|
@@ -765,10 +765,10 @@ var blast = (options = defaultOptions) => {
|
|
|
765
765
|
const getPoint = (view, pos) => {
|
|
766
766
|
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
767
767
|
const element = document.elementFromPoint(x, y);
|
|
768
|
-
const { offsetLeft: left = 0, offsetTop:
|
|
768
|
+
const { offsetLeft: left = 0, offsetTop: top = 0 } = view.scrollDOM.parentElement ?? {};
|
|
769
769
|
const point = {
|
|
770
770
|
x: x - left,
|
|
771
|
-
y: y -
|
|
771
|
+
y: y - top
|
|
772
772
|
};
|
|
773
773
|
return {
|
|
774
774
|
element,
|
|
@@ -1871,12 +1871,207 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
|
|
|
1871
1871
|
].filter(isNotFalsy3);
|
|
1872
1872
|
};
|
|
1873
1873
|
|
|
1874
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
|
1874
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
1875
1875
|
import { syntaxTree } from "@codemirror/language";
|
|
1876
1876
|
import { RangeSetBuilder } from "@codemirror/state";
|
|
1877
|
-
import {
|
|
1877
|
+
import { EditorView as EditorView10, Decoration as Decoration4, WidgetType as WidgetType2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
|
|
1878
1878
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1879
|
-
var
|
|
1879
|
+
var FencedCodeBoundary = class extends WidgetType2 {
|
|
1880
|
+
constructor(_className) {
|
|
1881
|
+
super();
|
|
1882
|
+
this._className = _className;
|
|
1883
|
+
}
|
|
1884
|
+
toDOM() {
|
|
1885
|
+
const el = document.createElement("span");
|
|
1886
|
+
el.innerHTML = " ";
|
|
1887
|
+
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1888
|
+
return el;
|
|
1889
|
+
}
|
|
1890
|
+
};
|
|
1891
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1892
|
+
toDOM() {
|
|
1893
|
+
const el = document.createElement("span");
|
|
1894
|
+
el.className = "cm-hr";
|
|
1895
|
+
return el;
|
|
1896
|
+
}
|
|
1897
|
+
};
|
|
1898
|
+
var LinkButton = class extends WidgetType2 {
|
|
1899
|
+
constructor(url, render) {
|
|
1900
|
+
super();
|
|
1901
|
+
this.url = url;
|
|
1902
|
+
this.render = render;
|
|
1903
|
+
}
|
|
1904
|
+
eq(other) {
|
|
1905
|
+
return this.url === other.url;
|
|
1906
|
+
}
|
|
1907
|
+
toDOM(view) {
|
|
1908
|
+
const el = document.createElement("span");
|
|
1909
|
+
this.render(el, this.url);
|
|
1910
|
+
return el;
|
|
1911
|
+
}
|
|
1912
|
+
};
|
|
1913
|
+
var CheckboxWidget = class extends WidgetType2 {
|
|
1914
|
+
constructor(_checked) {
|
|
1915
|
+
super();
|
|
1916
|
+
this._checked = _checked;
|
|
1917
|
+
}
|
|
1918
|
+
eq(other) {
|
|
1919
|
+
return this._checked === other._checked;
|
|
1920
|
+
}
|
|
1921
|
+
toDOM(view) {
|
|
1922
|
+
const input = document.createElement("input");
|
|
1923
|
+
input.className = "cm-task-checkbox";
|
|
1924
|
+
input.type = "checkbox";
|
|
1925
|
+
input.checked = this._checked;
|
|
1926
|
+
if (view.state.readOnly) {
|
|
1927
|
+
input.setAttribute("disabled", "true");
|
|
1928
|
+
} else {
|
|
1929
|
+
input.onmousedown = (event) => {
|
|
1930
|
+
const pos = view.posAtDOM(input);
|
|
1931
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
1932
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
1933
|
+
view.dispatch({
|
|
1934
|
+
changes: {
|
|
1935
|
+
from: pos + 1,
|
|
1936
|
+
to: pos + 2,
|
|
1937
|
+
insert: this._checked ? " " : "x"
|
|
1938
|
+
}
|
|
1939
|
+
});
|
|
1940
|
+
event.preventDefault();
|
|
1941
|
+
}
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
return input;
|
|
1945
|
+
}
|
|
1946
|
+
ignoreEvent() {
|
|
1947
|
+
return false;
|
|
1948
|
+
}
|
|
1949
|
+
};
|
|
1950
|
+
var hide = Decoration4.replace({});
|
|
1951
|
+
var fencedCodeTop = Decoration4.replace({
|
|
1952
|
+
widget: new FencedCodeBoundary("cm-codeblock-end cm-codeblock-first")
|
|
1953
|
+
});
|
|
1954
|
+
var fencedCodeBottom = Decoration4.replace({
|
|
1955
|
+
widget: new FencedCodeBoundary("cm-codeblock-end cm-codeblock-last")
|
|
1956
|
+
});
|
|
1957
|
+
var horizontalRule = Decoration4.replace({
|
|
1958
|
+
widget: new HorizontalRuleWidget()
|
|
1959
|
+
});
|
|
1960
|
+
var checkedTask = Decoration4.replace({
|
|
1961
|
+
widget: new CheckboxWidget(true)
|
|
1962
|
+
});
|
|
1963
|
+
var uncheckedTask = Decoration4.replace({
|
|
1964
|
+
widget: new CheckboxWidget(false)
|
|
1965
|
+
});
|
|
1966
|
+
var editingRange = (state, range) => {
|
|
1967
|
+
const { readOnly, selection: { main: { head } } } = state;
|
|
1968
|
+
return !readOnly && head >= range.from && head <= range.to;
|
|
1969
|
+
};
|
|
1970
|
+
var MarksByParent = /* @__PURE__ */ new Set([
|
|
1971
|
+
"CodeMark",
|
|
1972
|
+
"EmphasisMark",
|
|
1973
|
+
"StrikethroughMark",
|
|
1974
|
+
"SubscriptMark",
|
|
1975
|
+
"SuperscriptMark"
|
|
1976
|
+
]);
|
|
1977
|
+
var buildDecorations = (view, options) => {
|
|
1978
|
+
const builder = new RangeSetBuilder();
|
|
1979
|
+
const { state } = view;
|
|
1980
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1981
|
+
syntaxTree(state).iterate({
|
|
1982
|
+
from,
|
|
1983
|
+
to,
|
|
1984
|
+
enter: (node) => {
|
|
1985
|
+
if (node.name === "FencedCode") {
|
|
1986
|
+
const editing = editingRange(state, node);
|
|
1987
|
+
for (const block of view.viewportLineBlocks) {
|
|
1988
|
+
if (block.to < node.from) {
|
|
1989
|
+
continue;
|
|
1990
|
+
}
|
|
1991
|
+
if (block.from > node.to) {
|
|
1992
|
+
break;
|
|
1993
|
+
}
|
|
1994
|
+
const first = block.from <= node.from;
|
|
1995
|
+
const last = block.to >= node.to;
|
|
1996
|
+
if (!editing && (first || last)) {
|
|
1997
|
+
builder.add(block.from, block.to, first ? fencedCodeTop : fencedCodeBottom);
|
|
1998
|
+
} else {
|
|
1999
|
+
builder.add(block.from, block.from, Decoration4.line({
|
|
2000
|
+
class: mx2("cm-code cm-codeblock-line", first && "cm-codeblock-first", last && "cm-codeblock-last")
|
|
2001
|
+
}));
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
return false;
|
|
2005
|
+
} else if (node.name === "Link") {
|
|
2006
|
+
const marks = node.node.getChildren("LinkMark");
|
|
2007
|
+
const urlNode = node.node.getChild("URL");
|
|
2008
|
+
const editing = editingRange(state, node);
|
|
2009
|
+
if (urlNode && marks.length >= 2) {
|
|
2010
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
2011
|
+
if (!editing) {
|
|
2012
|
+
builder.add(node.from, marks[0].to, hide);
|
|
2013
|
+
}
|
|
2014
|
+
builder.add(marks[0].to, marks[1].from, Decoration4.mark({
|
|
2015
|
+
tagName: "a",
|
|
2016
|
+
attributes: {
|
|
2017
|
+
class: "cm-link",
|
|
2018
|
+
href: url,
|
|
2019
|
+
rel: "noreferrer",
|
|
2020
|
+
target: "_blank"
|
|
2021
|
+
}
|
|
2022
|
+
}));
|
|
2023
|
+
if (!editing) {
|
|
2024
|
+
builder.add(marks[1].from, node.to, options.renderLinkButton ? Decoration4.replace({
|
|
2025
|
+
widget: new LinkButton(url, options.renderLinkButton)
|
|
2026
|
+
}) : hide);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
} else if (node.name === "HeaderMark") {
|
|
2030
|
+
const parent = node.node.parent;
|
|
2031
|
+
if (/^ATX/.test(parent.name) && !editingRange(state, state.doc.lineAt(node.from))) {
|
|
2032
|
+
const next = state.doc.sliceString(node.to, node.to + 1);
|
|
2033
|
+
builder.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
2034
|
+
}
|
|
2035
|
+
} else if (node.name === "HorizontalRule") {
|
|
2036
|
+
if (!editingRange(state, node)) {
|
|
2037
|
+
builder.add(node.from, node.to, horizontalRule);
|
|
2038
|
+
}
|
|
2039
|
+
} else if (node.name === "TaskMarker") {
|
|
2040
|
+
if (!editingRange(state, node)) {
|
|
2041
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2042
|
+
builder.add(node.from - 2, node.from - 1, Decoration4.mark({
|
|
2043
|
+
class: "cm-task"
|
|
2044
|
+
}));
|
|
2045
|
+
builder.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
2046
|
+
}
|
|
2047
|
+
} else if (MarksByParent.has(node.name)) {
|
|
2048
|
+
if (!editingRange(state, node.node.parent)) {
|
|
2049
|
+
builder.add(node.from, node.to, hide);
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
2055
|
+
return builder.finish();
|
|
2056
|
+
};
|
|
2057
|
+
var decorateMarkdown = (options = {}) => {
|
|
2058
|
+
return [
|
|
2059
|
+
ViewPlugin3.fromClass(class {
|
|
2060
|
+
constructor(view) {
|
|
2061
|
+
this.decorations = buildDecorations(view, options);
|
|
2062
|
+
}
|
|
2063
|
+
update(update2) {
|
|
2064
|
+
if (update2.docChanged || update2.selectionSet || update2.viewportChanged) {
|
|
2065
|
+
this.decorations = buildDecorations(update2.view, options);
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
}, {
|
|
2069
|
+
decorations: (value) => value.decorations
|
|
2070
|
+
}),
|
|
2071
|
+
formattingStyles
|
|
2072
|
+
];
|
|
2073
|
+
};
|
|
2074
|
+
var formattingStyles = EditorView10.baseTheme({
|
|
1880
2075
|
"& .cm-code": {
|
|
1881
2076
|
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1882
2077
|
},
|
|
@@ -1924,82 +2119,28 @@ var styles4 = EditorView10.baseTheme({
|
|
|
1924
2119
|
"&::after": {
|
|
1925
2120
|
background: getToken("extend.semanticColors.input.dark")
|
|
1926
2121
|
}
|
|
2122
|
+
},
|
|
2123
|
+
"& .cm-hr": {
|
|
2124
|
+
display: "inline-block",
|
|
2125
|
+
width: "100%",
|
|
2126
|
+
height: "0",
|
|
2127
|
+
verticalAlign: "middle",
|
|
2128
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2129
|
+
},
|
|
2130
|
+
"& .cm-task": {
|
|
2131
|
+
color: getToken("extend.colors.blue.500")
|
|
2132
|
+
},
|
|
2133
|
+
"& .cm-task-checkbox": {
|
|
2134
|
+
marginLeft: "4px",
|
|
2135
|
+
marginRight: "4px"
|
|
1927
2136
|
}
|
|
1928
2137
|
});
|
|
1929
|
-
var getLineRange = (lines, from, to) => {
|
|
1930
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1931
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1932
|
-
return [
|
|
1933
|
-
start,
|
|
1934
|
-
end
|
|
1935
|
-
];
|
|
1936
|
-
};
|
|
1937
|
-
var LineWidget = class extends WidgetType2 {
|
|
1938
|
-
constructor(_className) {
|
|
1939
|
-
super();
|
|
1940
|
-
this._className = _className;
|
|
1941
|
-
}
|
|
1942
|
-
toDOM() {
|
|
1943
|
-
const el = document.createElement("span");
|
|
1944
|
-
el.innerHTML = " ";
|
|
1945
|
-
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1946
|
-
return el;
|
|
1947
|
-
}
|
|
1948
|
-
};
|
|
1949
|
-
var top = new LineWidget("cm-codeblock-end cm-codeblock-first");
|
|
1950
|
-
var bottom = new LineWidget("cm-codeblock-end cm-codeblock-last");
|
|
1951
|
-
var buildDecorations = (view) => {
|
|
1952
|
-
const builder = new RangeSetBuilder();
|
|
1953
|
-
const { state } = view;
|
|
1954
|
-
const blocks = view.viewportLineBlocks;
|
|
1955
|
-
const cursor = state.selection.main.head;
|
|
1956
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1957
|
-
syntaxTree(state).iterate({
|
|
1958
|
-
enter: (node) => {
|
|
1959
|
-
if (node.name === "FencedCode") {
|
|
1960
|
-
const editing = !view.state.readOnly && cursor >= node.from && cursor <= node.to;
|
|
1961
|
-
const range = getLineRange(blocks, node.from, node.to);
|
|
1962
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1963
|
-
const block = blocks[i];
|
|
1964
|
-
if (!editing && (i === range[0] || i === range[1])) {
|
|
1965
|
-
builder.add(block.from, block.to, Decoration4.replace({
|
|
1966
|
-
widget: i === range[0] ? top : bottom
|
|
1967
|
-
}));
|
|
1968
|
-
} else {
|
|
1969
|
-
builder.add(block.from, block.from, Decoration4.line({
|
|
1970
|
-
class: mx2("cm-code cm-codeblock-line", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1971
|
-
}));
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
},
|
|
1976
|
-
from,
|
|
1977
|
-
to
|
|
1978
|
-
});
|
|
1979
|
-
}
|
|
1980
|
-
return builder.finish();
|
|
1981
|
-
};
|
|
1982
|
-
var code2 = () => {
|
|
1983
|
-
return [
|
|
1984
|
-
ViewPlugin3.fromClass(class {
|
|
1985
|
-
constructor(view) {
|
|
1986
|
-
this.decorations = buildDecorations(view);
|
|
1987
|
-
}
|
|
1988
|
-
update(update2) {
|
|
1989
|
-
this.decorations = buildDecorations(update2.view);
|
|
1990
|
-
}
|
|
1991
|
-
}, {
|
|
1992
|
-
decorations: (value) => value.decorations
|
|
1993
|
-
}),
|
|
1994
|
-
styles4
|
|
1995
|
-
];
|
|
1996
|
-
};
|
|
1997
2138
|
|
|
1998
2139
|
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1999
2140
|
import { snippet } from "@codemirror/autocomplete";
|
|
2000
2141
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
2001
|
-
import {
|
|
2002
|
-
import {
|
|
2142
|
+
import { EditorSelection } from "@codemirror/state";
|
|
2143
|
+
import { EditorView as EditorView11, keymap as keymap5 } from "@codemirror/view";
|
|
2003
2144
|
import { useState, useMemo } from "react";
|
|
2004
2145
|
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;
|
|
2005
2146
|
var Inline;
|
|
@@ -2020,6 +2161,7 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
2020
2161
|
const changes = [];
|
|
2021
2162
|
let prevBlock = -1;
|
|
2022
2163
|
for (const range of ranges) {
|
|
2164
|
+
let sawBlock = false;
|
|
2023
2165
|
syntaxTree2(state).iterate({
|
|
2024
2166
|
from: range.from,
|
|
2025
2167
|
to: range.to,
|
|
@@ -2027,6 +2169,7 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
2027
2169
|
if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
|
|
2028
2170
|
return;
|
|
2029
2171
|
}
|
|
2172
|
+
sawBlock = true;
|
|
2030
2173
|
prevBlock = node.from;
|
|
2031
2174
|
const blockType = Textblocks[node.name];
|
|
2032
2175
|
const isHeading = /heading(\d)/.exec(blockType);
|
|
@@ -2071,12 +2214,22 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
2071
2214
|
}
|
|
2072
2215
|
}
|
|
2073
2216
|
});
|
|
2217
|
+
let line;
|
|
2218
|
+
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state.doc.lineAt(range.from)).text)) {
|
|
2219
|
+
changes.push({
|
|
2220
|
+
from: line.from,
|
|
2221
|
+
to: line.to,
|
|
2222
|
+
insert: "#".repeat(level) + " "
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2074
2225
|
}
|
|
2075
2226
|
if (!changes.length) {
|
|
2076
2227
|
return false;
|
|
2077
2228
|
}
|
|
2229
|
+
const changeSet = state.changes(changes);
|
|
2078
2230
|
dispatch(state.update({
|
|
2079
|
-
changes,
|
|
2231
|
+
changes: changeSet,
|
|
2232
|
+
selection: state.selection.map(changeSet, 1),
|
|
2080
2233
|
userEvent: "format.setHeading",
|
|
2081
2234
|
scrollIntoView: true
|
|
2082
2235
|
}));
|
|
@@ -2148,10 +2301,16 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2148
2301
|
const closeStart = node.to - size;
|
|
2149
2302
|
if (markType === type) {
|
|
2150
2303
|
if (openEnd <= from && closeStart >= from) {
|
|
2151
|
-
startCovered = openEnd === from
|
|
2304
|
+
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2305
|
+
from: node.from,
|
|
2306
|
+
to: openEnd
|
|
2307
|
+
} : true;
|
|
2152
2308
|
}
|
|
2153
2309
|
if (openEnd <= to && closeStart >= to) {
|
|
2154
|
-
endCovered = closeStart === to
|
|
2310
|
+
endCovered = !enable && closeStart === skipMarkers(to, node.node, 1, closeStart) ? {
|
|
2311
|
+
from: closeStart,
|
|
2312
|
+
to: node.to
|
|
2313
|
+
} : true;
|
|
2155
2314
|
}
|
|
2156
2315
|
}
|
|
2157
2316
|
if (markType === type || type === 3 && enable) {
|
|
@@ -2200,22 +2359,16 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2200
2359
|
});
|
|
2201
2360
|
}
|
|
2202
2361
|
} else {
|
|
2203
|
-
if (startCovered === "
|
|
2204
|
-
changes2.push(
|
|
2205
|
-
from: from - marker.length,
|
|
2206
|
-
to: from
|
|
2207
|
-
});
|
|
2362
|
+
if (typeof startCovered === "object") {
|
|
2363
|
+
changes2.push(startCovered);
|
|
2208
2364
|
} else if (startCovered) {
|
|
2209
2365
|
changes2.push({
|
|
2210
2366
|
from: skipSpaces(rangeStart, state.doc, -1, blockStart),
|
|
2211
2367
|
insert: marker
|
|
2212
2368
|
});
|
|
2213
2369
|
}
|
|
2214
|
-
if (endCovered === "
|
|
2215
|
-
changes2.push(
|
|
2216
|
-
from: to,
|
|
2217
|
-
to: to + marker.length
|
|
2218
|
-
});
|
|
2370
|
+
if (typeof endCovered === "object") {
|
|
2371
|
+
changes2.push(endCovered);
|
|
2219
2372
|
} else if (endCovered) {
|
|
2220
2373
|
changes2.push({
|
|
2221
2374
|
from: skipSpaces(rangeEnd, state.doc, 1, blockEnd),
|
|
@@ -2226,6 +2379,15 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2226
2379
|
}
|
|
2227
2380
|
}
|
|
2228
2381
|
});
|
|
2382
|
+
if (blockStart < 0 && range.empty && enable && !/\S/.test(state.doc.lineAt(range.from).text)) {
|
|
2383
|
+
return {
|
|
2384
|
+
changes: {
|
|
2385
|
+
from: range.head,
|
|
2386
|
+
insert: marker + marker
|
|
2387
|
+
},
|
|
2388
|
+
range: EditorSelection.cursor(range.head + marker.length)
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2229
2391
|
const changeSet = state.changes(changes2.concat(changesAtEnd));
|
|
2230
2392
|
return {
|
|
2231
2393
|
changes: changeSet,
|
|
@@ -2271,6 +2433,19 @@ var skipSpaces = (pos, doc, dir, limit) => {
|
|
|
2271
2433
|
}
|
|
2272
2434
|
return pos;
|
|
2273
2435
|
};
|
|
2436
|
+
var skipMarkers = (pos, tree, dir, limit) => {
|
|
2437
|
+
for (; ; ) {
|
|
2438
|
+
const next = tree.resolve(pos, dir);
|
|
2439
|
+
if (!IgnoreInline.has(next.name)) {
|
|
2440
|
+
return pos;
|
|
2441
|
+
}
|
|
2442
|
+
const moveTo = dir < 0 ? next.from : next.to;
|
|
2443
|
+
if (limit != null && (dir < 0 ? moveTo < limit : moveTo > limit)) {
|
|
2444
|
+
return pos;
|
|
2445
|
+
}
|
|
2446
|
+
pos = moveTo;
|
|
2447
|
+
}
|
|
2448
|
+
};
|
|
2274
2449
|
var snippets = {
|
|
2275
2450
|
codeblock: snippet([
|
|
2276
2451
|
//
|
|
@@ -2549,8 +2724,10 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
2549
2724
|
renumberListItems(next.firstChild, last.counter + 1, changes, state.doc);
|
|
2550
2725
|
}
|
|
2551
2726
|
}
|
|
2727
|
+
const changeSet = state.changes(changes);
|
|
2552
2728
|
dispatch(state.update({
|
|
2553
|
-
changes,
|
|
2729
|
+
changes: changeSet,
|
|
2730
|
+
selection: state.selection.map(changeSet, 1),
|
|
2554
2731
|
userEvent: "format.list.add",
|
|
2555
2732
|
scrollIntoView: true
|
|
2556
2733
|
}));
|
|
@@ -2644,6 +2821,7 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2644
2821
|
const lines = [];
|
|
2645
2822
|
let lastBlock = -1;
|
|
2646
2823
|
for (const { from, to } of state.selection.ranges) {
|
|
2824
|
+
const sawBlock = false;
|
|
2647
2825
|
syntaxTree2(state).iterate({
|
|
2648
2826
|
from,
|
|
2649
2827
|
to,
|
|
@@ -2653,9 +2831,9 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2653
2831
|
return false;
|
|
2654
2832
|
}
|
|
2655
2833
|
lastBlock = node.from;
|
|
2656
|
-
let
|
|
2657
|
-
if (
|
|
2658
|
-
const prevLine = state.doc.line(
|
|
2834
|
+
let line2 = state.doc.lineAt(node.from);
|
|
2835
|
+
if (line2.number > 1) {
|
|
2836
|
+
const prevLine = state.doc.line(line2.number - 1);
|
|
2659
2837
|
if (/^[>\s]*$/.test(prevLine.text)) {
|
|
2660
2838
|
if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
|
|
2661
2839
|
lines.push(prevLine);
|
|
@@ -2663,14 +2841,14 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2663
2841
|
}
|
|
2664
2842
|
}
|
|
2665
2843
|
for (; ; ) {
|
|
2666
|
-
lines.push(
|
|
2667
|
-
if (
|
|
2844
|
+
lines.push(line2);
|
|
2845
|
+
if (line2.to >= node.to) {
|
|
2668
2846
|
break;
|
|
2669
2847
|
}
|
|
2670
|
-
|
|
2848
|
+
line2 = state.doc.line(line2.number + 1);
|
|
2671
2849
|
}
|
|
2672
|
-
if (!enable &&
|
|
2673
|
-
const nextLine = state.doc.line(
|
|
2850
|
+
if (!enable && line2.number < state.doc.lines) {
|
|
2851
|
+
const nextLine = state.doc.line(line2.number + 1);
|
|
2674
2852
|
if (/^[>\s]*$/.test(nextLine.text)) {
|
|
2675
2853
|
lines.push(nextLine);
|
|
2676
2854
|
}
|
|
@@ -2679,6 +2857,10 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2679
2857
|
}
|
|
2680
2858
|
}
|
|
2681
2859
|
});
|
|
2860
|
+
let line;
|
|
2861
|
+
if (!sawBlock && enable && from === to && !/\S/.test((line = state.doc.lineAt(from)).text)) {
|
|
2862
|
+
lines.push(line);
|
|
2863
|
+
}
|
|
2682
2864
|
}
|
|
2683
2865
|
const changes = [];
|
|
2684
2866
|
for (const line of lines) {
|
|
@@ -2700,8 +2882,10 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
2700
2882
|
if (!changes.length) {
|
|
2701
2883
|
return false;
|
|
2702
2884
|
}
|
|
2885
|
+
const changeSet = state.changes(changes);
|
|
2703
2886
|
dispatch(state.update({
|
|
2704
|
-
changes,
|
|
2887
|
+
changes: changeSet,
|
|
2888
|
+
selection: state.selection.map(changeSet, 1),
|
|
2705
2889
|
userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
|
|
2706
2890
|
scrollIntoView: true
|
|
2707
2891
|
}));
|
|
@@ -2833,56 +3017,7 @@ var formatting = (options = {}) => {
|
|
|
2833
3017
|
key: "meta-b",
|
|
2834
3018
|
run: toggleStrong
|
|
2835
3019
|
}
|
|
2836
|
-
])
|
|
2837
|
-
styling()
|
|
2838
|
-
];
|
|
2839
|
-
};
|
|
2840
|
-
var styling = () => {
|
|
2841
|
-
const buildDecorations7 = (view) => {
|
|
2842
|
-
const builder = new RangeSetBuilder2();
|
|
2843
|
-
const { state } = view;
|
|
2844
|
-
const cursor = state.selection.main.head;
|
|
2845
|
-
const replace = (node, marks) => {
|
|
2846
|
-
if (cursor <= node.from || cursor >= node.to) {
|
|
2847
|
-
for (const mark2 of marks) {
|
|
2848
|
-
builder.add(mark2.from, mark2.to, Decoration5.replace({}));
|
|
2849
|
-
}
|
|
2850
|
-
}
|
|
2851
|
-
};
|
|
2852
|
-
for (const { from, to } of view.visibleRanges) {
|
|
2853
|
-
syntaxTree2(state).iterate({
|
|
2854
|
-
enter: (node) => {
|
|
2855
|
-
switch (node.name) {
|
|
2856
|
-
case "Emphasis":
|
|
2857
|
-
case "StrongEmphasis": {
|
|
2858
|
-
const marks = node.node.getChildren("EmphasisMark");
|
|
2859
|
-
replace(node, marks);
|
|
2860
|
-
break;
|
|
2861
|
-
}
|
|
2862
|
-
case "Strikethrough": {
|
|
2863
|
-
const marks = node.node.getChildren("StrikethroughMark");
|
|
2864
|
-
replace(node, marks);
|
|
2865
|
-
break;
|
|
2866
|
-
}
|
|
2867
|
-
}
|
|
2868
|
-
},
|
|
2869
|
-
from,
|
|
2870
|
-
to
|
|
2871
|
-
});
|
|
2872
|
-
}
|
|
2873
|
-
return builder.finish();
|
|
2874
|
-
};
|
|
2875
|
-
return [
|
|
2876
|
-
ViewPlugin4.fromClass(class {
|
|
2877
|
-
constructor(view) {
|
|
2878
|
-
this.decorations = buildDecorations7(view);
|
|
2879
|
-
}
|
|
2880
|
-
update(update2) {
|
|
2881
|
-
this.decorations = buildDecorations7(update2.view);
|
|
2882
|
-
}
|
|
2883
|
-
}, {
|
|
2884
|
-
decorations: (value) => value.decorations
|
|
2885
|
-
})
|
|
3020
|
+
])
|
|
2886
3021
|
];
|
|
2887
3022
|
};
|
|
2888
3023
|
var InlineMarker = {
|
|
@@ -2932,7 +3067,7 @@ var getFormatting = (state) => {
|
|
|
2932
3067
|
null,
|
|
2933
3068
|
null
|
|
2934
3069
|
];
|
|
2935
|
-
let
|
|
3070
|
+
let link = false;
|
|
2936
3071
|
let blockQuote = null;
|
|
2937
3072
|
let listStyle = null;
|
|
2938
3073
|
const stack = [];
|
|
@@ -2994,7 +3129,7 @@ var getFormatting = (state) => {
|
|
|
2994
3129
|
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2995
3130
|
stack.push(name);
|
|
2996
3131
|
} else if (name === "Link") {
|
|
2997
|
-
|
|
3132
|
+
link = true;
|
|
2998
3133
|
} else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
|
|
2999
3134
|
if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
3000
3135
|
stack[stack.length - 1] = "TaskList";
|
|
@@ -3069,7 +3204,7 @@ var getFormatting = (state) => {
|
|
|
3069
3204
|
emphasis: inline[1] ?? false,
|
|
3070
3205
|
strong: inline[0] ?? false,
|
|
3071
3206
|
strikethrough: inline[2] ?? false,
|
|
3072
|
-
link
|
|
3207
|
+
link,
|
|
3073
3208
|
listStyle: listStyle || null
|
|
3074
3209
|
};
|
|
3075
3210
|
};
|
|
@@ -3089,117 +3224,14 @@ var useFormattingState = () => {
|
|
|
3089
3224
|
];
|
|
3090
3225
|
};
|
|
3091
3226
|
|
|
3092
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
3093
|
-
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3094
|
-
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
3095
|
-
import { Decoration as Decoration6, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
3096
|
-
var buildDecorations2 = (view) => {
|
|
3097
|
-
const builder = new RangeSetBuilder3();
|
|
3098
|
-
const { state } = view;
|
|
3099
|
-
const cursor = state.selection.main.head;
|
|
3100
|
-
for (const { from, to } of view.visibleRanges) {
|
|
3101
|
-
syntaxTree3(state).iterate({
|
|
3102
|
-
enter: (node) => {
|
|
3103
|
-
switch (node.name) {
|
|
3104
|
-
case "ATXHeading1":
|
|
3105
|
-
case "ATXHeading2":
|
|
3106
|
-
case "ATXHeading3":
|
|
3107
|
-
case "ATXHeading4":
|
|
3108
|
-
case "ATXHeading5":
|
|
3109
|
-
case "ATXHeading6": {
|
|
3110
|
-
const mark2 = node.node.getChild("HeaderMark");
|
|
3111
|
-
if (mark2) {
|
|
3112
|
-
if (!view.hasFocus || view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
3113
|
-
builder.add(mark2.from, mark2.to + 1, Decoration6.replace({}));
|
|
3114
|
-
}
|
|
3115
|
-
}
|
|
3116
|
-
}
|
|
3117
|
-
}
|
|
3118
|
-
},
|
|
3119
|
-
from,
|
|
3120
|
-
to
|
|
3121
|
-
});
|
|
3122
|
-
}
|
|
3123
|
-
return builder.finish();
|
|
3124
|
-
};
|
|
3125
|
-
var heading2 = () => {
|
|
3126
|
-
return [
|
|
3127
|
-
ViewPlugin5.fromClass(class {
|
|
3128
|
-
constructor(view) {
|
|
3129
|
-
this.decorations = buildDecorations2(view);
|
|
3130
|
-
}
|
|
3131
|
-
update(update2) {
|
|
3132
|
-
this.decorations = buildDecorations2(update2.view);
|
|
3133
|
-
}
|
|
3134
|
-
}, {
|
|
3135
|
-
decorations: (value) => value.decorations
|
|
3136
|
-
})
|
|
3137
|
-
];
|
|
3138
|
-
};
|
|
3139
|
-
|
|
3140
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
3141
|
-
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
3142
|
-
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
3143
|
-
import { Decoration as Decoration7, EditorView as EditorView12, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
3144
|
-
var styles5 = EditorView12.baseTheme({
|
|
3145
|
-
"& .cm-hr": {
|
|
3146
|
-
// Note that block-level decorations should not have vertical margins,
|
|
3147
|
-
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
3148
|
-
}
|
|
3149
|
-
});
|
|
3150
|
-
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
3151
|
-
toDOM() {
|
|
3152
|
-
const el = document.createElement("div");
|
|
3153
|
-
el.className = "cm-hr";
|
|
3154
|
-
return el;
|
|
3155
|
-
}
|
|
3156
|
-
};
|
|
3157
|
-
var decoration = Decoration7.replace({
|
|
3158
|
-
widget: new HorizontalRuleWidget()
|
|
3159
|
-
});
|
|
3160
|
-
var buildDecorations3 = (view) => {
|
|
3161
|
-
const builder = new RangeSetBuilder4();
|
|
3162
|
-
const { state } = view;
|
|
3163
|
-
const cursor = state.selection.main.head;
|
|
3164
|
-
for (const { from, to } of view.visibleRanges) {
|
|
3165
|
-
syntaxTree4(state).iterate({
|
|
3166
|
-
enter: (node) => {
|
|
3167
|
-
if (node.name === "HorizontalRule") {
|
|
3168
|
-
if (cursor <= node.from || cursor >= node.to) {
|
|
3169
|
-
builder.add(node.from, node.to, decoration);
|
|
3170
|
-
}
|
|
3171
|
-
}
|
|
3172
|
-
},
|
|
3173
|
-
from,
|
|
3174
|
-
to
|
|
3175
|
-
});
|
|
3176
|
-
}
|
|
3177
|
-
return builder.finish();
|
|
3178
|
-
};
|
|
3179
|
-
var hr = () => {
|
|
3180
|
-
return [
|
|
3181
|
-
ViewPlugin6.fromClass(class {
|
|
3182
|
-
constructor(view) {
|
|
3183
|
-
this.decorations = buildDecorations3(view);
|
|
3184
|
-
}
|
|
3185
|
-
update(update2) {
|
|
3186
|
-
this.decorations = buildDecorations3(update2.view);
|
|
3187
|
-
}
|
|
3188
|
-
}, {
|
|
3189
|
-
decorations: (value) => value.decorations
|
|
3190
|
-
}),
|
|
3191
|
-
styles5
|
|
3192
|
-
];
|
|
3193
|
-
};
|
|
3194
|
-
|
|
3195
3227
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3196
|
-
import { syntaxTree as
|
|
3228
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3197
3229
|
import { StateField as StateField4 } from "@codemirror/state";
|
|
3198
|
-
import { Decoration as
|
|
3230
|
+
import { Decoration as Decoration5, EditorView as EditorView12, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
3199
3231
|
var image = (options = {}) => {
|
|
3200
3232
|
return StateField4.define({
|
|
3201
3233
|
create: (state) => {
|
|
3202
|
-
return
|
|
3234
|
+
return Decoration5.set(buildDecorations2(0, state.doc.length, state));
|
|
3203
3235
|
},
|
|
3204
3236
|
update: (value, tr) => {
|
|
3205
3237
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -3219,26 +3251,26 @@ var image = (options = {}) => {
|
|
|
3219
3251
|
filterFrom: from,
|
|
3220
3252
|
filterTo: to,
|
|
3221
3253
|
filter: () => false,
|
|
3222
|
-
add:
|
|
3254
|
+
add: buildDecorations2(from, to, tr.state)
|
|
3223
3255
|
});
|
|
3224
3256
|
},
|
|
3225
|
-
provide: (field) =>
|
|
3257
|
+
provide: (field) => EditorView12.decorations.from(field)
|
|
3226
3258
|
});
|
|
3227
3259
|
};
|
|
3228
|
-
var
|
|
3260
|
+
var buildDecorations2 = (from, to, state) => {
|
|
3229
3261
|
const decorations = [];
|
|
3230
3262
|
const cursor = state.selection.main.head;
|
|
3231
|
-
|
|
3263
|
+
syntaxTree3(state).iterate({
|
|
3232
3264
|
enter: (node) => {
|
|
3233
3265
|
if (node.name === "Image") {
|
|
3234
3266
|
const urlNode = node.node.getChild("URL");
|
|
3235
3267
|
if (urlNode) {
|
|
3236
|
-
const
|
|
3268
|
+
const hide2 = state.readOnly || cursor < node.from || cursor > node.to;
|
|
3237
3269
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
3238
|
-
decorations.push(
|
|
3270
|
+
decorations.push(Decoration5.replace({
|
|
3239
3271
|
block: true,
|
|
3240
3272
|
widget: new ImageWidget(url)
|
|
3241
|
-
}).range(
|
|
3273
|
+
}).range(hide2 ? node.from : node.to, node.to));
|
|
3242
3274
|
}
|
|
3243
3275
|
}
|
|
3244
3276
|
},
|
|
@@ -3247,7 +3279,7 @@ var buildDecorations4 = (from, to, state) => {
|
|
|
3247
3279
|
});
|
|
3248
3280
|
return decorations;
|
|
3249
3281
|
};
|
|
3250
|
-
var ImageWidget = class extends
|
|
3282
|
+
var ImageWidget = class extends WidgetType3 {
|
|
3251
3283
|
constructor(_url) {
|
|
3252
3284
|
super();
|
|
3253
3285
|
this._url = _url;
|
|
@@ -3265,155 +3297,52 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
3265
3297
|
};
|
|
3266
3298
|
|
|
3267
3299
|
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
3268
|
-
import { syntaxTree as
|
|
3269
|
-
import {
|
|
3270
|
-
import { hoverTooltip as hoverTooltip2, Decoration as Decoration9, ViewPlugin as ViewPlugin7, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
3300
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
3301
|
+
import { hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
|
3271
3302
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
3272
|
-
var
|
|
3273
|
-
const
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
}
|
|
3282
|
-
}
|
|
3283
|
-
}, {
|
|
3284
|
-
decorations: (value) => value.decorations
|
|
3285
|
-
})
|
|
3286
|
-
];
|
|
3287
|
-
if (options.onHover) {
|
|
3288
|
-
extensions.push(
|
|
3289
|
-
// https://codemirror.net/examples/tooltip
|
|
3290
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
3291
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
3292
|
-
hoverTooltip2((view, pos, side) => {
|
|
3293
|
-
const syntax = syntaxTree6(view.state).resolveInner(pos, side);
|
|
3294
|
-
let link2 = null;
|
|
3295
|
-
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
3296
|
-
link2 = node.name === "Link" ? node : null;
|
|
3297
|
-
}
|
|
3298
|
-
const url = link2 && link2.getChild("URL");
|
|
3299
|
-
if (!url || !link2) {
|
|
3300
|
-
return null;
|
|
3301
|
-
}
|
|
3302
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
3303
|
-
return {
|
|
3304
|
-
pos: link2.from,
|
|
3305
|
-
end: link2.to,
|
|
3306
|
-
above: true,
|
|
3307
|
-
create: () => {
|
|
3308
|
-
const el = document.createElement("div");
|
|
3309
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
3310
|
-
options.onHover(el, urlText);
|
|
3311
|
-
return {
|
|
3312
|
-
dom: el,
|
|
3313
|
-
offset: {
|
|
3314
|
-
x: 0,
|
|
3315
|
-
y: 4
|
|
3316
|
-
}
|
|
3317
|
-
};
|
|
3318
|
-
}
|
|
3319
|
-
};
|
|
3320
|
-
})
|
|
3321
|
-
);
|
|
3322
|
-
}
|
|
3323
|
-
return extensions;
|
|
3324
|
-
};
|
|
3325
|
-
var LinkButton = class extends WidgetType5 {
|
|
3326
|
-
constructor(_url, _onAttach) {
|
|
3327
|
-
super();
|
|
3328
|
-
this._url = _url;
|
|
3329
|
-
this._onAttach = _onAttach;
|
|
3330
|
-
}
|
|
3331
|
-
eq(other) {
|
|
3332
|
-
return this._url === other._url;
|
|
3333
|
-
}
|
|
3334
|
-
toDOM(view) {
|
|
3335
|
-
const el = document.createElement("span");
|
|
3336
|
-
this._onAttach(el, this._url);
|
|
3337
|
-
return el;
|
|
3338
|
-
}
|
|
3339
|
-
};
|
|
3340
|
-
var LinkText = class extends WidgetType5 {
|
|
3341
|
-
constructor(_text, _url) {
|
|
3342
|
-
super();
|
|
3343
|
-
this._text = _text;
|
|
3344
|
-
this._url = _url;
|
|
3345
|
-
}
|
|
3346
|
-
eq(other) {
|
|
3347
|
-
return this._url === other._url;
|
|
3303
|
+
var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
|
|
3304
|
+
const syntax = syntaxTree4(view.state).resolveInner(pos, side);
|
|
3305
|
+
let link = null;
|
|
3306
|
+
for (let i = 0, node = syntax; !link && node && i < 5; node = node.parent, i++) {
|
|
3307
|
+
link = node.name === "Link" ? node : null;
|
|
3308
|
+
}
|
|
3309
|
+
const url = link && link.getChild("URL");
|
|
3310
|
+
if (!url || !link) {
|
|
3311
|
+
return null;
|
|
3348
3312
|
}
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
}
|
|
3313
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
3314
|
+
return {
|
|
3315
|
+
pos: link.from,
|
|
3316
|
+
end: link.to,
|
|
3317
|
+
above: true,
|
|
3318
|
+
create: () => {
|
|
3319
|
+
const el = document.createElement("div");
|
|
3320
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
3321
|
+
render(el, urlText);
|
|
3322
|
+
return {
|
|
3323
|
+
dom: el,
|
|
3324
|
+
offset: {
|
|
3325
|
+
x: 0,
|
|
3326
|
+
y: 4
|
|
3327
|
+
}
|
|
3364
3328
|
};
|
|
3365
3329
|
}
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
};
|
|
3369
|
-
var buildDecorations5 = (view, options) => {
|
|
3370
|
-
const builder = new RangeSetBuilder5();
|
|
3371
|
-
const { state } = view;
|
|
3372
|
-
const cursor = state.selection.main.head;
|
|
3373
|
-
for (const { from, to } of view.visibleRanges) {
|
|
3374
|
-
syntaxTree6(state).iterate({
|
|
3375
|
-
enter: (node) => {
|
|
3376
|
-
if (node.name === "Link") {
|
|
3377
|
-
const marks = node.node.getChildren("LinkMark");
|
|
3378
|
-
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
3379
|
-
const urlNode = node.node.getChild("URL");
|
|
3380
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
3381
|
-
if (!url) {
|
|
3382
|
-
return false;
|
|
3383
|
-
}
|
|
3384
|
-
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
3385
|
-
builder.add(node.from, node.to, Decoration9.replace({
|
|
3386
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
3387
|
-
}));
|
|
3388
|
-
}
|
|
3389
|
-
if (options.onRender) {
|
|
3390
|
-
builder.add(node.to, node.to, Decoration9.replace({
|
|
3391
|
-
widget: new LinkButton(url, options.onRender)
|
|
3392
|
-
}));
|
|
3393
|
-
}
|
|
3394
|
-
return false;
|
|
3395
|
-
}
|
|
3396
|
-
},
|
|
3397
|
-
from,
|
|
3398
|
-
to
|
|
3399
|
-
});
|
|
3400
|
-
}
|
|
3401
|
-
return builder.finish();
|
|
3402
|
-
};
|
|
3330
|
+
};
|
|
3331
|
+
});
|
|
3403
3332
|
|
|
3404
3333
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
3405
|
-
import { syntaxTree as
|
|
3406
|
-
import { RangeSetBuilder as
|
|
3407
|
-
import { Decoration as
|
|
3334
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
3335
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField5 } from "@codemirror/state";
|
|
3336
|
+
import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3408
3337
|
var table = (options = {}) => {
|
|
3409
3338
|
return StateField5.define({
|
|
3410
3339
|
create: (state) => update(state, options),
|
|
3411
3340
|
update: (_, tr) => update(tr.state, options),
|
|
3412
|
-
provide: (field) =>
|
|
3341
|
+
provide: (field) => EditorView13.decorations.from(field)
|
|
3413
3342
|
});
|
|
3414
3343
|
};
|
|
3415
3344
|
var update = (state, options) => {
|
|
3416
|
-
const builder = new
|
|
3345
|
+
const builder = new RangeSetBuilder2();
|
|
3417
3346
|
const cursor = state.selection.main.head;
|
|
3418
3347
|
const tables = [];
|
|
3419
3348
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -3421,7 +3350,7 @@ var update = (state, options) => {
|
|
|
3421
3350
|
const table2 = getTable();
|
|
3422
3351
|
return table2.rows?.[table2.rows.length - 1];
|
|
3423
3352
|
};
|
|
3424
|
-
|
|
3353
|
+
syntaxTree5(state).iterate({
|
|
3425
3354
|
enter: (node) => {
|
|
3426
3355
|
switch (node.name) {
|
|
3427
3356
|
case "Table": {
|
|
@@ -3452,17 +3381,17 @@ var update = (state, options) => {
|
|
|
3452
3381
|
}
|
|
3453
3382
|
});
|
|
3454
3383
|
tables.forEach((table2) => {
|
|
3455
|
-
const
|
|
3456
|
-
|
|
3384
|
+
const hide2 = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
3385
|
+
hide2 && builder.add(table2.from, table2.to, Decoration6.replace({
|
|
3457
3386
|
widget: new TableWidget(table2)
|
|
3458
3387
|
}));
|
|
3459
|
-
builder.add(table2.from, table2.to,
|
|
3388
|
+
builder.add(table2.from, table2.to, Decoration6.mark({
|
|
3460
3389
|
class: "cm-table"
|
|
3461
3390
|
}));
|
|
3462
3391
|
});
|
|
3463
3392
|
return builder.finish();
|
|
3464
3393
|
};
|
|
3465
|
-
var TableWidget = class extends
|
|
3394
|
+
var TableWidget = class extends WidgetType4 {
|
|
3466
3395
|
constructor(_table) {
|
|
3467
3396
|
super();
|
|
3468
3397
|
this._table = _table;
|
|
@@ -3499,103 +3428,6 @@ var TableWidget = class extends WidgetType6 {
|
|
|
3499
3428
|
}
|
|
3500
3429
|
};
|
|
3501
3430
|
|
|
3502
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
3503
|
-
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
3504
|
-
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
3505
|
-
import { EditorView as EditorView15, Decoration as Decoration11, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
3506
|
-
var styles6 = EditorView15.baseTheme({
|
|
3507
|
-
"& .cm-task": {
|
|
3508
|
-
color: getToken("extend.colors.blue.500")
|
|
3509
|
-
},
|
|
3510
|
-
"& .cm-task-checkbox": {
|
|
3511
|
-
marginLeft: "4px",
|
|
3512
|
-
marginRight: "4px"
|
|
3513
|
-
}
|
|
3514
|
-
});
|
|
3515
|
-
var CheckboxWidget = class extends WidgetType7 {
|
|
3516
|
-
constructor(_checked) {
|
|
3517
|
-
super();
|
|
3518
|
-
this._checked = _checked;
|
|
3519
|
-
}
|
|
3520
|
-
eq(other) {
|
|
3521
|
-
return this._checked === other._checked;
|
|
3522
|
-
}
|
|
3523
|
-
toDOM(view) {
|
|
3524
|
-
const input = document.createElement("input");
|
|
3525
|
-
input.className = "cm-task-checkbox";
|
|
3526
|
-
input.type = "checkbox";
|
|
3527
|
-
input.checked = this._checked;
|
|
3528
|
-
if (view.state.readOnly) {
|
|
3529
|
-
input.setAttribute("disabled", "true");
|
|
3530
|
-
} else {
|
|
3531
|
-
input.onmousedown = (event) => {
|
|
3532
|
-
const pos = view.posAtDOM(input);
|
|
3533
|
-
const text = view.state.sliceDoc(pos, pos + 3);
|
|
3534
|
-
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
3535
|
-
view.dispatch({
|
|
3536
|
-
changes: {
|
|
3537
|
-
from: pos + 1,
|
|
3538
|
-
to: pos + 2,
|
|
3539
|
-
insert: this._checked ? " " : "x"
|
|
3540
|
-
}
|
|
3541
|
-
});
|
|
3542
|
-
event.preventDefault();
|
|
3543
|
-
}
|
|
3544
|
-
};
|
|
3545
|
-
}
|
|
3546
|
-
return input;
|
|
3547
|
-
}
|
|
3548
|
-
ignoreEvent() {
|
|
3549
|
-
return false;
|
|
3550
|
-
}
|
|
3551
|
-
};
|
|
3552
|
-
var checkedDecoration = Decoration11.replace({
|
|
3553
|
-
widget: new CheckboxWidget(true)
|
|
3554
|
-
});
|
|
3555
|
-
var uncheckedDecoration = Decoration11.replace({
|
|
3556
|
-
widget: new CheckboxWidget(false)
|
|
3557
|
-
});
|
|
3558
|
-
var buildDecorations6 = (view) => {
|
|
3559
|
-
const builder = new RangeSetBuilder7();
|
|
3560
|
-
const { state } = view;
|
|
3561
|
-
const cursor = state.selection.main.head;
|
|
3562
|
-
for (const { from, to } of view.visibleRanges) {
|
|
3563
|
-
syntaxTree8(state).iterate({
|
|
3564
|
-
enter: (node) => {
|
|
3565
|
-
if (node.name === "TaskMarker") {
|
|
3566
|
-
if (cursor < node.from || cursor > node.to) {
|
|
3567
|
-
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
3568
|
-
builder.add(node.from - 2, node.from - 1, Decoration11.mark({
|
|
3569
|
-
class: "cm-task"
|
|
3570
|
-
}));
|
|
3571
|
-
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
},
|
|
3575
|
-
from,
|
|
3576
|
-
to
|
|
3577
|
-
});
|
|
3578
|
-
}
|
|
3579
|
-
return builder.finish();
|
|
3580
|
-
};
|
|
3581
|
-
var tasklist = (options = {}) => {
|
|
3582
|
-
return [
|
|
3583
|
-
ViewPlugin8.fromClass(class {
|
|
3584
|
-
constructor(view) {
|
|
3585
|
-
this.decorations = buildDecorations6(view);
|
|
3586
|
-
}
|
|
3587
|
-
update(update2) {
|
|
3588
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
3589
|
-
this.decorations = buildDecorations6(update2.view);
|
|
3590
|
-
}
|
|
3591
|
-
}
|
|
3592
|
-
}, {
|
|
3593
|
-
decorations: (value) => value.decorations
|
|
3594
|
-
}),
|
|
3595
|
-
styles6
|
|
3596
|
-
];
|
|
3597
|
-
};
|
|
3598
|
-
|
|
3599
3431
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
3600
3432
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
3601
3433
|
var mention = ({ onSearch }) => {
|
|
@@ -3993,7 +3825,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
3993
3825
|
selection,
|
|
3994
3826
|
extensions: [
|
|
3995
3827
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
3996
|
-
|
|
3828
|
+
EditorView14.exceptionSink.of((err) => {
|
|
3997
3829
|
log3.catch(err, void 0, {
|
|
3998
3830
|
F: __dxlog_file4,
|
|
3999
3831
|
L: 113,
|
|
@@ -4003,17 +3835,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4003
3835
|
}),
|
|
4004
3836
|
// Theme.
|
|
4005
3837
|
// TODO(burdon): Make configurable.
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
3838
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3839
|
+
EditorView14.theme(theme ?? {}),
|
|
3840
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3841
|
+
EditorView14.editorAttributes.of({
|
|
4010
3842
|
class: slots.editor?.className ?? ""
|
|
4011
3843
|
}),
|
|
4012
|
-
|
|
3844
|
+
EditorView14.contentAttributes.of({
|
|
4013
3845
|
class: slots.content?.className ?? ""
|
|
4014
3846
|
}),
|
|
4015
3847
|
// Focus.
|
|
4016
|
-
|
|
3848
|
+
EditorView14.updateListener.of((update2) => {
|
|
4017
3849
|
update2.transactions.forEach((transaction) => {
|
|
4018
3850
|
if (transaction.isUserEvent("focus.container")) {
|
|
4019
3851
|
rootRef.current?.focus();
|
|
@@ -4021,7 +3853,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4021
3853
|
});
|
|
4022
3854
|
}),
|
|
4023
3855
|
// State.
|
|
4024
|
-
|
|
3856
|
+
EditorView14.editable.of(!readonly),
|
|
4025
3857
|
EditorState2.readOnly.of(!!readonly),
|
|
4026
3858
|
// Storage and replication.
|
|
4027
3859
|
// NOTE: This must come before user extensions.
|
|
@@ -4030,7 +3862,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4030
3862
|
...extensions
|
|
4031
3863
|
].filter(isNotFalsy4)
|
|
4032
3864
|
});
|
|
4033
|
-
const newView = new
|
|
3865
|
+
const newView = new EditorView14({
|
|
4034
3866
|
state,
|
|
4035
3867
|
parent: rootRef.current,
|
|
4036
3868
|
scrollTo,
|
|
@@ -4352,8 +4184,7 @@ var markdownBlocks = [
|
|
|
4352
4184
|
{
|
|
4353
4185
|
type: "codeblock",
|
|
4354
4186
|
Icon: CodeBlock,
|
|
4355
|
-
getState: (state) => state.blockType === "codeblock"
|
|
4356
|
-
disabled: (state) => !state.blankLine
|
|
4187
|
+
getState: (state) => state.blockType === "codeblock"
|
|
4357
4188
|
},
|
|
4358
4189
|
{
|
|
4359
4190
|
type: "table",
|
|
@@ -4586,7 +4417,7 @@ var useEditorView = (id) => {
|
|
|
4586
4417
|
|
|
4587
4418
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4588
4419
|
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4589
|
-
import { EditorView as
|
|
4420
|
+
import { EditorView as EditorView15 } from "@codemirror/view";
|
|
4590
4421
|
import { useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
|
|
4591
4422
|
import { log as log5 } from "@dxos/log";
|
|
4592
4423
|
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
@@ -4603,7 +4434,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
4603
4434
|
selection,
|
|
4604
4435
|
extensions: [
|
|
4605
4436
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4606
|
-
|
|
4437
|
+
EditorView15.exceptionSink.of((err) => {
|
|
4607
4438
|
log5.catch(err, void 0, {
|
|
4608
4439
|
F: __dxlog_file6,
|
|
4609
4440
|
L: 60,
|
|
@@ -4612,12 +4443,12 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
|
|
|
4612
4443
|
});
|
|
4613
4444
|
}),
|
|
4614
4445
|
extensions,
|
|
4615
|
-
|
|
4446
|
+
EditorView15.updateListener.of(() => {
|
|
4616
4447
|
onUpdate.current?.();
|
|
4617
4448
|
})
|
|
4618
4449
|
].filter(isNotFalsy5)
|
|
4619
4450
|
});
|
|
4620
|
-
view2 = new
|
|
4451
|
+
view2 = new EditorView15({
|
|
4621
4452
|
parent: parentRef.current,
|
|
4622
4453
|
scrollTo,
|
|
4623
4454
|
state,
|
|
@@ -4675,19 +4506,19 @@ var createDataExtensions = ({ readonly = false } = {}) => {
|
|
|
4675
4506
|
return [
|
|
4676
4507
|
//
|
|
4677
4508
|
EditorState3.readOnly.of(readonly),
|
|
4678
|
-
|
|
4509
|
+
EditorView15.editable.of(!readonly)
|
|
4679
4510
|
];
|
|
4680
4511
|
};
|
|
4681
4512
|
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
4682
4513
|
return [
|
|
4683
4514
|
//
|
|
4684
|
-
|
|
4685
|
-
theme &&
|
|
4686
|
-
|
|
4687
|
-
|
|
4515
|
+
EditorView15.baseTheme(defaultTheme),
|
|
4516
|
+
theme && EditorView15.theme(theme),
|
|
4517
|
+
EditorView15.darkTheme.of(themeMode === "dark"),
|
|
4518
|
+
EditorView15.editorAttributes.of({
|
|
4688
4519
|
class: slots?.editor?.className ?? ""
|
|
4689
4520
|
}),
|
|
4690
|
-
|
|
4521
|
+
EditorView15.contentAttributes.of({
|
|
4691
4522
|
class: slots?.content?.className ?? ""
|
|
4692
4523
|
})
|
|
4693
4524
|
].filter(isNotFalsy5);
|
|
@@ -4787,7 +4618,6 @@ export {
|
|
|
4787
4618
|
awarenessProvider,
|
|
4788
4619
|
blast,
|
|
4789
4620
|
callbackWrapper,
|
|
4790
|
-
code2 as code,
|
|
4791
4621
|
codeTheme,
|
|
4792
4622
|
comments,
|
|
4793
4623
|
compareFormatting,
|
|
@@ -4798,6 +4628,7 @@ export {
|
|
|
4798
4628
|
createThemeExtensions,
|
|
4799
4629
|
cursorLineMargin,
|
|
4800
4630
|
cursorLineMarginFacet,
|
|
4631
|
+
decorateMarkdown,
|
|
4801
4632
|
defaultMarkdownSlots,
|
|
4802
4633
|
defaultOptions,
|
|
4803
4634
|
defaultSlots,
|
|
@@ -4812,12 +4643,10 @@ export {
|
|
|
4812
4643
|
formatting,
|
|
4813
4644
|
getFormatting,
|
|
4814
4645
|
getToken,
|
|
4815
|
-
heading2 as heading,
|
|
4816
|
-
hr,
|
|
4817
4646
|
image,
|
|
4818
4647
|
insertTable,
|
|
4819
4648
|
keymap8 as keymap,
|
|
4820
|
-
|
|
4649
|
+
linkTooltip,
|
|
4821
4650
|
listener,
|
|
4822
4651
|
logChanges,
|
|
4823
4652
|
markdownHighlightStyle,
|
|
@@ -4839,7 +4668,6 @@ export {
|
|
|
4839
4668
|
setStyle,
|
|
4840
4669
|
table,
|
|
4841
4670
|
tags2 as tags,
|
|
4842
|
-
tasklist,
|
|
4843
4671
|
textTheme,
|
|
4844
4672
|
toggleBlockquote,
|
|
4845
4673
|
toggleCodeblock,
|