@dxos/react-ui-editor 0.6.8-main.046e6cf → 0.6.8-staging.77f93a3
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 +290 -293
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/TextEditor.stories.d.ts +5 -2
- package/dist/types/src/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/defaults.d.ts +1 -1
- package/dist/types/src/defaults.d.ts.map +1 -1
- package/dist/types/src/extensions/doc.d.ts +3 -0
- package/dist/types/src/extensions/doc.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/folding.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts +2 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link-paste.d.ts +3 -0
- package/dist/types/src/extensions/markdown/link-paste.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts +3 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/extensions/state.d.ts +14 -14
- package/dist/types/src/extensions/state.d.ts.map +1 -1
- package/dist/types/src/extensions/util/react.d.ts +1 -1
- package/dist/types/src/extensions/util/react.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts +5 -3
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +7 -17
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts +2 -1
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/styles/tokens.d.ts +5 -7
- package/dist/types/src/styles/tokens.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/TextEditor.stories.tsx +40 -27
- package/src/defaults.ts +2 -1
- package/src/extensions/doc.ts +3 -0
- package/src/extensions/factories.ts +3 -2
- package/src/extensions/folding.tsx +5 -7
- package/src/extensions/markdown/bundle.ts +1 -3
- package/src/extensions/markdown/decorate.ts +29 -23
- package/src/extensions/markdown/formatting.ts +3 -1
- package/src/extensions/markdown/highlight.ts +33 -19
- package/src/extensions/markdown/link-paste.ts +3 -0
- package/src/extensions/state.ts +41 -35
- package/src/extensions/util/react.tsx +3 -4
- package/src/hooks/useTextEditor.ts +24 -29
- package/src/styles/markdown.ts +17 -40
- package/src/styles/theme.ts +42 -49
- package/src/styles/tokens.ts +9 -7
|
@@ -1387,45 +1387,42 @@ import React from "react";
|
|
|
1387
1387
|
import { createRoot } from "react-dom/client";
|
|
1388
1388
|
import { ThemeProvider } from "@dxos/react-ui";
|
|
1389
1389
|
import { defaultTx } from "@dxos/react-ui-theme";
|
|
1390
|
-
var renderRoot = (node) => {
|
|
1391
|
-
|
|
1392
|
-
createRoot(el).render(/* @__PURE__ */ React.createElement(ThemeProvider, {
|
|
1390
|
+
var renderRoot = (root, node) => {
|
|
1391
|
+
createRoot(root).render(/* @__PURE__ */ React.createElement(ThemeProvider, {
|
|
1393
1392
|
tx: defaultTx
|
|
1394
1393
|
}, node));
|
|
1395
|
-
return
|
|
1394
|
+
return root;
|
|
1396
1395
|
};
|
|
1397
1396
|
|
|
1398
1397
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
1399
1398
|
import { mx } from "@dxos/react-ui-theme";
|
|
1400
1399
|
var headings = {
|
|
1401
|
-
1: "
|
|
1402
|
-
2: "
|
|
1403
|
-
3: "
|
|
1404
|
-
4: "
|
|
1405
|
-
5: "
|
|
1406
|
-
6: "
|
|
1407
|
-
};
|
|
1408
|
-
var
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
var inlineUrl = mx(code, "px-1");
|
|
1419
|
-
var blockquote = mx("pl-1 mr-1 border-is-4 border-orange-500 dark:border-orange-500 text-transparent");
|
|
1420
|
-
|
|
1421
|
-
// packages/ui/react-ui-editor/src/styles/theme.ts
|
|
1422
|
-
import get2 from "lodash.get";
|
|
1400
|
+
1: "text-4xl",
|
|
1401
|
+
2: "text-3xl",
|
|
1402
|
+
3: "text-2xl",
|
|
1403
|
+
4: "text-xl",
|
|
1404
|
+
5: "text-lg",
|
|
1405
|
+
6: "text-md"
|
|
1406
|
+
};
|
|
1407
|
+
var theme = {
|
|
1408
|
+
mark: "opacity-50",
|
|
1409
|
+
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
|
1410
|
+
codeMark: "font-mono text-primary-500",
|
|
1411
|
+
// TODO(burdon): Replace with widget.
|
|
1412
|
+
blockquote: "pl-1 mr-1 border-is-4 border-orange-500 dark:border-orange-500 dark:text-neutral-500",
|
|
1413
|
+
heading: (level) => {
|
|
1414
|
+
return mx(headings[level], "dark:text-primary-400");
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1423
1417
|
|
|
1424
1418
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1425
1419
|
import get from "lodash.get";
|
|
1426
1420
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1427
1421
|
var tokens = tailwindConfig({}).theme;
|
|
1428
|
-
var getToken = (path, defaultValue
|
|
1422
|
+
var getToken = (path, defaultValue) => {
|
|
1423
|
+
const value = get(tokens, path, defaultValue);
|
|
1424
|
+
return value?.toString() ?? "";
|
|
1425
|
+
};
|
|
1429
1426
|
|
|
1430
1427
|
// packages/ui/react-ui-editor/src/styles/theme.ts
|
|
1431
1428
|
var defaultTheme = {
|
|
@@ -1436,21 +1433,21 @@ var defaultTheme = {
|
|
|
1436
1433
|
// Scroller.
|
|
1437
1434
|
// NOTE: See https://codemirror.net/docs/guide (DOM Structure).
|
|
1438
1435
|
".cm-scroller": {
|
|
1439
|
-
overflowY: "auto"
|
|
1440
|
-
fontFamily: get2(tokens, "fontFamily.body", []).join(","),
|
|
1441
|
-
lineHeight: 1.5
|
|
1436
|
+
overflowY: "auto"
|
|
1442
1437
|
},
|
|
1443
1438
|
// Content.
|
|
1444
1439
|
".cm-content": {
|
|
1445
1440
|
padding: "unset",
|
|
1446
1441
|
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
1447
|
-
fontSize: "16px"
|
|
1442
|
+
fontSize: "16px",
|
|
1443
|
+
fontFamily: getToken("fontFamily.body"),
|
|
1444
|
+
lineHeight: 1.5
|
|
1448
1445
|
},
|
|
1449
1446
|
"&light .cm-content": {
|
|
1450
|
-
color:
|
|
1447
|
+
color: getToken("extend.semanticColors.base.fg.light", "black")
|
|
1451
1448
|
},
|
|
1452
1449
|
"&dark .cm-content": {
|
|
1453
|
-
color:
|
|
1450
|
+
color: getToken("extend.semanticColors.base.fg.dark", "white")
|
|
1454
1451
|
},
|
|
1455
1452
|
//
|
|
1456
1453
|
// Cursor
|
|
@@ -1462,10 +1459,10 @@ var defaultTheme = {
|
|
|
1462
1459
|
borderLeft: "2px solid white"
|
|
1463
1460
|
},
|
|
1464
1461
|
"&light .cm-placeholder": {
|
|
1465
|
-
color:
|
|
1462
|
+
color: getToken("extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
1466
1463
|
},
|
|
1467
1464
|
"&dark .cm-placeholder": {
|
|
1468
|
-
color:
|
|
1465
|
+
color: getToken("extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
1469
1466
|
},
|
|
1470
1467
|
//
|
|
1471
1468
|
// line
|
|
@@ -1486,46 +1483,51 @@ var defaultTheme = {
|
|
|
1486
1483
|
// Selection
|
|
1487
1484
|
//
|
|
1488
1485
|
"&light .cm-selectionBackground": {
|
|
1489
|
-
background:
|
|
1486
|
+
background: getToken("extend.colors.primary.100")
|
|
1490
1487
|
},
|
|
1491
1488
|
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
1492
|
-
background:
|
|
1489
|
+
background: getToken("extend.colors.primary.200")
|
|
1493
1490
|
},
|
|
1494
1491
|
"&dark .cm-selectionBackground": {
|
|
1495
|
-
background:
|
|
1492
|
+
background: getToken("extend.colors.primary.700")
|
|
1496
1493
|
},
|
|
1497
1494
|
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
1498
|
-
background:
|
|
1495
|
+
background: getToken("extend.colors.primary.600")
|
|
1499
1496
|
},
|
|
1500
1497
|
//
|
|
1501
1498
|
// Search
|
|
1502
1499
|
//
|
|
1503
1500
|
"&light .cm-searchMatch": {
|
|
1504
|
-
backgroundColor:
|
|
1501
|
+
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1505
1502
|
},
|
|
1506
1503
|
"&dark .cm-searchMatch": {
|
|
1507
|
-
backgroundColor:
|
|
1504
|
+
backgroundColor: getToken("extend.colors.yellow.700")
|
|
1508
1505
|
},
|
|
1509
1506
|
//
|
|
1510
1507
|
// link
|
|
1511
1508
|
//
|
|
1512
1509
|
".cm-link": {
|
|
1513
|
-
color: get2(tokens, "extend.colors.primary.500"),
|
|
1514
1510
|
textDecorationLine: "underline",
|
|
1515
1511
|
textDecorationThickness: "1px",
|
|
1516
1512
|
textUnderlineOffset: "2px",
|
|
1517
1513
|
borderRadius: ".125rem",
|
|
1518
|
-
fontFamily:
|
|
1514
|
+
fontFamily: getToken("fontFamily.body")
|
|
1515
|
+
},
|
|
1516
|
+
"&light .cm-link > span": {
|
|
1517
|
+
color: getToken("extend.colors.primary.600")
|
|
1518
|
+
},
|
|
1519
|
+
"&dark .cm-link > span": {
|
|
1520
|
+
color: getToken("extend.colors.primary.400")
|
|
1519
1521
|
},
|
|
1520
1522
|
//
|
|
1521
1523
|
// tooltip
|
|
1522
1524
|
//
|
|
1523
1525
|
".cm-tooltip": {},
|
|
1524
1526
|
"&light .cm-tooltip": {
|
|
1525
|
-
background: `${
|
|
1527
|
+
background: `${getToken("extend.colors.neutral.100")} !important`
|
|
1526
1528
|
},
|
|
1527
1529
|
"&dark .cm-tooltip": {
|
|
1528
|
-
background: `${
|
|
1530
|
+
background: `${getToken("extend.colors.neutral.900")} !important`
|
|
1529
1531
|
},
|
|
1530
1532
|
".cm-tooltip-below": {},
|
|
1531
1533
|
//
|
|
@@ -1541,14 +1543,13 @@ var defaultTheme = {
|
|
|
1541
1543
|
},
|
|
1542
1544
|
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
|
1543
1545
|
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
|
1544
|
-
// TODO(burdon): Can we add a class prefix to avoid adding !important?
|
|
1545
1546
|
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
|
1546
1547
|
paddingLeft: "4px !important",
|
|
1547
1548
|
borderBottom: "none !important",
|
|
1548
|
-
color:
|
|
1549
|
+
color: getToken("extend.colors.primary.500")
|
|
1549
1550
|
},
|
|
1550
1551
|
".cm-tooltip.cm-completionInfo": {
|
|
1551
|
-
border:
|
|
1552
|
+
border: getToken("extend.colors.neutral.500"),
|
|
1552
1553
|
width: "360px !important",
|
|
1553
1554
|
margin: "-10px 1px 0 1px",
|
|
1554
1555
|
padding: "8px !important"
|
|
@@ -1557,7 +1558,7 @@ var defaultTheme = {
|
|
|
1557
1558
|
display: "none"
|
|
1558
1559
|
},
|
|
1559
1560
|
".cm-completionLabel": {
|
|
1560
|
-
fontFamily:
|
|
1561
|
+
fontFamily: getToken("fontFamily.body")
|
|
1561
1562
|
},
|
|
1562
1563
|
".cm-completionMatchedText": {
|
|
1563
1564
|
textDecoration: "none !important",
|
|
@@ -1567,14 +1568,14 @@ var defaultTheme = {
|
|
|
1567
1568
|
// table
|
|
1568
1569
|
//
|
|
1569
1570
|
".cm-table *": {
|
|
1570
|
-
fontFamily: `${
|
|
1571
|
+
fontFamily: `${getToken("fontFamily.mono")} !important`,
|
|
1571
1572
|
textDecoration: "none !important"
|
|
1572
1573
|
},
|
|
1573
1574
|
".cm-table-head": {
|
|
1574
1575
|
padding: "2px 16px 2px 0px",
|
|
1575
1576
|
textAlign: "left",
|
|
1576
|
-
borderBottom: `1px solid ${
|
|
1577
|
-
color:
|
|
1577
|
+
borderBottom: `1px solid ${getToken("extend.colors.primary.500")}`,
|
|
1578
|
+
color: getToken("extend.colors.neutral.500")
|
|
1578
1579
|
},
|
|
1579
1580
|
".cm-table-cell": {
|
|
1580
1581
|
padding: "2px 16px 2px 0px"
|
|
@@ -1591,19 +1592,6 @@ var defaultTheme = {
|
|
|
1591
1592
|
borderTop: "0.5rem solid transparent",
|
|
1592
1593
|
borderBottom: "0.5rem solid transparent"
|
|
1593
1594
|
},
|
|
1594
|
-
//
|
|
1595
|
-
// font size
|
|
1596
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
1597
|
-
// but it's far more verbose than it needs to be.
|
|
1598
|
-
//
|
|
1599
|
-
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
1600
|
-
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
1601
|
-
//
|
|
1602
|
-
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
1603
|
-
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
1604
|
-
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
1605
|
-
// return acc;
|
|
1606
|
-
// }, {}),
|
|
1607
1595
|
// TODO(burdon): Override vars --cm-background.
|
|
1608
1596
|
// https://www.npmjs.com/package/codemirror-theme-vars
|
|
1609
1597
|
/**
|
|
@@ -1630,20 +1618,20 @@ var defaultTheme = {
|
|
|
1630
1618
|
*/
|
|
1631
1619
|
".cm-panels": {},
|
|
1632
1620
|
".cm-panel": {
|
|
1633
|
-
fontFamily:
|
|
1621
|
+
fontFamily: getToken("fontFamily.body")
|
|
1634
1622
|
},
|
|
1635
1623
|
".cm-panel input[type=checkbox]": {
|
|
1636
1624
|
marginRight: "0.4rem !important"
|
|
1637
1625
|
},
|
|
1638
1626
|
"&light .cm-panel": {
|
|
1639
|
-
background:
|
|
1627
|
+
background: getToken("extend.colors.neutral.50")
|
|
1640
1628
|
},
|
|
1641
1629
|
"&dark .cm-panel": {
|
|
1642
|
-
background:
|
|
1630
|
+
background: getToken("extend.colors.neutral.850")
|
|
1643
1631
|
},
|
|
1644
1632
|
".cm-button": {
|
|
1645
1633
|
margin: "4px",
|
|
1646
|
-
fontFamily:
|
|
1634
|
+
fontFamily: getToken("fontFamily.body"),
|
|
1647
1635
|
backgroundImage: "none",
|
|
1648
1636
|
border: "none",
|
|
1649
1637
|
"&:active": {
|
|
@@ -1651,21 +1639,21 @@ var defaultTheme = {
|
|
|
1651
1639
|
}
|
|
1652
1640
|
},
|
|
1653
1641
|
"&light .cm-button": {
|
|
1654
|
-
background:
|
|
1642
|
+
background: getToken("extend.colors.neutral.100"),
|
|
1655
1643
|
"&:hover": {
|
|
1656
|
-
background:
|
|
1644
|
+
background: getToken("extend.colors.neutral.200")
|
|
1657
1645
|
},
|
|
1658
1646
|
"&:active": {
|
|
1659
|
-
background:
|
|
1647
|
+
background: getToken("extend.colors.neutral.300")
|
|
1660
1648
|
}
|
|
1661
1649
|
},
|
|
1662
1650
|
"&dark .cm-button": {
|
|
1663
|
-
background:
|
|
1651
|
+
background: getToken("extend.colors.neutral.800"),
|
|
1664
1652
|
"&:hover": {
|
|
1665
|
-
background:
|
|
1653
|
+
background: getToken("extend.colors.neutral.700")
|
|
1666
1654
|
},
|
|
1667
1655
|
"&:active": {
|
|
1668
|
-
background:
|
|
1656
|
+
background: getToken("extend.colors.neutral.600")
|
|
1669
1657
|
}
|
|
1670
1658
|
}
|
|
1671
1659
|
};
|
|
@@ -1828,8 +1816,8 @@ var commentsDecorations = EditorView7.decorations.compute([
|
|
|
1828
1816
|
} else if (range.from === range.to) {
|
|
1829
1817
|
return void 0;
|
|
1830
1818
|
}
|
|
1831
|
-
const
|
|
1832
|
-
return
|
|
1819
|
+
const mark = createCommentMark(comment.comment.id, comment.comment.id === current);
|
|
1820
|
+
return mark.range(range.from, range.to);
|
|
1833
1821
|
}).filter(nonNullable);
|
|
1834
1822
|
return Decoration4.set(decorations);
|
|
1835
1823
|
});
|
|
@@ -2248,7 +2236,7 @@ var documentId2 = Facet5.define({
|
|
|
2248
2236
|
combine: (providers) => {
|
|
2249
2237
|
invariant3(providers.length <= 1, void 0, {
|
|
2250
2238
|
F: __dxlog_file8,
|
|
2251
|
-
L:
|
|
2239
|
+
L: 14,
|
|
2252
2240
|
S: void 0,
|
|
2253
2241
|
A: [
|
|
2254
2242
|
"providers.length <= 1",
|
|
@@ -2297,7 +2285,7 @@ var dropFile = (options = {}) => {
|
|
|
2297
2285
|
|
|
2298
2286
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
|
2299
2287
|
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
2300
|
-
import { defaultKeymap, history, historyKeymap,
|
|
2288
|
+
import { defaultKeymap, history, historyKeymap, standardKeymap } from "@codemirror/commands";
|
|
2301
2289
|
import { bracketMatching } from "@codemirror/language";
|
|
2302
2290
|
import { searchKeymap } from "@codemirror/search";
|
|
2303
2291
|
import { EditorState } from "@codemirror/state";
|
|
@@ -2357,10 +2345,9 @@ var createBasicExtensions = (_props) => {
|
|
|
2357
2345
|
// https://codemirror.net/docs/ref/#view.KeyBinding
|
|
2358
2346
|
keymap5.of([
|
|
2359
2347
|
...(props.keymap && keymaps[props.keymap]) ?? [],
|
|
2348
|
+
// NOTE: Tab configured by markdown extension.
|
|
2360
2349
|
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2361
|
-
...props.indentWithTab ? [
|
|
2362
|
-
indentWithTab
|
|
2363
|
-
] : [],
|
|
2350
|
+
// ...(props.indentWithTab ? [indentWithTab] : []),
|
|
2364
2351
|
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2365
2352
|
...props.closeBrackets ? closeBracketsKeymap : [],
|
|
2366
2353
|
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
@@ -2375,12 +2362,12 @@ var defaultThemeSlots = {
|
|
|
2375
2362
|
className: "w-full bs-full"
|
|
2376
2363
|
}
|
|
2377
2364
|
};
|
|
2378
|
-
var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
|
|
2365
|
+
var createThemeExtensions = ({ theme: theme2, themeMode, slots: _slots } = {}) => {
|
|
2379
2366
|
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
|
2380
2367
|
return [
|
|
2381
2368
|
EditorView9.baseTheme(defaultTheme),
|
|
2382
2369
|
EditorView9.darkTheme.of(themeMode === "dark"),
|
|
2383
|
-
|
|
2370
|
+
theme2 && EditorView9.theme(theme2),
|
|
2384
2371
|
slots.editor?.className && EditorView9.editorAttributes.of({
|
|
2385
2372
|
class: slots.editor.className
|
|
2386
2373
|
}),
|
|
@@ -2414,21 +2401,18 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
|
2414
2401
|
// packages/ui/react-ui-editor/src/extensions/folding.tsx
|
|
2415
2402
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
|
2416
2403
|
import React2 from "react";
|
|
2417
|
-
import {
|
|
2418
|
-
import { defaultTx as defaultTx2, getSize, mx as mx2 } from "@dxos/react-ui-theme";
|
|
2404
|
+
import { getSize, mx as mx2 } from "@dxos/react-ui-theme";
|
|
2419
2405
|
var folding = (_props = {}) => [
|
|
2420
2406
|
codeFolding({
|
|
2421
2407
|
placeholderDOM: () => document.createElement("div")
|
|
2422
2408
|
}),
|
|
2423
2409
|
foldGutter({
|
|
2424
2410
|
markerDOM: (open) => {
|
|
2425
|
-
return renderRoot(/* @__PURE__ */ React2.createElement(
|
|
2426
|
-
tx: defaultTx2
|
|
2427
|
-
}, /* @__PURE__ */ React2.createElement("svg", {
|
|
2411
|
+
return renderRoot(document.createElement("div"), /* @__PURE__ */ React2.createElement("svg", {
|
|
2428
2412
|
className: mx2(getSize(3), "m-3 cursor-pointer", open && "rotate-90")
|
|
2429
2413
|
}, /* @__PURE__ */ React2.createElement("use", {
|
|
2430
2414
|
href: "/icons.svg#ph--caret-right--regular"
|
|
2431
|
-
})))
|
|
2415
|
+
})));
|
|
2432
2416
|
}
|
|
2433
2417
|
})
|
|
2434
2418
|
];
|
|
@@ -2449,6 +2433,7 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
2449
2433
|
|
|
2450
2434
|
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
2451
2435
|
import { snippet } from "@codemirror/autocomplete";
|
|
2436
|
+
import { indentWithTab } from "@codemirror/commands";
|
|
2452
2437
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
2453
2438
|
import { EditorSelection } from "@codemirror/state";
|
|
2454
2439
|
import { EditorView as EditorView11, keymap as keymap6 } from "@codemirror/view";
|
|
@@ -2870,28 +2855,28 @@ var addLink = ({ url, image: image2 } = {}) => {
|
|
|
2870
2855
|
let cursorOffset = 1;
|
|
2871
2856
|
for (const style of cutStyles) {
|
|
2872
2857
|
const type = InlineMarker[style.name];
|
|
2873
|
-
const
|
|
2858
|
+
const mark = inlineMarkerText(type);
|
|
2874
2859
|
if (style.from < from) {
|
|
2875
2860
|
changes2.push({
|
|
2876
2861
|
from: skipSpaces(from, state2.doc, -1),
|
|
2877
|
-
insert:
|
|
2862
|
+
insert: mark
|
|
2878
2863
|
});
|
|
2879
2864
|
changesAfter.push({
|
|
2880
2865
|
from: skipSpaces(from, state2.doc, 1, to),
|
|
2881
|
-
insert:
|
|
2866
|
+
insert: mark
|
|
2882
2867
|
});
|
|
2883
2868
|
} else {
|
|
2884
2869
|
changes2.push({
|
|
2885
2870
|
from: skipSpaces(to, state2.doc, -1, from),
|
|
2886
|
-
insert:
|
|
2871
|
+
insert: mark
|
|
2887
2872
|
});
|
|
2888
2873
|
const after = skipSpaces(to, state2.doc, 1);
|
|
2889
2874
|
if (after === to) {
|
|
2890
|
-
cursorOffset +=
|
|
2875
|
+
cursorOffset += mark.length;
|
|
2891
2876
|
}
|
|
2892
2877
|
changesAfter.push({
|
|
2893
2878
|
from: after,
|
|
2894
|
-
insert:
|
|
2879
|
+
insert: mark
|
|
2895
2880
|
});
|
|
2896
2881
|
}
|
|
2897
2882
|
}
|
|
@@ -2942,10 +2927,10 @@ var addList = (type) => {
|
|
|
2942
2927
|
const itemText = itemLine.text.slice(item.from - itemLine.from);
|
|
2943
2928
|
parentColumn = item.from - itemLine.from + /^\s*/.exec(itemText)[0].length;
|
|
2944
2929
|
if (type === 0) {
|
|
2945
|
-
const
|
|
2946
|
-
if (
|
|
2947
|
-
parentColumn +=
|
|
2948
|
-
counter = +
|
|
2930
|
+
const mark = /^\s*(\d+)[.)]/.exec(itemText);
|
|
2931
|
+
if (mark) {
|
|
2932
|
+
parentColumn += mark[1].length;
|
|
2933
|
+
counter = +mark[1] + 1;
|
|
2949
2934
|
}
|
|
2950
2935
|
}
|
|
2951
2936
|
}
|
|
@@ -3006,7 +2991,7 @@ var addList = (type) => {
|
|
|
3006
2991
|
if (parentColumn2 !== null && parentColumn2 > column) {
|
|
3007
2992
|
padding = Math.max(padding, parentColumn2 - column);
|
|
3008
2993
|
}
|
|
3009
|
-
let
|
|
2994
|
+
let mark;
|
|
3010
2995
|
if (type === 0) {
|
|
3011
2996
|
let max = counter2;
|
|
3012
2997
|
for (let j = i + 1; j < blocks.length; j++) {
|
|
@@ -3017,20 +3002,20 @@ var addList = (type) => {
|
|
|
3017
3002
|
}
|
|
3018
3003
|
const num = String(counter2);
|
|
3019
3004
|
padding = Math.max(String(max).length, padding);
|
|
3020
|
-
|
|
3005
|
+
mark = " ".repeat(Math.max(0, padding - num.length)) + num + ". ";
|
|
3021
3006
|
} else {
|
|
3022
|
-
|
|
3007
|
+
mark = " ".repeat(padding) + "- " + (type === 2 ? "[ ] " : "");
|
|
3023
3008
|
}
|
|
3024
3009
|
changes.push({
|
|
3025
3010
|
from: nodeFrom,
|
|
3026
|
-
insert:
|
|
3011
|
+
insert: mark
|
|
3027
3012
|
});
|
|
3028
3013
|
while (line.to < node.to) {
|
|
3029
3014
|
line = state2.doc.lineAt(line.to + 1);
|
|
3030
3015
|
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
3031
3016
|
changes.push({
|
|
3032
3017
|
from: line.from + Math.min(open, column),
|
|
3033
|
-
insert: " ".repeat(
|
|
3018
|
+
insert: " ".repeat(mark.length)
|
|
3034
3019
|
});
|
|
3035
3020
|
}
|
|
3036
3021
|
}
|
|
@@ -3079,14 +3064,14 @@ var removeList = (type) => {
|
|
|
3079
3064
|
} else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
|
|
3080
3065
|
lastBlock = node.from;
|
|
3081
3066
|
let line = state2.doc.lineAt(node.from);
|
|
3082
|
-
const
|
|
3083
|
-
if (!
|
|
3067
|
+
const mark = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
|
|
3068
|
+
if (!mark) {
|
|
3084
3069
|
return false;
|
|
3085
3070
|
}
|
|
3086
3071
|
const column = node.from - line.from;
|
|
3087
3072
|
changes.push({
|
|
3088
3073
|
from: node.from,
|
|
3089
|
-
to: node.from +
|
|
3074
|
+
to: node.from + mark[0].length
|
|
3090
3075
|
});
|
|
3091
3076
|
while (line.to < node.to) {
|
|
3092
3077
|
line = state2.doc.lineAt(line.to + 1);
|
|
@@ -3094,7 +3079,7 @@ var removeList = (type) => {
|
|
|
3094
3079
|
if (open > column) {
|
|
3095
3080
|
changes.push({
|
|
3096
3081
|
from: line.from + column,
|
|
3097
|
-
to: line.from + Math.min(column +
|
|
3082
|
+
to: line.from + Math.min(column + mark[0].length, open)
|
|
3098
3083
|
});
|
|
3099
3084
|
}
|
|
3100
3085
|
}
|
|
@@ -3337,7 +3322,7 @@ var removeCodeblock = ({ state: state2, dispatch }) => {
|
|
|
3337
3322
|
var toggleCodeblock = (target) => {
|
|
3338
3323
|
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
3339
3324
|
};
|
|
3340
|
-
var formattingKeymap = (
|
|
3325
|
+
var formattingKeymap = (_options = {}) => {
|
|
3341
3326
|
return [
|
|
3342
3327
|
keymap6.of([
|
|
3343
3328
|
{
|
|
@@ -3441,10 +3426,10 @@ var getFormatting = (state2) => {
|
|
|
3441
3426
|
}
|
|
3442
3427
|
}
|
|
3443
3428
|
for (let i = 0; i < inline.length; i++) {
|
|
3444
|
-
const
|
|
3445
|
-
const found = contextAfter.indexOf(
|
|
3429
|
+
const mark = inlineMarkerText(i);
|
|
3430
|
+
const found = contextAfter.indexOf(mark);
|
|
3446
3431
|
if (found > -1) {
|
|
3447
|
-
contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found +
|
|
3432
|
+
contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found + mark.length);
|
|
3448
3433
|
if (inline[i] === null) {
|
|
3449
3434
|
inline[i] = true;
|
|
3450
3435
|
}
|
|
@@ -3653,7 +3638,7 @@ var markdownTagsExtensions = [
|
|
|
3653
3638
|
]
|
|
3654
3639
|
}
|
|
3655
3640
|
];
|
|
3656
|
-
var markdownHighlightStyle = (
|
|
3641
|
+
var markdownHighlightStyle = (_options = {}) => {
|
|
3657
3642
|
return HighlightStyle.define([
|
|
3658
3643
|
{
|
|
3659
3644
|
tag: [
|
|
@@ -3691,6 +3676,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
3691
3676
|
tags.inserted,
|
|
3692
3677
|
tags.invalid
|
|
3693
3678
|
],
|
|
3679
|
+
// TODO(burdon): Explain.
|
|
3694
3680
|
color: "inherit !important"
|
|
3695
3681
|
},
|
|
3696
3682
|
// Markdown marks.
|
|
@@ -3702,26 +3688,29 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
3702
3688
|
markdownTags.LinkReference,
|
|
3703
3689
|
markdownTags.ListMark
|
|
3704
3690
|
],
|
|
3705
|
-
class: mark
|
|
3691
|
+
class: theme.mark
|
|
3706
3692
|
},
|
|
3707
3693
|
// Markdown marks.
|
|
3708
3694
|
{
|
|
3709
3695
|
tag: [
|
|
3696
|
+
//
|
|
3710
3697
|
markdownTags.CodeMark,
|
|
3711
3698
|
markdownTags.HeaderMark,
|
|
3712
3699
|
markdownTags.QuoteMark,
|
|
3713
3700
|
markdownTags.EmphasisMark
|
|
3714
3701
|
],
|
|
3715
|
-
class: mark
|
|
3702
|
+
class: theme.mark
|
|
3716
3703
|
},
|
|
3717
3704
|
// E.g., code block language (after ```).
|
|
3718
3705
|
{
|
|
3719
3706
|
tag: [
|
|
3707
|
+
//
|
|
3720
3708
|
tags.function(tags.variableName),
|
|
3721
3709
|
tags.labelName
|
|
3722
3710
|
],
|
|
3723
|
-
class: codeMark
|
|
3711
|
+
class: theme.codeMark
|
|
3724
3712
|
},
|
|
3713
|
+
// Fonts.
|
|
3725
3714
|
{
|
|
3726
3715
|
tag: [
|
|
3727
3716
|
tags.monospace
|
|
@@ -3731,40 +3720,40 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
3731
3720
|
// Headings.
|
|
3732
3721
|
{
|
|
3733
3722
|
tag: tags.heading1,
|
|
3734
|
-
class: heading(1)
|
|
3723
|
+
class: theme.heading(1)
|
|
3735
3724
|
},
|
|
3736
3725
|
{
|
|
3737
3726
|
tag: tags.heading2,
|
|
3738
|
-
class: heading(2)
|
|
3727
|
+
class: theme.heading(2)
|
|
3739
3728
|
},
|
|
3740
3729
|
{
|
|
3741
3730
|
tag: tags.heading3,
|
|
3742
|
-
class: heading(3)
|
|
3731
|
+
class: theme.heading(3)
|
|
3743
3732
|
},
|
|
3744
3733
|
{
|
|
3745
3734
|
tag: tags.heading4,
|
|
3746
|
-
class: heading(4)
|
|
3735
|
+
class: theme.heading(4)
|
|
3747
3736
|
},
|
|
3748
3737
|
{
|
|
3749
3738
|
tag: tags.heading5,
|
|
3750
|
-
class: heading(5)
|
|
3739
|
+
class: theme.heading(5)
|
|
3751
3740
|
},
|
|
3752
3741
|
{
|
|
3753
3742
|
tag: tags.heading6,
|
|
3754
|
-
class: heading(6)
|
|
3743
|
+
class: theme.heading(6)
|
|
3755
3744
|
},
|
|
3756
3745
|
// Emphasis.
|
|
3757
3746
|
{
|
|
3758
3747
|
tag: tags.emphasis,
|
|
3759
|
-
class: italic
|
|
3748
|
+
class: "italic"
|
|
3760
3749
|
},
|
|
3761
3750
|
{
|
|
3762
3751
|
tag: tags.strong,
|
|
3763
|
-
class: bold
|
|
3752
|
+
class: "font-bold"
|
|
3764
3753
|
},
|
|
3765
3754
|
{
|
|
3766
3755
|
tag: tags.strikethrough,
|
|
3767
|
-
class:
|
|
3756
|
+
class: "line-through"
|
|
3768
3757
|
},
|
|
3769
3758
|
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
3770
3759
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
@@ -3776,13 +3765,13 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
3776
3765
|
markdownTags.CodeText,
|
|
3777
3766
|
markdownTags.InlineCode
|
|
3778
3767
|
],
|
|
3779
|
-
class: code
|
|
3768
|
+
class: theme.code
|
|
3780
3769
|
},
|
|
3781
3770
|
{
|
|
3782
3771
|
tag: [
|
|
3783
3772
|
markdownTags.QuoteMark
|
|
3784
3773
|
],
|
|
3785
|
-
class: blockquote
|
|
3774
|
+
class: theme.blockquote
|
|
3786
3775
|
},
|
|
3787
3776
|
{
|
|
3788
3777
|
tag: [
|
|
@@ -3793,108 +3782,11 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
3793
3782
|
], {
|
|
3794
3783
|
scope: markdownLanguage2,
|
|
3795
3784
|
all: {
|
|
3796
|
-
fontFamily: getToken("fontFamily.body"
|
|
3785
|
+
fontFamily: getToken("fontFamily.body")
|
|
3797
3786
|
}
|
|
3798
3787
|
});
|
|
3799
3788
|
};
|
|
3800
3789
|
|
|
3801
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/link-paste.ts
|
|
3802
|
-
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3803
|
-
import { Transaction } from "@codemirror/state";
|
|
3804
|
-
import { ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
3805
|
-
var linkPastePlugin = ViewPlugin5.fromClass(class {
|
|
3806
|
-
update(update2) {
|
|
3807
|
-
for (const tr of update2.transactions) {
|
|
3808
|
-
const event = tr.annotation(Transaction.userEvent);
|
|
3809
|
-
if (event === "input.paste") {
|
|
3810
|
-
const changes = tr.changes;
|
|
3811
|
-
if (changes.empty) {
|
|
3812
|
-
return;
|
|
3813
|
-
}
|
|
3814
|
-
changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
3815
|
-
const insertedUrl = getValidUrl(update2.view.state.sliceDoc(fromB, toB));
|
|
3816
|
-
if (insertedUrl && isValidPosition(update2.view.state, fromB)) {
|
|
3817
|
-
const replacedText = tr.startState.sliceDoc(fromA, toA);
|
|
3818
|
-
setTimeout(() => {
|
|
3819
|
-
update2.view.dispatch(update2.view.state.update({
|
|
3820
|
-
changes: {
|
|
3821
|
-
from: fromA,
|
|
3822
|
-
to: toB,
|
|
3823
|
-
insert: createLink(insertedUrl, replacedText)
|
|
3824
|
-
}
|
|
3825
|
-
}));
|
|
3826
|
-
});
|
|
3827
|
-
}
|
|
3828
|
-
});
|
|
3829
|
-
}
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
|
-
});
|
|
3833
|
-
var createLink = (url, label) => {
|
|
3834
|
-
const { host, pathname } = url;
|
|
3835
|
-
const [, extension] = pathname.split(".");
|
|
3836
|
-
const imageExtensions = [
|
|
3837
|
-
"jpg",
|
|
3838
|
-
"jpeg",
|
|
3839
|
-
"png",
|
|
3840
|
-
"gif",
|
|
3841
|
-
"svg",
|
|
3842
|
-
"webp"
|
|
3843
|
-
];
|
|
3844
|
-
if (imageExtensions.includes(extension)) {
|
|
3845
|
-
return ``;
|
|
3846
|
-
}
|
|
3847
|
-
if (!label) {
|
|
3848
|
-
label = createLinkLabel(url);
|
|
3849
|
-
}
|
|
3850
|
-
return `[${label}](${url})`;
|
|
3851
|
-
};
|
|
3852
|
-
var createLinkLabel = (url) => {
|
|
3853
|
-
let { protocol, host, pathname } = url;
|
|
3854
|
-
if (protocol === "http:" || protocol === "https:") {
|
|
3855
|
-
protocol = "";
|
|
3856
|
-
}
|
|
3857
|
-
host = host.replace(/^www\./, "");
|
|
3858
|
-
return [
|
|
3859
|
-
protocol,
|
|
3860
|
-
host
|
|
3861
|
-
].filter(Boolean).join("//") + (pathname !== "/" ? pathname : "");
|
|
3862
|
-
};
|
|
3863
|
-
var getValidUrl = (str) => {
|
|
3864
|
-
const validProtocols = [
|
|
3865
|
-
"http:",
|
|
3866
|
-
"https:",
|
|
3867
|
-
"mailto:",
|
|
3868
|
-
"tel:"
|
|
3869
|
-
];
|
|
3870
|
-
try {
|
|
3871
|
-
const url = new URL(str);
|
|
3872
|
-
if (!validProtocols.includes(url.protocol)) {
|
|
3873
|
-
return void 0;
|
|
3874
|
-
}
|
|
3875
|
-
return url;
|
|
3876
|
-
} catch (_err) {
|
|
3877
|
-
return void 0;
|
|
3878
|
-
}
|
|
3879
|
-
};
|
|
3880
|
-
var isValidPosition = (state2, pos) => {
|
|
3881
|
-
const invalidPositions = /* @__PURE__ */ new Set([
|
|
3882
|
-
"Link",
|
|
3883
|
-
"LinkMark",
|
|
3884
|
-
"Code",
|
|
3885
|
-
"FencedCode"
|
|
3886
|
-
]);
|
|
3887
|
-
const tree = syntaxTree3(state2);
|
|
3888
|
-
let node = tree.resolveInner(pos, -1);
|
|
3889
|
-
while (node) {
|
|
3890
|
-
if (invalidPositions.has(node.name)) {
|
|
3891
|
-
return false;
|
|
3892
|
-
}
|
|
3893
|
-
node = node.parent;
|
|
3894
|
-
}
|
|
3895
|
-
return true;
|
|
3896
|
-
};
|
|
3897
|
-
|
|
3898
3790
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
3899
3791
|
var createMarkdownExtensions = ({ themeMode } = {}) => {
|
|
3900
3792
|
return [
|
|
@@ -3920,8 +3812,8 @@ var createMarkdownExtensions = ({ themeMode } = {}) => {
|
|
|
3920
3812
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
3921
3813
|
// Custom styles.
|
|
3922
3814
|
syntaxHighlighting(markdownHighlightStyle()),
|
|
3923
|
-
linkPastePlugin,
|
|
3924
3815
|
keymap7.of([
|
|
3816
|
+
// TODO(burdon): Indent by 4 if in task list.
|
|
3925
3817
|
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
3926
3818
|
indentWithTab2,
|
|
3927
3819
|
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
@@ -3940,7 +3832,7 @@ import { invariant as invariant4 } from "@dxos/invariant";
|
|
|
3940
3832
|
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
3941
3833
|
|
|
3942
3834
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3943
|
-
import { syntaxTree as
|
|
3835
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3944
3836
|
import { StateField as StateField6 } from "@codemirror/state";
|
|
3945
3837
|
import { Decoration as Decoration5, EditorView as EditorView12, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
3946
3838
|
var image = (_options = {}) => {
|
|
@@ -3983,7 +3875,7 @@ var preloadImage = (url) => {
|
|
|
3983
3875
|
var buildDecorations = (from, to, state2) => {
|
|
3984
3876
|
const decorations = [];
|
|
3985
3877
|
const cursor = state2.selection.main.head;
|
|
3986
|
-
|
|
3878
|
+
syntaxTree3(state2).iterate({
|
|
3987
3879
|
enter: (node) => {
|
|
3988
3880
|
if (node.name === "Image") {
|
|
3989
3881
|
const urlNode = node.node.getChild("URL");
|
|
@@ -4022,6 +3914,103 @@ var ImageWidget = class extends WidgetType3 {
|
|
|
4022
3914
|
var imageUpload = (options = {}) => {
|
|
4023
3915
|
};
|
|
4024
3916
|
|
|
3917
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link-paste.ts
|
|
3918
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
3919
|
+
import { Transaction } from "@codemirror/state";
|
|
3920
|
+
import { ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
3921
|
+
var linkPastePlugin = ViewPlugin5.fromClass(class {
|
|
3922
|
+
update(update2) {
|
|
3923
|
+
for (const tr of update2.transactions) {
|
|
3924
|
+
const event = tr.annotation(Transaction.userEvent);
|
|
3925
|
+
if (event === "input.paste") {
|
|
3926
|
+
const changes = tr.changes;
|
|
3927
|
+
if (changes.empty) {
|
|
3928
|
+
return;
|
|
3929
|
+
}
|
|
3930
|
+
changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
3931
|
+
const insertedUrl = getValidUrl(update2.view.state.sliceDoc(fromB, toB));
|
|
3932
|
+
if (insertedUrl && isValidPosition(update2.view.state, fromB)) {
|
|
3933
|
+
const replacedText = tr.startState.sliceDoc(fromA, toA);
|
|
3934
|
+
setTimeout(() => {
|
|
3935
|
+
update2.view.dispatch(update2.view.state.update({
|
|
3936
|
+
changes: {
|
|
3937
|
+
from: fromA,
|
|
3938
|
+
to: toB,
|
|
3939
|
+
insert: createLink(insertedUrl, replacedText)
|
|
3940
|
+
}
|
|
3941
|
+
}));
|
|
3942
|
+
});
|
|
3943
|
+
}
|
|
3944
|
+
});
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
});
|
|
3949
|
+
var createLink = (url, label) => {
|
|
3950
|
+
const { host, pathname } = url;
|
|
3951
|
+
const [, extension] = pathname.split(".");
|
|
3952
|
+
const imageExtensions = [
|
|
3953
|
+
"jpg",
|
|
3954
|
+
"jpeg",
|
|
3955
|
+
"png",
|
|
3956
|
+
"gif",
|
|
3957
|
+
"svg",
|
|
3958
|
+
"webp"
|
|
3959
|
+
];
|
|
3960
|
+
if (imageExtensions.includes(extension)) {
|
|
3961
|
+
return ``;
|
|
3962
|
+
}
|
|
3963
|
+
if (!label) {
|
|
3964
|
+
label = createLinkLabel(url);
|
|
3965
|
+
}
|
|
3966
|
+
return `[${label}](${url})`;
|
|
3967
|
+
};
|
|
3968
|
+
var createLinkLabel = (url) => {
|
|
3969
|
+
let { protocol, host, pathname } = url;
|
|
3970
|
+
if (protocol === "http:" || protocol === "https:") {
|
|
3971
|
+
protocol = "";
|
|
3972
|
+
}
|
|
3973
|
+
host = host.replace(/^www\./, "");
|
|
3974
|
+
return [
|
|
3975
|
+
protocol,
|
|
3976
|
+
host
|
|
3977
|
+
].filter(Boolean).join("//") + (pathname !== "/" ? pathname : "");
|
|
3978
|
+
};
|
|
3979
|
+
var getValidUrl = (str) => {
|
|
3980
|
+
const validProtocols = [
|
|
3981
|
+
"http:",
|
|
3982
|
+
"https:",
|
|
3983
|
+
"mailto:",
|
|
3984
|
+
"tel:"
|
|
3985
|
+
];
|
|
3986
|
+
try {
|
|
3987
|
+
const url = new URL(str);
|
|
3988
|
+
if (!validProtocols.includes(url.protocol)) {
|
|
3989
|
+
return void 0;
|
|
3990
|
+
}
|
|
3991
|
+
return url;
|
|
3992
|
+
} catch (_err) {
|
|
3993
|
+
return void 0;
|
|
3994
|
+
}
|
|
3995
|
+
};
|
|
3996
|
+
var isValidPosition = (state2, pos) => {
|
|
3997
|
+
const invalidPositions = /* @__PURE__ */ new Set([
|
|
3998
|
+
"Link",
|
|
3999
|
+
"LinkMark",
|
|
4000
|
+
"Code",
|
|
4001
|
+
"FencedCode"
|
|
4002
|
+
]);
|
|
4003
|
+
const tree = syntaxTree4(state2);
|
|
4004
|
+
let node = tree.resolveInner(pos, -1);
|
|
4005
|
+
while (node) {
|
|
4006
|
+
if (invalidPositions.has(node.name)) {
|
|
4007
|
+
return false;
|
|
4008
|
+
}
|
|
4009
|
+
node = node.parent;
|
|
4010
|
+
}
|
|
4011
|
+
return true;
|
|
4012
|
+
};
|
|
4013
|
+
|
|
4025
4014
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
4026
4015
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
4027
4016
|
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField7 } from "@codemirror/state";
|
|
@@ -4244,7 +4233,7 @@ var buildDecorations2 = (view, options, focus) => {
|
|
|
4244
4233
|
const getHeaderLevels = (node, level) => {
|
|
4245
4234
|
invariant4(level > 0, void 0, {
|
|
4246
4235
|
F: __dxlog_file10,
|
|
4247
|
-
L:
|
|
4236
|
+
L: 158,
|
|
4248
4237
|
S: void 0,
|
|
4249
4238
|
A: [
|
|
4250
4239
|
"level > 0",
|
|
@@ -4283,7 +4272,7 @@ var buildDecorations2 = (view, options, focus) => {
|
|
|
4283
4272
|
const getCurrentList = () => {
|
|
4284
4273
|
invariant4(listLevels.length, void 0, {
|
|
4285
4274
|
F: __dxlog_file10,
|
|
4286
|
-
L:
|
|
4275
|
+
L: 180,
|
|
4287
4276
|
S: void 0,
|
|
4288
4277
|
A: [
|
|
4289
4278
|
"listLevels.length",
|
|
@@ -4306,20 +4295,23 @@ var buildDecorations2 = (view, options, focus) => {
|
|
|
4306
4295
|
headers[level - 1].number++;
|
|
4307
4296
|
}
|
|
4308
4297
|
const editing = editingRange(state2, node, focus);
|
|
4309
|
-
if (
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4298
|
+
if (editing) {
|
|
4299
|
+
break;
|
|
4300
|
+
}
|
|
4301
|
+
const mark = node.node.firstChild;
|
|
4302
|
+
if (mark?.name === "HeaderMark") {
|
|
4303
|
+
const { from, to = 6 } = options.numberedHeadings ?? {};
|
|
4304
|
+
const text = view.state.sliceDoc(node.from, node.to);
|
|
4305
|
+
const len = text.match(/[#\s]+/)[0].length;
|
|
4306
|
+
if (!from || level < from || level > to) {
|
|
4307
|
+
atomicDeco.add(mark.from, mark.from + len, hide);
|
|
4308
|
+
} else {
|
|
4309
|
+
const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + " ";
|
|
4310
|
+
if (num.length) {
|
|
4311
|
+
atomicDeco.add(mark.from, mark.from + len, Decoration7.replace({
|
|
4312
|
+
widget: new TextWidget(num, theme.heading(level))
|
|
4313
|
+
}));
|
|
4319
4314
|
}
|
|
4320
|
-
deco.add(node.from, node.to, Decoration7.replace({
|
|
4321
|
-
widget: new TextWidget(text, heading(level))
|
|
4322
|
-
}));
|
|
4323
4315
|
}
|
|
4324
4316
|
}
|
|
4325
4317
|
return false;
|
|
@@ -4519,13 +4511,14 @@ var decorateMarkdown = (options = {}) => {
|
|
|
4519
4511
|
]
|
|
4520
4512
|
}),
|
|
4521
4513
|
formattingStyles,
|
|
4514
|
+
linkPastePlugin,
|
|
4522
4515
|
image(),
|
|
4523
4516
|
table()
|
|
4524
4517
|
];
|
|
4525
4518
|
};
|
|
4526
4519
|
var formattingStyles = EditorView14.baseTheme({
|
|
4527
4520
|
"& .cm-code": {
|
|
4528
|
-
fontFamily: getToken("fontFamily.mono"
|
|
4521
|
+
fontFamily: getToken("fontFamily.mono")
|
|
4529
4522
|
},
|
|
4530
4523
|
"& .cm-codeblock-line": {
|
|
4531
4524
|
paddingInline: "1rem !important"
|
|
@@ -4578,7 +4571,6 @@ var formattingStyles = EditorView14.baseTheme({
|
|
|
4578
4571
|
"& .cm-list-mark": {
|
|
4579
4572
|
display: "inline-block",
|
|
4580
4573
|
textAlign: "right",
|
|
4581
|
-
color: getToken("extend.colors.neutral.500"),
|
|
4582
4574
|
fontVariant: "tabular-nums"
|
|
4583
4575
|
},
|
|
4584
4576
|
"& .cm-list-mark-bullet": {
|
|
@@ -4717,57 +4709,69 @@ import { debounce as debounce2 } from "@dxos/async";
|
|
|
4717
4709
|
import { invariant as invariant5 } from "@dxos/invariant";
|
|
4718
4710
|
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
4719
4711
|
var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/state.ts";
|
|
4720
|
-
var
|
|
4712
|
+
var stateRestoreAnnotation = "dxos.org/cm/state-restore";
|
|
4721
4713
|
var keyPrefix = "dxos.org/react-ui-editor/state";
|
|
4722
4714
|
var localStorageStateStoreAdapter = {
|
|
4723
|
-
|
|
4715
|
+
getState: (id) => {
|
|
4724
4716
|
invariant5(id, void 0, {
|
|
4725
4717
|
F: __dxlog_file12,
|
|
4726
|
-
L:
|
|
4718
|
+
L: 34,
|
|
4727
4719
|
S: void 0,
|
|
4728
4720
|
A: [
|
|
4729
4721
|
"id",
|
|
4730
4722
|
""
|
|
4731
4723
|
]
|
|
4732
4724
|
});
|
|
4733
|
-
localStorage.
|
|
4725
|
+
const state2 = localStorage.getItem(`${keyPrefix}/${id}`);
|
|
4726
|
+
return state2 ? JSON.parse(state2) : void 0;
|
|
4734
4727
|
},
|
|
4735
|
-
|
|
4728
|
+
setState: (id, state2) => {
|
|
4736
4729
|
invariant5(id, void 0, {
|
|
4737
4730
|
F: __dxlog_file12,
|
|
4738
|
-
L:
|
|
4731
|
+
L: 40,
|
|
4739
4732
|
S: void 0,
|
|
4740
4733
|
A: [
|
|
4741
4734
|
"id",
|
|
4742
4735
|
""
|
|
4743
4736
|
]
|
|
4744
4737
|
});
|
|
4745
|
-
|
|
4746
|
-
return state2 ? JSON.parse(state2) : void 0;
|
|
4738
|
+
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state2));
|
|
4747
4739
|
}
|
|
4748
4740
|
};
|
|
4741
|
+
var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
4742
|
+
return {
|
|
4743
|
+
selection,
|
|
4744
|
+
scrollIntoView: !scrollTo,
|
|
4745
|
+
effects: scrollTo ? EditorView15.scrollIntoView(scrollTo, {
|
|
4746
|
+
yMargin: 96
|
|
4747
|
+
}) : void 0,
|
|
4748
|
+
annotations: Transaction2.userEvent.of(stateRestoreAnnotation)
|
|
4749
|
+
};
|
|
4750
|
+
};
|
|
4749
4751
|
var state = ({ getState, setState } = {}) => {
|
|
4750
4752
|
const setStateDebounced = debounce2(setState, 1e3);
|
|
4751
4753
|
return [
|
|
4752
4754
|
// TODO(burdon): Track scrolling (currently only updates when cursor moves).
|
|
4753
|
-
|
|
4755
|
+
// EditorView.domEventHandlers({
|
|
4756
|
+
// scroll: (event) => {
|
|
4757
|
+
// setStateDebounced(id, {});
|
|
4758
|
+
// },
|
|
4759
|
+
// }),
|
|
4760
|
+
EditorView15.updateListener.of(({ view, transactions }) => {
|
|
4754
4761
|
const id = view.state.facet(documentId2);
|
|
4755
|
-
if (!id || transactions.some((tr) => tr.isUserEvent(
|
|
4762
|
+
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
|
4756
4763
|
return;
|
|
4757
4764
|
}
|
|
4758
4765
|
if (setState) {
|
|
4759
|
-
const {
|
|
4766
|
+
const { scrollTop } = view.scrollDOM;
|
|
4760
4767
|
const pos = view.posAtCoords({
|
|
4761
4768
|
x: 0,
|
|
4762
|
-
y:
|
|
4769
|
+
y: scrollTop
|
|
4763
4770
|
});
|
|
4764
4771
|
if (pos !== null) {
|
|
4765
4772
|
const { anchor, head } = view.state.selection.main;
|
|
4766
4773
|
setStateDebounced(id, {
|
|
4767
|
-
scrollTo:
|
|
4768
|
-
from: pos,
|
|
4769
|
-
yMargin: 0
|
|
4770
|
-
},
|
|
4774
|
+
scrollTo: pos,
|
|
4771
4775
|
selection: {
|
|
4772
4776
|
anchor,
|
|
4773
4777
|
head
|
|
@@ -4782,13 +4786,7 @@ var state = ({ getState, setState } = {}) => {
|
|
|
4782
4786
|
run: (view) => {
|
|
4783
4787
|
const state2 = getState(view.state.facet(documentId2));
|
|
4784
4788
|
if (state2) {
|
|
4785
|
-
view.dispatch(
|
|
4786
|
-
effects: EditorView15.scrollIntoView(state2.scrollTo.from, {
|
|
4787
|
-
yMargin: 0
|
|
4788
|
-
}),
|
|
4789
|
-
selection: state2.selection,
|
|
4790
|
-
annotations: Transaction2.userEvent.of(scrollAnnotation)
|
|
4791
|
-
});
|
|
4789
|
+
view.dispatch(createEditorStateTransaction(state2));
|
|
4792
4790
|
}
|
|
4793
4791
|
return true;
|
|
4794
4792
|
}
|
|
@@ -5234,12 +5232,13 @@ var Toolbar = {
|
|
|
5234
5232
|
|
|
5235
5233
|
// packages/ui/react-ui-editor/src/defaults.ts
|
|
5236
5234
|
import { EditorView as EditorView16 } from "@codemirror/view";
|
|
5237
|
-
var editorContent = "!mt-[16px] !mli-auto w-full max-w-[min(50rem,100%-4rem)]";
|
|
5235
|
+
var editorContent = "!mt-[16px] !mb-[32px] !mli-auto w-full max-w-[min(50rem,100%-4rem)]";
|
|
5238
5236
|
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
|
5239
5237
|
var editorGutter = EditorView16.baseTheme({
|
|
5240
5238
|
".cm-gutters": {
|
|
5241
5239
|
// Match margin from content.
|
|
5242
5240
|
marginTop: "16px",
|
|
5241
|
+
marginBottom: "16px",
|
|
5243
5242
|
// Inside within content margin.
|
|
5244
5243
|
marginRight: "-32px",
|
|
5245
5244
|
width: "32px",
|
|
@@ -5258,18 +5257,14 @@ import { EditorView as EditorView17 } from "@codemirror/view";
|
|
|
5258
5257
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
5259
5258
|
import { useCallback, useEffect as useEffect3, useMemo as useMemo3, useRef as useRef2, useState as useState4 } from "react";
|
|
5260
5259
|
import { log as log8 } from "@dxos/log";
|
|
5261
|
-
import { useDefaultValue } from "@dxos/react-ui";
|
|
5262
5260
|
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
5263
5261
|
var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
5264
5262
|
var instanceCount = 0;
|
|
5265
5263
|
var useTextEditor = (props = {}, deps = []) => {
|
|
5266
|
-
const { id, initialValue,
|
|
5264
|
+
const { id, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } = useMemo3(() => {
|
|
5267
5265
|
return typeof props === "function" ? props() : props;
|
|
5268
5266
|
}, deps ?? []);
|
|
5269
5267
|
const [instanceId] = useState4(() => `text-editor-${++instanceCount}`);
|
|
5270
|
-
const scrollTo = useDefaultValue(_scrollTo, EditorView17.scrollIntoView(0, {
|
|
5271
|
-
yMargin: 0
|
|
5272
|
-
}));
|
|
5273
5268
|
const onUpdate = useRef2();
|
|
5274
5269
|
const [view, setView] = useState4();
|
|
5275
5270
|
const parentRef = useRef2(null);
|
|
@@ -5282,12 +5277,16 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
|
5282
5277
|
doc: initialValue?.length ?? 0
|
|
5283
5278
|
}, {
|
|
5284
5279
|
F: __dxlog_file13,
|
|
5285
|
-
L:
|
|
5280
|
+
L: 78,
|
|
5286
5281
|
S: void 0,
|
|
5287
5282
|
C: (f, a) => f(...a)
|
|
5288
5283
|
});
|
|
5289
|
-
let initialSelection
|
|
5290
|
-
if (
|
|
5284
|
+
let initialSelection;
|
|
5285
|
+
if (selection?.anchor && initialValue?.length) {
|
|
5286
|
+
if (selection.anchor <= initialValue.length && (selection?.head ?? 0) <= initialValue.length) {
|
|
5287
|
+
initialSelection = selection;
|
|
5288
|
+
}
|
|
5289
|
+
} else if (moveToEndOfLine && selection === void 0) {
|
|
5291
5290
|
const index = initialValue?.indexOf("\n");
|
|
5292
5291
|
const anchor = !index || index === -1 ? 0 : index;
|
|
5293
5292
|
initialSelection = {
|
|
@@ -5303,20 +5302,21 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
|
5303
5302
|
EditorView17.exceptionSink.of((err) => {
|
|
5304
5303
|
log8.catch(err, void 0, {
|
|
5305
5304
|
F: __dxlog_file13,
|
|
5306
|
-
L:
|
|
5305
|
+
L: 100,
|
|
5307
5306
|
S: void 0,
|
|
5308
5307
|
C: (f, a) => f(...a)
|
|
5309
5308
|
});
|
|
5310
5309
|
}),
|
|
5311
5310
|
extensions,
|
|
5312
5311
|
EditorView17.updateListener.of(() => {
|
|
5313
|
-
|
|
5312
|
+
setTimeout(() => {
|
|
5313
|
+
onUpdate.current?.();
|
|
5314
|
+
});
|
|
5314
5315
|
})
|
|
5315
5316
|
].filter(isNotFalsy4)
|
|
5316
5317
|
});
|
|
5317
5318
|
view2 = new EditorView17({
|
|
5318
5319
|
parent: parentRef.current,
|
|
5319
|
-
scrollTo,
|
|
5320
5320
|
selection: initialSelection,
|
|
5321
5321
|
state: state2,
|
|
5322
5322
|
// NOTE: Uncomment to debug/monitor all transactions.
|
|
@@ -5343,7 +5343,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
|
5343
5343
|
id
|
|
5344
5344
|
}, {
|
|
5345
5345
|
F: __dxlog_file13,
|
|
5346
|
-
L:
|
|
5346
|
+
L: 136,
|
|
5347
5347
|
S: void 0,
|
|
5348
5348
|
C: (f, a) => f(...a)
|
|
5349
5349
|
});
|
|
@@ -5352,17 +5352,13 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
|
5352
5352
|
}, deps);
|
|
5353
5353
|
useEffect3(() => {
|
|
5354
5354
|
if (view) {
|
|
5355
|
-
|
|
5356
|
-
onUpdate.current =
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
scrollIntoView: !scrollTo
|
|
5363
|
-
});
|
|
5364
|
-
};
|
|
5365
|
-
}
|
|
5355
|
+
onUpdate.current = () => {
|
|
5356
|
+
onUpdate.current = void 0;
|
|
5357
|
+
view.dispatch(createEditorStateTransaction({
|
|
5358
|
+
scrollTo,
|
|
5359
|
+
selection
|
|
5360
|
+
}));
|
|
5361
|
+
};
|
|
5366
5362
|
if (view.state.facet(editorInputMode).noTabster) {
|
|
5367
5363
|
parentRef.current?.removeAttribute("data-tabster");
|
|
5368
5364
|
}
|
|
@@ -5436,6 +5432,7 @@ export {
|
|
|
5436
5432
|
createBasicExtensions,
|
|
5437
5433
|
createComment,
|
|
5438
5434
|
createDataExtensions,
|
|
5435
|
+
createEditorStateTransaction,
|
|
5439
5436
|
createExternalCommentSync,
|
|
5440
5437
|
createMarkdownExtensions,
|
|
5441
5438
|
createThemeExtensions,
|