@connextar/house 0.19.2 → 0.21.0
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/README.md +37 -0
- package/dist/editor/block-handle.d.ts +15 -7
- package/dist/editor/block-handle.d.ts.map +1 -1
- package/dist/editor/block-handle.js +83 -10
- package/dist/editor/block-handle.js.map +1 -1
- package/dist/editor/bubble-toolbar.d.ts.map +1 -1
- package/dist/editor/bubble-toolbar.js +8 -1
- package/dist/editor/bubble-toolbar.js.map +1 -1
- package/dist/editor/collapsible.d.ts +31 -0
- package/dist/editor/collapsible.d.ts.map +1 -0
- package/dist/editor/collapsible.js +123 -0
- package/dist/editor/collapsible.js.map +1 -0
- package/dist/editor/content.d.ts +3 -1
- package/dist/editor/content.d.ts.map +1 -1
- package/dist/editor/content.js +15 -2
- package/dist/editor/content.js.map +1 -1
- package/dist/editor/editor.d.ts +15 -2
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +57 -1
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/sections.d.ts +37 -0
- package/dist/editor/sections.d.ts.map +1 -0
- package/dist/editor/sections.js +85 -0
- package/dist/editor/sections.js.map +1 -0
- package/dist/editor/ui.d.ts +3 -1
- package/dist/editor/ui.d.ts.map +1 -1
- package/dist/editor/ui.js +2 -2
- package/dist/editor/ui.js.map +1 -1
- package/dist/guides/guide-figure.d.ts +3 -1
- package/dist/guides/guide-figure.d.ts.map +1 -1
- package/dist/guides/guide-figure.js +7 -6
- package/dist/guides/guide-figure.js.map +1 -1
- package/dist/house.css +52 -1
- package/dist/markdown/figure.d.ts +13 -2
- package/dist/markdown/figure.d.ts.map +1 -1
- package/dist/markdown/figure.js +16 -8
- package/dist/markdown/figure.js.map +1 -1
- package/dist/markdown/figures.d.ts +18 -0
- package/dist/markdown/figures.d.ts.map +1 -1
- package/dist/markdown/figures.js +17 -0
- package/dist/markdown/figures.js.map +1 -1
- package/dist/markdown/index.d.ts +2 -2
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1341,6 +1341,31 @@ is given the alt text as `label` for its own `<svg role="img" aria-label>`; one
|
|
|
1341
1341
|
registered as an element is wrapped in `role="img"`. Headings keep their ids
|
|
1342
1342
|
across pictures, and a picture ends a list.
|
|
1343
1343
|
|
|
1344
|
+
**Smaller files for phones (since 0.20.0).** A screenshot can list narrower copies of
|
|
1345
|
+
itself, made by the app when it captures the picture:
|
|
1346
|
+
|
|
1347
|
+
```ts
|
|
1348
|
+
"/guide-images/home.webp": {
|
|
1349
|
+
width: 1600,
|
|
1350
|
+
height: 1656,
|
|
1351
|
+
dark: "/guide-images/home-dark.webp",
|
|
1352
|
+
smaller: [
|
|
1353
|
+
{ width: 800, src: "/guide-images/home-800.webp", dark: "/guide-images/home-dark-800.webp" },
|
|
1354
|
+
{ width: 1200, src: "/guide-images/home-1200.webp", dark: "/guide-images/home-dark-1200.webp" },
|
|
1355
|
+
],
|
|
1356
|
+
},
|
|
1357
|
+
```
|
|
1358
|
+
|
|
1359
|
+
Each `<img>` (light and dark) then gets a `srcset` of the copies and the original, and
|
|
1360
|
+
`sizes` saying how wide the layout draws it — `GUIDE_FIGURE_SIZES`, the article's 48rem
|
|
1361
|
+
or the screen less a 1rem gutter either side. The browser loads the smallest copy that
|
|
1362
|
+
is sharp at that width and the screen's pixel density: 800 for a 2× phone or a 1×
|
|
1363
|
+
desktop, 1200 for a 3× phone, the original for a 2× desktop. `src` stays the
|
|
1364
|
+
original, and the enlarged view always loads it, since it is there to be zoomed into.
|
|
1365
|
+
An app whose layout draws pictures at another width passes `sizes` to `GuideFigure`
|
|
1366
|
+
or `GuideFigureMedia`. A copy as wide as the original or wider is ignored; with no
|
|
1367
|
+
narrower copies nothing changes.
|
|
1368
|
+
|
|
1344
1369
|
`guideFigureProblems(body, figures, { minAltLength })` is the check an app's test
|
|
1345
1370
|
asserts empty for every guide: an unregistered picture, missing (or too short) alt
|
|
1346
1371
|
text, a picture without a blank line either side or indented as if in a list, and
|
|
@@ -1621,6 +1646,18 @@ app knows what its people, records and tags are. **Storage is plain Markdown wit
|
|
|
1621
1646
|
no new node types** — a reference is `[@Ann Lee](/people/1)` — so every existing
|
|
1622
1647
|
text column keeps working and a server can read mentions with a regex.
|
|
1623
1648
|
|
|
1649
|
+
**Sections** (0.21.0). A heading carries everything under it — up to the next heading of its level or higher, a
|
|
1650
|
+
divider or an empty block (`sections.ts`). Dragging a heading by its grip, or **Move section up / down**, moves the
|
|
1651
|
+
whole section, past whole sections; the chevron beside a heading (or **Collapse section** in its menu) folds the
|
|
1652
|
+
section away behind a "Show N more" pill. Folding is a view, never stored, and a caret that lands inside a folded part
|
|
1653
|
+
opens it again. The grip is the drag source only: its menu opens on click from an anchor beside it, because a menu
|
|
1654
|
+
trigger cancels the pointer-down a drag needs.
|
|
1655
|
+
|
|
1656
|
+
**Images** (0.21.0). Pass `onImageFiles(files)` and images can be pasted or dropped in: the app stores each file and
|
|
1657
|
+
answers where it is shown, and the editor writes ``. Only same-site paths are ever drawn — in the editor
|
|
1658
|
+
and in `RichTextContent` (`imageSrc`) — so text can't load an outside address and tell its owner who read it, and
|
|
1659
|
+
when. Without `onImageFiles`, pasted images are ignored as before.
|
|
1660
|
+
|
|
1624
1661
|
`RichTextContent` (from `/editor/content`) is the read-only side: Markdown to
|
|
1625
1662
|
React with no HTML, an allow-list of link schemes, and bounded patterns, safe for
|
|
1626
1663
|
text a stranger wrote. `EmojiPicker` and the curated set of ~360 emoji are in
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Editor } from "@tiptap/react";
|
|
2
2
|
/**
|
|
3
3
|
* The gutter beside whichever block the pointer is over: a `+` that starts a new
|
|
4
|
-
* block underneath (with the `/` menu already open, as Notion does)
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* block underneath (with the `/` menu already open, as Notion does), a grip that
|
|
5
|
+
* drags the block to reorder it or, clicked, opens the block menu — turn into,
|
|
6
|
+
* duplicate, move up, move down, delete — and, beside a heading, a chevron that
|
|
7
|
+
* collapses or expands its section.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* A heading carries its section: dragging it, or moving it up or down, takes
|
|
10
|
+
* everything under it along (sections.ts). Everything works on the block's
|
|
11
|
+
* document position rather than the caret, so a block can be acted on without
|
|
12
|
+
* ever being clicked into. The drag itself is the extension's: it understands
|
|
13
|
+
* nested lists and shows the drop cursor.
|
|
14
|
+
*
|
|
15
|
+
* The grip is the drag source, so it must not be the menu's trigger: a menu
|
|
16
|
+
* trigger opens on pointer-down and cancels it, and a cancelled pointer-down
|
|
17
|
+
* never starts a drag. The menu opens on click instead, anchored to a still
|
|
18
|
+
* element beside the grip.
|
|
11
19
|
*/
|
|
12
20
|
export declare function BlockHandle({ editor }: {
|
|
13
21
|
editor: Editor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block-handle.d.ts","sourceRoot":"","sources":["../../src/editor/block-handle.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"block-handle.d.ts","sourceRoot":"","sources":["../../src/editor/block-handle.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,MAAM,EAAkB,MAAM,eAAe,CAAC;AAqC5D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,+BA2PzD"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { DragHandle } from "@tiptap/extension-drag-handle-react";
|
|
4
|
-
import {
|
|
4
|
+
import { TextSelection } from "@tiptap/pm/state";
|
|
5
|
+
import { useEditorState } from "@tiptap/react";
|
|
6
|
+
import { ArrowDown, ArrowUp, Check, ChevronDown, ChevronRight, Copy, GripVertical, Plus, Trash2 } from "lucide-react";
|
|
5
7
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
8
|
import { BLOCK_TYPES } from "./blocks.js";
|
|
9
|
+
import { collapseKey } from "./collapsible.js";
|
|
10
|
+
import { childIndexAt, neighbourUnit, positionOfChild, sectionEnd, sectionRange } from "./sections.js";
|
|
7
11
|
import { ghostButtonClass, Menu, MenuContent, MenuItem, MenuSeparator, MenuSub, MenuSubContent, MenuSubTrigger, MenuTrigger, } from "./ui.js";
|
|
8
12
|
/**
|
|
9
13
|
* Stable on purpose: the DragHandle wrapper re-registers its plugin when this
|
|
@@ -12,23 +16,38 @@ import { ghostButtonClass, Menu, MenuContent, MenuItem, MenuSeparator, MenuSub,
|
|
|
12
16
|
*/
|
|
13
17
|
const HANDLE_POSITION = { placement: "left-start" };
|
|
14
18
|
const handleButtonClass = `${ghostButtonClass} size-6 p-0 text-muted-foreground hover:text-foreground`;
|
|
19
|
+
/** A top-level heading: the start of a section (sections.ts). */
|
|
20
|
+
const isSectionHeading = (editor, block) => block.node.type.name === "heading" && childIndexAt(editor.state.doc, block.pos) !== null;
|
|
15
21
|
/**
|
|
16
22
|
* The gutter beside whichever block the pointer is over: a `+` that starts a new
|
|
17
|
-
* block underneath (with the `/` menu already open, as Notion does)
|
|
18
|
-
*
|
|
19
|
-
*
|
|
23
|
+
* block underneath (with the `/` menu already open, as Notion does), a grip that
|
|
24
|
+
* drags the block to reorder it or, clicked, opens the block menu — turn into,
|
|
25
|
+
* duplicate, move up, move down, delete — and, beside a heading, a chevron that
|
|
26
|
+
* collapses or expands its section.
|
|
20
27
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
28
|
+
* A heading carries its section: dragging it, or moving it up or down, takes
|
|
29
|
+
* everything under it along (sections.ts). Everything works on the block's
|
|
30
|
+
* document position rather than the caret, so a block can be acted on without
|
|
31
|
+
* ever being clicked into. The drag itself is the extension's: it understands
|
|
32
|
+
* nested lists and shows the drop cursor.
|
|
33
|
+
*
|
|
34
|
+
* The grip is the drag source, so it must not be the menu's trigger: a menu
|
|
35
|
+
* trigger opens on pointer-down and cancels it, and a cancelled pointer-down
|
|
36
|
+
* never starts a drag. The menu opens on click instead, anchored to a still
|
|
37
|
+
* element beside the grip.
|
|
24
38
|
*/
|
|
25
39
|
export function BlockHandle({ editor }) {
|
|
26
40
|
const [hovered, setHovered] = useState(null);
|
|
27
41
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
28
42
|
const menuOpenRef = useRef(false);
|
|
43
|
+
const hoveredRef = useRef(null);
|
|
44
|
+
const gripRef = useRef(null);
|
|
29
45
|
useEffect(() => {
|
|
30
46
|
menuOpenRef.current = menuOpen;
|
|
31
47
|
}, [menuOpen]);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
hoveredRef.current = hovered;
|
|
50
|
+
}, [hovered]);
|
|
32
51
|
// Leave the last block in place while its menu is open, so the menu still
|
|
33
52
|
// knows what it belongs to after the pointer wanders. Stable identity for the
|
|
34
53
|
// same reason as HANDLE_POSITION.
|
|
@@ -37,6 +56,18 @@ export function BlockHandle({ editor }) {
|
|
|
37
56
|
return;
|
|
38
57
|
setHovered(node ? { node, pos } : null);
|
|
39
58
|
}, []);
|
|
59
|
+
// A heading's drag takes its section: select the whole section first, and the
|
|
60
|
+
// extension drags a selection that covers the grip's block as one piece.
|
|
61
|
+
const onElementDragStart = useCallback(() => {
|
|
62
|
+
const block = hoveredRef.current;
|
|
63
|
+
if (!block || block.node.type.name !== "heading")
|
|
64
|
+
return;
|
|
65
|
+
const range = sectionRange(editor.state.doc, block.pos);
|
|
66
|
+
if (!range || range.blocks < 2)
|
|
67
|
+
return;
|
|
68
|
+
const { doc, tr } = editor.state;
|
|
69
|
+
editor.view.dispatch(tr.setSelection(TextSelection.between(doc.resolve(range.from + 1), doc.resolve(range.to - 1))));
|
|
70
|
+
}, [editor]);
|
|
40
71
|
const range = (block) => ({ from: block.pos, to: block.pos + block.node.nodeSize });
|
|
41
72
|
/** Turn the whole block into another type, without moving the caret by hand. */
|
|
42
73
|
const turnInto = (block, typeId) => {
|
|
@@ -57,9 +88,38 @@ export function BlockHandle({ editor }) {
|
|
|
57
88
|
const remove = (block) => {
|
|
58
89
|
editor.chain().focus().deleteRange(range(block)).run();
|
|
59
90
|
};
|
|
60
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* Move the block up (-1) or down (+1) past its neighbour. At the top of the
|
|
93
|
+
* document a heading moves with its section, past whole sections; inside a
|
|
94
|
+
* list or quote, a block swaps with its sibling.
|
|
95
|
+
*/
|
|
61
96
|
const move = (block, direction) => {
|
|
62
|
-
const
|
|
97
|
+
const { doc } = editor.state;
|
|
98
|
+
const index = childIndexAt(doc, block.pos);
|
|
99
|
+
if (index !== null) {
|
|
100
|
+
const end = sectionEnd(doc, index);
|
|
101
|
+
const other = neighbourUnit(doc, index, end, direction);
|
|
102
|
+
if (!other)
|
|
103
|
+
return;
|
|
104
|
+
const [first, last] = direction === 1 ? [[index, end], other] : [other, [index, end]];
|
|
105
|
+
const from = positionOfChild(doc, first[0]);
|
|
106
|
+
const middle = positionOfChild(doc, last[0]);
|
|
107
|
+
const to = positionOfChild(doc, last[1]);
|
|
108
|
+
const upper = doc.slice(from, middle);
|
|
109
|
+
const lower = doc.slice(middle, to);
|
|
110
|
+
editor
|
|
111
|
+
.chain()
|
|
112
|
+
.focus()
|
|
113
|
+
.command(({ tr }) => {
|
|
114
|
+
// Swap the two runs of blocks: [first][last] becomes [last][first].
|
|
115
|
+
tr.replaceRange(from, to, lower);
|
|
116
|
+
tr.insert(from + lower.size, upper.content);
|
|
117
|
+
return true;
|
|
118
|
+
})
|
|
119
|
+
.run();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const $pos = doc.resolve(block.pos);
|
|
63
123
|
const parent = $pos.parent;
|
|
64
124
|
const siblingIndex = $pos.index() + direction;
|
|
65
125
|
if (siblingIndex < 0 || siblingIndex >= parent.childCount)
|
|
@@ -77,6 +137,7 @@ export function BlockHandle({ editor }) {
|
|
|
77
137
|
})
|
|
78
138
|
.run();
|
|
79
139
|
};
|
|
140
|
+
const toggleSection = (block) => editor.chain().focus().toggleSection(block.pos).run();
|
|
80
141
|
/**
|
|
81
142
|
* The `+`: a fresh paragraph under this block with the `/` menu open — or, if
|
|
82
143
|
* this block is already an empty paragraph, just the menu, right here.
|
|
@@ -101,6 +162,18 @@ export function BlockHandle({ editor }) {
|
|
|
101
162
|
.insertContent("/")
|
|
102
163
|
.run();
|
|
103
164
|
};
|
|
104
|
-
|
|
165
|
+
// Re-render when a section folds or opens, wherever that happened (the pill, the menu, a caret).
|
|
166
|
+
const collapsedAt = useEditorState({
|
|
167
|
+
editor,
|
|
168
|
+
selector: ({ editor: current }) => collapseKey.getState(current.state)?.collapsed.join(",") ?? "",
|
|
169
|
+
}) ?? "";
|
|
170
|
+
const heading = hovered && isSectionHeading(editor, hovered) ? hovered : null;
|
|
171
|
+
const collapsed = heading ? collapsedAt.split(",").includes(String(heading.pos)) : false;
|
|
172
|
+
const canCollapse = heading ? (sectionRange(editor.state.doc, heading.pos)?.blocks ?? 1) > 1 || collapsed : false;
|
|
173
|
+
return (_jsxs(DragHandle, { editor: editor, nested: true, className: "house-block-handle", computePositionConfig: HANDLE_POSITION, onNodeChange: onNodeChange, onElementDragStart: onElementDragStart, children: [heading && canCollapse ? (_jsx("button", { type: "button", className: handleButtonClass, "aria-label": collapsed ? "Expand section" : "Collapse section", "aria-expanded": !collapsed, title: collapsed ? "Expand section" : "Collapse section", onClick: () => toggleSection(heading), children: collapsed ? _jsx(ChevronRight, { className: "size-4", "aria-hidden": true }) : _jsx(ChevronDown, { className: "size-4", "aria-hidden": true }) })) : (_jsx("span", { className: "inline-block size-6", "aria-hidden": true })), _jsx("button", { type: "button", className: handleButtonClass, "aria-label": "Add a block below", title: "Add a block below", onClick: () => hovered && insertBelow(hovered), children: _jsx(Plus, { className: "size-4", "aria-hidden": true }) }), _jsxs(Menu, { open: menuOpen, onOpenChange: setMenuOpen, children: [_jsxs("span", { className: "relative inline-flex", children: [_jsx("button", { ref: gripRef, type: "button", className: `${handleButtonClass} cursor-grab active:cursor-grabbing`, "aria-label": heading ? "Section options — drag to move the section" : "Block options — drag to move", "aria-haspopup": "menu", "aria-expanded": menuOpen, title: heading ? "Drag to move the section, click for options" : "Drag to move, click for options", onClick: () => setMenuOpen(true), children: _jsx(GripVertical, { className: "size-4", "aria-hidden": true }) }), _jsx(MenuTrigger, { asChild: true, children: _jsx("span", { "aria-hidden": true, className: "pointer-events-none absolute inset-0", tabIndex: -1 }) })] }), _jsxs(MenuContent, { className: "w-52", onCloseAutoFocus: (event) => {
|
|
174
|
+
// Back to the grip, not the invisible anchor.
|
|
175
|
+
event.preventDefault();
|
|
176
|
+
gripRef.current?.focus();
|
|
177
|
+
}, children: [_jsxs(MenuSub, { children: [_jsx(MenuSubTrigger, { children: "Turn into" }), _jsx(MenuSubContent, { className: "w-48", children: BLOCK_TYPES.map((type) => (_jsxs(MenuItem, { onSelect: () => hovered && turnInto(hovered, type.id), children: [_jsx(type.icon, { className: "size-4", "aria-hidden": true }), _jsx("span", { className: "flex-1", children: type.label }), hovered && type.matchesNode(hovered.node) ? (_jsx(Check, { className: "size-4 text-primary", "aria-hidden": true })) : null] }, type.id))) })] }), heading && canCollapse ? (_jsxs(MenuItem, { onSelect: () => toggleSection(heading), children: [collapsed ? (_jsx(ChevronRight, { className: "size-4", "aria-hidden": true })) : (_jsx(ChevronDown, { className: "size-4", "aria-hidden": true })), collapsed ? "Expand section" : "Collapse section"] })) : null, _jsxs(MenuItem, { onSelect: () => hovered && duplicate(hovered), children: [_jsx(Copy, { className: "size-4", "aria-hidden": true }), "Duplicate"] }), _jsxs(MenuItem, { onSelect: () => hovered && move(hovered, -1), children: [_jsx(ArrowUp, { className: "size-4", "aria-hidden": true }), heading ? "Move section up" : "Move up"] }), _jsxs(MenuItem, { onSelect: () => hovered && move(hovered, 1), children: [_jsx(ArrowDown, { className: "size-4", "aria-hidden": true }), heading ? "Move section down" : "Move down"] }), _jsx(MenuSeparator, {}), _jsxs(MenuItem, { className: "text-destructive focus:text-destructive", onSelect: () => hovered && remove(hovered), children: [_jsx(Trash2, { className: "size-4", "aria-hidden": true }), "Delete"] })] })] })] }));
|
|
105
178
|
}
|
|
106
179
|
//# sourceMappingURL=block-handle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block-handle.js","sourceRoot":"","sources":["../../src/editor/block-handle.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"block-handle.js","sourceRoot":"","sources":["../../src/editor/block-handle.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bubble-toolbar.d.ts","sourceRoot":"","sources":["../../src/editor/bubble-toolbar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAyC5D;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"bubble-toolbar.d.ts","sourceRoot":"","sources":["../../src/editor/bubble-toolbar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAyC5D;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,sCA0E3D"}
|
|
@@ -50,7 +50,14 @@ export function BubbleToolbar({ editor }) {
|
|
|
50
50
|
return null;
|
|
51
51
|
const chain = () => editor.chain().focus();
|
|
52
52
|
const BlockIcon = state.block.icon;
|
|
53
|
-
return (_jsxs(BubbleMenu, { editor: editor, pluginKey: "houseFormattingBubble", updateDelay: 120, options: BUBBLE_OPTIONS, shouldShow: shouldShowBubble, className: "house-bubble-menu flex items-center gap-0.5 rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md", children: [_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: `${ghostButtonClass} h-8 px-2 text-xs`,
|
|
53
|
+
return (_jsxs(BubbleMenu, { editor: editor, pluginKey: "houseFormattingBubble", updateDelay: 120, options: BUBBLE_OPTIONS, shouldShow: shouldShowBubble, className: "house-bubble-menu flex items-center gap-0.5 rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md", children: [_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: `${ghostButtonClass} h-8 px-2 text-xs`,
|
|
54
|
+
// The bubble hides itself when the editor loses focus — unless the press was on the bubble, which it learns
|
|
55
|
+
// from a mousedown. The menu opens on pointer-down and cancels that mousedown, then takes focus; the bubble
|
|
56
|
+
// hid, taking the trigger out of the page, and the menu lost its anchor and opened at the top-left of the
|
|
57
|
+
// screen. So the press is reported to the bubble here, before the menu takes focus.
|
|
58
|
+
onPointerDown: (event) => {
|
|
59
|
+
event.currentTarget.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
|
|
60
|
+
}, children: [_jsx(BlockIcon, { className: "size-4", "aria-hidden": true }), state.block.label, _jsx(ChevronDown, { className: "size-3.5 opacity-60", "aria-hidden": true })] }) }), _jsxs(MenuContent, { className: "w-52", children: [_jsx(MenuLabel, { children: "Turn into" }), BLOCK_TYPES.map((type) => (_jsxs(MenuItem, { onSelect: () => void type.apply(chain()).run(), children: [_jsx(type.icon, { className: "size-4", "aria-hidden": true }), _jsx("span", { className: "flex-1", children: type.label }), type.id === state.block.id ? _jsx(Check, { className: "size-4 text-primary", "aria-hidden": true }) : null] }, type.id)))] })] }), _jsx(VerticalSeparator, {}), _jsx(MarkToggle, { label: "Bold", pressed: state.bold, onToggle: () => chain().toggleBold().run(), children: _jsx(Bold, { className: "size-4" }) }), _jsx(MarkToggle, { label: "Italic", pressed: state.italic, onToggle: () => chain().toggleItalic().run(), children: _jsx(Italic, { className: "size-4" }) }), _jsx(MarkToggle, { label: "Strikethrough", pressed: state.strike, onToggle: () => chain().toggleStrike().run(), children: _jsx(Strikethrough, { className: "size-4" }) }), _jsx(MarkToggle, { label: "Inline code", pressed: state.code, onToggle: () => chain().toggleCode().run(), children: _jsx(Code, { className: "size-4" }) }), _jsx(LinkControl, { editor: editor, active: state.link, href: state.linkHref })] }));
|
|
54
61
|
}
|
|
55
62
|
function MarkToggle({ label, pressed, onToggle, children, }) {
|
|
56
63
|
return (_jsx(IconButton, { "aria-label": label, title: label, pressed: pressed, onClick: onToggle, children: children }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bubble-toolbar.js","sourceRoot":"","sources":["../../src/editor/bubble-toolbar.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAe,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAwB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACvG,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,SAAS,EACT,WAAW,EACX,cAAc,EACd,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,SAAS,EACT,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,EAAE,SAAS,EAAE,KAAc,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAEhE;iFACiF;AACjF,MAAM,gBAAgB,GAA+C,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;IAC/G,MAAM,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC;IAClC,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,SAAS,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzD,IAAI,CAAC,CAAC,SAAS,YAAY,aAAa,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,OAAO,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AACrF,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,MAAM,EAAsB;IAC1D,MAAM,KAAK,GAAG,cAAc,CAAC;QAC3B,MAAM;QACN,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;YAClC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC9B,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAClC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAClC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC9B,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC9B,QAAQ,EAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAA2B,IAAI,EAAE;YAC1E,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC;SAChC,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;IAEnC,OAAO,CACL,MAAC,UAAU,IACT,MAAM,EAAE,MAAM,EACd,SAAS,EAAC,uBAAuB,EACjC,WAAW,EAAE,GAAG,EAChB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAC,8HAA8H,aAExI,MAAC,IAAI,eACH,KAAC,WAAW,IAAC,OAAO,kBAClB,
|
|
1
|
+
{"version":3,"file":"bubble-toolbar.js","sourceRoot":"","sources":["../../src/editor/bubble-toolbar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Extension } from "@tiptap/core";
|
|
2
|
+
import type { EditorState } from "@tiptap/pm/state";
|
|
3
|
+
import { PluginKey } from "@tiptap/pm/state";
|
|
4
|
+
/**
|
|
5
|
+
* Collapsing a heading folds its section away (sections.ts): what's under it is
|
|
6
|
+
* hidden, and a "Show N more" pill at the end of the heading says how much. It
|
|
7
|
+
* is a view of the document, never part of it — nothing is written to the
|
|
8
|
+
* stored Markdown, and a fresh editor opens with everything showing.
|
|
9
|
+
*
|
|
10
|
+
* A caret that lands inside a hidden part (a search, an undo, Enter at the end
|
|
11
|
+
* of a collapsed heading) opens that section again, so nothing is ever typed
|
|
12
|
+
* where it can't be seen.
|
|
13
|
+
*/
|
|
14
|
+
interface CollapseState {
|
|
15
|
+
/** Positions of collapsed headings, kept current as the document changes. */
|
|
16
|
+
collapsed: number[];
|
|
17
|
+
}
|
|
18
|
+
export declare const collapseKey: PluginKey<CollapseState>;
|
|
19
|
+
declare module "@tiptap/core" {
|
|
20
|
+
interface Commands<ReturnType> {
|
|
21
|
+
houseCollapsible: {
|
|
22
|
+
/** Collapse the section of the heading at `pos`, or expand it if it is collapsed. */
|
|
23
|
+
toggleSection: (pos: number) => ReturnType;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Whether the heading at `pos` is collapsed. */
|
|
28
|
+
export declare function isSectionCollapsed(state: EditorState, pos: number): boolean;
|
|
29
|
+
export declare const Collapsible: Extension<any, any>;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=collapsible.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collapsible.d.ts","sourceRoot":"","sources":["../../src/editor/collapsible.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAU,SAAS,EAAiB,MAAM,kBAAkB,CAAC;AAKpE;;;;;;;;;GASG;AAEH,UAAU,aAAa;IACrB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAID,eAAO,MAAM,WAAW,0BAAyD,CAAC;AAElF,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,gBAAgB,EAAE;YAChB,qFAAqF;YACrF,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,UAAU,CAAC;SAC5C,CAAC;KACH;CACF;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE3E;AAiCD,eAAO,MAAM,WAAW,qBAsFtB,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Extension } from "@tiptap/core";
|
|
2
|
+
import { Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
|
|
3
|
+
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
4
|
+
import { childIndexAt, sectionRange } from "./sections.js";
|
|
5
|
+
export const collapseKey = new PluginKey("houseCollapsedSections");
|
|
6
|
+
/** Whether the heading at `pos` is collapsed. */
|
|
7
|
+
export function isSectionCollapsed(state, pos) {
|
|
8
|
+
return collapseKey.getState(state)?.collapsed.includes(pos) ?? false;
|
|
9
|
+
}
|
|
10
|
+
/** The hidden part of each collapsed section: [from, to) positions, keyed by the heading's position. */
|
|
11
|
+
function hiddenRanges(state) {
|
|
12
|
+
const out = [];
|
|
13
|
+
for (const pos of collapseKey.getState(state)?.collapsed ?? []) {
|
|
14
|
+
const range = sectionRange(state.doc, pos);
|
|
15
|
+
const heading = state.doc.nodeAt(pos);
|
|
16
|
+
if (!range || !heading || range.blocks < 2)
|
|
17
|
+
continue;
|
|
18
|
+
out.push({ heading: pos, from: pos + heading.nodeSize, to: range.to });
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
function pill(view, getPos, hidden) {
|
|
23
|
+
const button = document.createElement("button");
|
|
24
|
+
button.type = "button";
|
|
25
|
+
button.className = "house-section-more";
|
|
26
|
+
button.contentEditable = "false";
|
|
27
|
+
button.textContent = `Show ${hidden} more`;
|
|
28
|
+
button.setAttribute("aria-label", `Expand the section: ${hidden} hidden ${hidden === 1 ? "block" : "blocks"}`);
|
|
29
|
+
// Keep the caret where it is; the click does the work.
|
|
30
|
+
button.addEventListener("mousedown", (event) => event.preventDefault());
|
|
31
|
+
button.addEventListener("click", (event) => {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
const at = getPos();
|
|
34
|
+
if (at === undefined)
|
|
35
|
+
return;
|
|
36
|
+
const heading = view.state.doc.resolve(at).before(1);
|
|
37
|
+
view.dispatch(view.state.tr.setMeta(collapseKey, { expand: heading }));
|
|
38
|
+
});
|
|
39
|
+
return button;
|
|
40
|
+
}
|
|
41
|
+
export const Collapsible = Extension.create({
|
|
42
|
+
name: "houseCollapsible",
|
|
43
|
+
addCommands() {
|
|
44
|
+
return {
|
|
45
|
+
toggleSection: (pos) => ({ tr, state, dispatch }) => {
|
|
46
|
+
const heading = tr.doc.nodeAt(pos);
|
|
47
|
+
if (childIndexAt(tr.doc, pos) === null || heading?.type.name !== "heading")
|
|
48
|
+
return false;
|
|
49
|
+
if (dispatch) {
|
|
50
|
+
tr.setMeta(collapseKey, { toggle: pos });
|
|
51
|
+
// Folding away the part the caret is in would open it again at once: the caret goes to the heading.
|
|
52
|
+
const range = sectionRange(tr.doc, pos);
|
|
53
|
+
const head = tr.selection.head;
|
|
54
|
+
if (!isSectionCollapsed(state, pos) && range && head > pos + heading.nodeSize && head < range.to) {
|
|
55
|
+
tr.setSelection(TextSelection.create(tr.doc, pos + heading.nodeSize - 1));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
addProseMirrorPlugins() {
|
|
63
|
+
return [
|
|
64
|
+
new Plugin({
|
|
65
|
+
key: collapseKey,
|
|
66
|
+
state: {
|
|
67
|
+
init: () => ({ collapsed: [] }),
|
|
68
|
+
apply(tr, value, _old, next) {
|
|
69
|
+
let collapsed = value.collapsed
|
|
70
|
+
.map((pos) => tr.mapping.mapResult(pos))
|
|
71
|
+
.filter((result) => !result.deleted)
|
|
72
|
+
.map((result) => result.pos)
|
|
73
|
+
.filter((pos) => childIndexAt(next.doc, pos) !== null && next.doc.nodeAt(pos)?.type.name === "heading");
|
|
74
|
+
const meta = tr.getMeta(collapseKey);
|
|
75
|
+
if (meta && "toggle" in meta) {
|
|
76
|
+
collapsed = collapsed.includes(meta.toggle)
|
|
77
|
+
? collapsed.filter((pos) => pos !== meta.toggle)
|
|
78
|
+
: [...collapsed, meta.toggle];
|
|
79
|
+
}
|
|
80
|
+
else if (meta && "expand" in meta) {
|
|
81
|
+
collapsed = collapsed.filter((pos) => pos !== meta.expand);
|
|
82
|
+
}
|
|
83
|
+
return { collapsed: [...new Set(collapsed)] };
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
// Whatever moved the caret into a hidden part opens it again.
|
|
87
|
+
appendTransaction(_trs, _old, next) {
|
|
88
|
+
const head = next.selection.head;
|
|
89
|
+
const opened = hiddenRanges(next).find((range) => head > range.from && head < range.to);
|
|
90
|
+
return opened ? next.tr.setMeta(collapseKey, { expand: opened.heading }) : null;
|
|
91
|
+
},
|
|
92
|
+
props: {
|
|
93
|
+
decorations(state) {
|
|
94
|
+
const decorations = [];
|
|
95
|
+
for (const range of hiddenRanges(state)) {
|
|
96
|
+
const heading = state.doc.nodeAt(range.heading);
|
|
97
|
+
decorations.push(Decoration.node(range.heading, range.heading + heading.nodeSize, {
|
|
98
|
+
class: "house-section-collapsed",
|
|
99
|
+
"aria-expanded": "false",
|
|
100
|
+
}));
|
|
101
|
+
let hidden = 0;
|
|
102
|
+
state.doc.nodesBetween(range.from, range.to, (node, pos) => {
|
|
103
|
+
if (pos < range.from)
|
|
104
|
+
return false;
|
|
105
|
+
decorations.push(Decoration.node(pos, pos + node.nodeSize, { class: "house-section-hidden" }));
|
|
106
|
+
hidden += 1;
|
|
107
|
+
return false;
|
|
108
|
+
});
|
|
109
|
+
const count = hidden;
|
|
110
|
+
decorations.push(Decoration.widget(range.heading + heading.nodeSize - 1, (view, getPos) => pill(view, getPos, count), {
|
|
111
|
+
side: 1,
|
|
112
|
+
ignoreSelection: true,
|
|
113
|
+
key: `more-${range.heading}-${count}`,
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
return DecorationSet.create(state.doc, decorations);
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
}),
|
|
120
|
+
];
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
//# sourceMappingURL=collapsible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collapsible.js","sourceRoot":"","sources":["../../src/editor/collapsible.ts"],"names":[],"mappings":"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"}
|
package/dist/editor/content.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Read-only display for what `RichTextEditor` writes — the Markdown dialect the
|
|
3
3
|
* editor produces (headings, lists incl. task lists, quotes, code fences,
|
|
4
|
-
* bold/italic/strike/inline code, links, `@`-references, `#hashtags
|
|
4
|
+
* bold/italic/strike/inline code, links, `@`-references, `#hashtags`, images from this site), with a
|
|
5
5
|
* bare newline shown as a line break so legacy plain-text values in the same
|
|
6
6
|
* columns read exactly as they always did.
|
|
7
7
|
*
|
|
@@ -22,6 +22,8 @@ export declare function RichTextContent({ content, className }: {
|
|
|
22
22
|
}): import("react").JSX.Element;
|
|
23
23
|
/** Only hrefs safe to hand a browser; anything else renders as plain text. */
|
|
24
24
|
export declare function safeHref(href: string): string | null;
|
|
25
|
+
/** An image address that may be shown: a path on this site, never another origin. */
|
|
26
|
+
export declare function imageSrc(src: string): string | null;
|
|
25
27
|
/**
|
|
26
28
|
* A plain-text preview of a Markdown body — for list cards and search rows.
|
|
27
29
|
* Strips block and inline syntax rather than rendering it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/editor/content.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAE9F;AAiBD,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBpD;
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/editor/content.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAE9F;AAiBD,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBpD;AAED,qFAAqF;AACrF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGnD;AAkQD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAclE"}
|
package/dist/editor/content.js
CHANGED
|
@@ -4,7 +4,7 @@ import { cx } from "../internal/cx.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Read-only display for what `RichTextEditor` writes — the Markdown dialect the
|
|
6
6
|
* editor produces (headings, lists incl. task lists, quotes, code fences,
|
|
7
|
-
* bold/italic/strike/inline code, links, `@`-references, `#hashtags
|
|
7
|
+
* bold/italic/strike/inline code, links, `@`-references, `#hashtags`, images from this site), with a
|
|
8
8
|
* bare newline shown as a line break so legacy plain-text values in the same
|
|
9
9
|
* columns read exactly as they always did.
|
|
10
10
|
*
|
|
@@ -26,7 +26,7 @@ export function RichTextContent({ content, className }) {
|
|
|
26
26
|
// Link labels exclude `[` and both halves are bounded: `[^\]]+` let every `[`
|
|
27
27
|
// of a long run swallow the rest and backtrack, so a 100 KB run of `[` stalled
|
|
28
28
|
// a server for seconds (AltEd security round 8, 8.1).
|
|
29
|
-
const INLINE = /(`([^`\n]+)`)|(\[([^[\]\n]{1,500})\]\(([^)\s]{1,2048})\))|(\*\*([^*]+)\*\*)|(~~([^~]+)~~)|(\*([^*\n]+)\*)|(\b_([^_\n]+)_\b)|((?:^|(?<=[\s(]))#([a-z0-9][a-z0-9_-]{0,47})\b)/gim;
|
|
29
|
+
const INLINE = /(`([^`\n]+)`)|(\[([^[\]\n]{1,500})\]\(([^)\s]{1,2048})\))|(\*\*([^*]+)\*\*)|(~~([^~]+)~~)|(\*([^*\n]+)\*)|(\b_([^_\n]+)_\b)|((?:^|(?<=[\s(]))#([a-z0-9][a-z0-9_-]{0,47})\b)|(!\[([^[\]\n]{0,500})\]\(([^)\s]{1,2048})\))/gim;
|
|
30
30
|
const ESCAPED = /\\([\\`*_{}[\]()#+\-.!>~|])/g;
|
|
31
31
|
/** The editor's serialiser backslash-escapes Markdown punctuation in literal text (`\#`, `\*`). */
|
|
32
32
|
function unescapeMarkdown(text) {
|
|
@@ -53,6 +53,11 @@ export function safeHref(href) {
|
|
|
53
53
|
return null;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
/** An image address that may be shown: a path on this site, never another origin. */
|
|
57
|
+
export function imageSrc(src) {
|
|
58
|
+
const safe = safeHref(src);
|
|
59
|
+
return safe?.startsWith("/") ? safe : null;
|
|
60
|
+
}
|
|
56
61
|
function renderInline(text, keyPrefix) {
|
|
57
62
|
const nodes = [];
|
|
58
63
|
let last = 0;
|
|
@@ -98,6 +103,14 @@ function renderInline(text, keyPrefix) {
|
|
|
98
103
|
else if (match[14]) {
|
|
99
104
|
nodes.push(_jsxs("span", { className: "house-hashtag", children: ["#", match[15]] }, key));
|
|
100
105
|
}
|
|
106
|
+
else if (match[16]) {
|
|
107
|
+
// Images only from this site: an outside address would tell its owner who read the note, and when.
|
|
108
|
+
const src = imageSrc(match[18] ?? "");
|
|
109
|
+
const alt = unescapeMarkdown(match[17] ?? "");
|
|
110
|
+
nodes.push(src ? (
|
|
111
|
+
// The app's own, access-checked image route: a plain <img>, not a framework image optimiser.
|
|
112
|
+
_jsx("img", { src: src, alt: alt, loading: "lazy", className: "house-image" }, key)) : (_jsx("span", { children: alt ? `[image: ${alt}]` : "[image]" }, key)));
|
|
113
|
+
}
|
|
101
114
|
last = index + match[0].length;
|
|
102
115
|
}
|
|
103
116
|
if (last < text.length)
|