@connextar/house 0.1.1 → 0.2.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.
Files changed (112) hide show
  1. package/README.md +205 -28
  2. package/dist/changelog/changelog.d.ts +60 -0
  3. package/dist/changelog/changelog.d.ts.map +1 -0
  4. package/dist/changelog/changelog.js +61 -0
  5. package/dist/changelog/changelog.js.map +1 -0
  6. package/dist/changelog/index.d.ts +2 -0
  7. package/dist/changelog/index.d.ts.map +1 -0
  8. package/dist/changelog/index.js +2 -0
  9. package/dist/changelog/index.js.map +1 -0
  10. package/dist/editor/block-handle.d.ts +15 -0
  11. package/dist/editor/block-handle.d.ts.map +1 -0
  12. package/dist/editor/block-handle.js +106 -0
  13. package/dist/editor/block-handle.js.map +1 -0
  14. package/dist/editor/blocks.d.ts +35 -0
  15. package/dist/editor/blocks.d.ts.map +1 -0
  16. package/dist/editor/blocks.js +114 -0
  17. package/dist/editor/blocks.js.map +1 -0
  18. package/dist/editor/bubble-toolbar.d.ts +11 -0
  19. package/dist/editor/bubble-toolbar.d.ts.map +1 -0
  20. package/dist/editor/bubble-toolbar.js +87 -0
  21. package/dist/editor/bubble-toolbar.js.map +1 -0
  22. package/dist/editor/content-index.d.ts +2 -0
  23. package/dist/editor/content-index.d.ts.map +1 -0
  24. package/dist/editor/content-index.js +2 -0
  25. package/dist/editor/content-index.js.map +1 -0
  26. package/dist/editor/content.d.ts +30 -0
  27. package/dist/editor/content.d.ts.map +1 -0
  28. package/dist/editor/content.js +256 -0
  29. package/dist/editor/content.js.map +1 -0
  30. package/dist/editor/editor.d.ts +52 -0
  31. package/dist/editor/editor.d.ts.map +1 -0
  32. package/dist/editor/editor.js +160 -0
  33. package/dist/editor/editor.js.map +1 -0
  34. package/dist/editor/emoji-index.d.ts +2 -0
  35. package/dist/editor/emoji-index.d.ts.map +1 -0
  36. package/dist/editor/emoji-index.js +2 -0
  37. package/dist/editor/emoji-index.js.map +1 -0
  38. package/dist/editor/emoji-picker.d.ts +16 -0
  39. package/dist/editor/emoji-picker.d.ts.map +1 -0
  40. package/dist/editor/emoji-picker.js +37 -0
  41. package/dist/editor/emoji-picker.js.map +1 -0
  42. package/dist/editor/emoji.d.ts +18 -0
  43. package/dist/editor/emoji.d.ts.map +1 -0
  44. package/dist/editor/emoji.js +418 -0
  45. package/dist/editor/emoji.js.map +1 -0
  46. package/dist/editor/index.d.ts +5 -0
  47. package/dist/editor/index.d.ts.map +1 -0
  48. package/dist/editor/index.js +6 -0
  49. package/dist/editor/index.js.map +1 -0
  50. package/dist/editor/suggestion-popup.d.ts +17 -0
  51. package/dist/editor/suggestion-popup.d.ts.map +1 -0
  52. package/dist/editor/suggestion-popup.js +57 -0
  53. package/dist/editor/suggestion-popup.js.map +1 -0
  54. package/dist/editor/suggestions.d.ts +93 -0
  55. package/dist/editor/suggestions.d.ts.map +1 -0
  56. package/dist/editor/suggestions.js +179 -0
  57. package/dist/editor/suggestions.js.map +1 -0
  58. package/dist/editor/ui.d.ts +54 -0
  59. package/dist/editor/ui.d.ts.map +1 -0
  60. package/dist/editor/ui.js +58 -0
  61. package/dist/editor/ui.js.map +1 -0
  62. package/dist/house.css +267 -0
  63. package/dist/internal/cx.d.ts +3 -0
  64. package/dist/internal/cx.d.ts.map +1 -0
  65. package/dist/internal/cx.js +5 -0
  66. package/dist/internal/cx.js.map +1 -0
  67. package/dist/internal/next-link.d.ts +23 -0
  68. package/dist/internal/next-link.d.ts.map +1 -0
  69. package/dist/internal/next-link.js +3 -0
  70. package/dist/internal/next-link.js.map +1 -0
  71. package/dist/markdown/guide.d.ts +98 -0
  72. package/dist/markdown/guide.d.ts.map +1 -0
  73. package/dist/markdown/guide.js +328 -0
  74. package/dist/markdown/guide.js.map +1 -0
  75. package/dist/markdown/index.d.ts +4 -0
  76. package/dist/markdown/index.d.ts.map +1 -0
  77. package/dist/markdown/index.js +4 -0
  78. package/dist/markdown/index.js.map +1 -0
  79. package/dist/markdown/table-view.d.ts +28 -0
  80. package/dist/markdown/table-view.d.ts.map +1 -0
  81. package/dist/markdown/table-view.js +25 -0
  82. package/dist/markdown/table-view.js.map +1 -0
  83. package/dist/markdown/table.d.ts +35 -0
  84. package/dist/markdown/table.d.ts.map +1 -0
  85. package/dist/markdown/table.js +79 -0
  86. package/dist/markdown/table.js.map +1 -0
  87. package/dist/release/changelog.d.ts +72 -0
  88. package/dist/release/changelog.d.ts.map +1 -0
  89. package/dist/release/changelog.js +92 -0
  90. package/dist/release/changelog.js.map +1 -0
  91. package/dist/release/index.d.ts +3 -0
  92. package/dist/release/index.d.ts.map +1 -0
  93. package/dist/release/index.js +3 -0
  94. package/dist/release/index.js.map +1 -0
  95. package/dist/release/version.d.ts +33 -0
  96. package/dist/release/version.d.ts.map +1 -0
  97. package/dist/release/version.js +57 -0
  98. package/dist/release/version.js.map +1 -0
  99. package/dist/trail/index.d.ts +3 -0
  100. package/dist/trail/index.d.ts.map +1 -0
  101. package/dist/trail/index.js +3 -0
  102. package/dist/trail/index.js.map +1 -0
  103. package/dist/trail/rules.d.ts +44 -0
  104. package/dist/trail/rules.d.ts.map +1 -0
  105. package/dist/trail/rules.js +74 -0
  106. package/dist/trail/rules.js.map +1 -0
  107. package/dist/trail/trail.d.ts +49 -0
  108. package/dist/trail/trail.d.ts.map +1 -0
  109. package/dist/trail/trail.js +188 -0
  110. package/dist/trail/trail.js.map +1 -0
  111. package/docs/ReleaseProcess.md +315 -0
  112. package/package.json +75 -11
@@ -0,0 +1,114 @@
1
+ import { Code2, Heading1, Heading2, Heading3, List, ListOrdered, ListTodo, Pilcrow, Quote, } from "lucide-react";
2
+ const named = (name) => (node) => node.type.name === name;
3
+ const headingLevel = (level) => (node) => node.type.name === "heading" && node.attrs.level === level;
4
+ const PARAGRAPH = {
5
+ id: "paragraph",
6
+ label: "Text",
7
+ description: "Plain writing",
8
+ icon: Pilcrow,
9
+ keywords: ["paragraph", "plain", "body"],
10
+ shortcut: "",
11
+ apply: (chain) => chain.clearNodes().setParagraph(),
12
+ isActive: (editor) => editor.isActive("paragraph") &&
13
+ !editor.isActive("bulletList") &&
14
+ !editor.isActive("orderedList") &&
15
+ !editor.isActive("taskList") &&
16
+ !editor.isActive("blockquote"),
17
+ matchesNode: named("paragraph"),
18
+ };
19
+ export const BLOCK_TYPES = [
20
+ PARAGRAPH,
21
+ {
22
+ id: "heading1",
23
+ label: "Heading 1",
24
+ description: "Big section heading",
25
+ icon: Heading1,
26
+ keywords: ["h1", "title", "big"],
27
+ shortcut: "# ",
28
+ apply: (chain) => chain.clearNodes().setHeading({ level: 1 }),
29
+ isActive: (editor) => editor.isActive("heading", { level: 1 }),
30
+ matchesNode: headingLevel(1),
31
+ },
32
+ {
33
+ id: "heading2",
34
+ label: "Heading 2",
35
+ description: "Medium section heading",
36
+ icon: Heading2,
37
+ keywords: ["h2", "subtitle"],
38
+ shortcut: "## ",
39
+ apply: (chain) => chain.clearNodes().setHeading({ level: 2 }),
40
+ isActive: (editor) => editor.isActive("heading", { level: 2 }),
41
+ matchesNode: headingLevel(2),
42
+ },
43
+ {
44
+ id: "heading3",
45
+ label: "Heading 3",
46
+ description: "Small section heading",
47
+ icon: Heading3,
48
+ keywords: ["h3", "subheading"],
49
+ shortcut: "### ",
50
+ apply: (chain) => chain.clearNodes().setHeading({ level: 3 }),
51
+ isActive: (editor) => editor.isActive("heading", { level: 3 }),
52
+ matchesNode: headingLevel(3),
53
+ },
54
+ {
55
+ id: "bulletList",
56
+ label: "Bulleted list",
57
+ description: "A simple list",
58
+ icon: List,
59
+ keywords: ["bullet", "unordered", "points"],
60
+ shortcut: "- ",
61
+ apply: (chain) => chain.clearNodes().toggleBulletList(),
62
+ isActive: (editor) => editor.isActive("bulletList"),
63
+ matchesNode: named("bulletList"),
64
+ },
65
+ {
66
+ id: "orderedList",
67
+ label: "Numbered list",
68
+ description: "A list with numbers",
69
+ icon: ListOrdered,
70
+ keywords: ["numbered", "ordered", "steps"],
71
+ shortcut: "1. ",
72
+ apply: (chain) => chain.clearNodes().toggleOrderedList(),
73
+ isActive: (editor) => editor.isActive("orderedList"),
74
+ matchesNode: named("orderedList"),
75
+ },
76
+ {
77
+ id: "taskList",
78
+ label: "To-do list",
79
+ description: "Tick things off",
80
+ icon: ListTodo,
81
+ keywords: ["todo", "task", "checkbox", "tick", "checklist"],
82
+ shortcut: "[] ",
83
+ apply: (chain) => chain.clearNodes().toggleTaskList(),
84
+ isActive: (editor) => editor.isActive("taskList"),
85
+ matchesNode: named("taskList"),
86
+ },
87
+ {
88
+ id: "blockquote",
89
+ label: "Quote",
90
+ description: "Set a passage apart",
91
+ icon: Quote,
92
+ keywords: ["quote", "blockquote", "citation"],
93
+ shortcut: "> ",
94
+ apply: (chain) => chain.clearNodes().setBlockquote(),
95
+ isActive: (editor) => editor.isActive("blockquote"),
96
+ matchesNode: named("blockquote"),
97
+ },
98
+ {
99
+ id: "codeBlock",
100
+ label: "Code",
101
+ description: "Monospaced block",
102
+ icon: Code2,
103
+ keywords: ["code", "snippet", "monospace", "pre"],
104
+ shortcut: "``` ",
105
+ apply: (chain) => chain.clearNodes().setCodeBlock(),
106
+ isActive: (editor) => editor.isActive("codeBlock"),
107
+ matchesNode: named("codeBlock"),
108
+ },
109
+ ];
110
+ /** The block type the selection currently sits in, for "Turn into" state. */
111
+ export function activeBlockType(editor) {
112
+ return BLOCK_TYPES.find((type) => type.id !== "paragraph" && type.isActive(editor)) ?? PARAGRAPH;
113
+ }
114
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../src/editor/blocks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type Editor } from "@tiptap/react";
2
+ /**
3
+ * The formatting controls, shown only over a text selection — the Notion model.
4
+ * There is no standing toolbar: an empty editor is just a page, and the controls
5
+ * appear when there is something to apply them to. Block changes live under
6
+ * "Turn into", the same list the `/` menu and the block grip use.
7
+ */
8
+ export declare function BubbleToolbar({ editor }: {
9
+ editor: Editor;
10
+ }): import("react").JSX.Element | null;
11
+ //# sourceMappingURL=bubble-toolbar.d.ts.map
@@ -0,0 +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,sCAgE3D"}
@@ -0,0 +1,87 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { TextSelection } from "@tiptap/pm/state";
4
+ import { useEditorState } from "@tiptap/react";
5
+ import { BubbleMenu } from "@tiptap/react/menus";
6
+ import { Bold, Check, ChevronDown, Code, Italic, Link as LinkIcon, Strikethrough } from "lucide-react";
7
+ import { useState } from "react";
8
+ import { BLOCK_TYPES, activeBlockType } from "./blocks.js";
9
+ import { ghostButtonClass, IconButton, Menu, MenuContent, MenuItem, MenuLabel, MenuTrigger, PopoverContent, PopoverRoot, PopoverTrigger, primaryButtonClass, TextInput, VerticalSeparator, } from "./ui.js";
10
+ /**
11
+ * Everything the BubbleMenu wrapper is handed must be referentially stable. It
12
+ * re-registers its ProseMirror plugin whenever these props change identity, and
13
+ * re-registering reconfigures the editor's plugin set — which destroys and
14
+ * recreates *every* plugin view, including the suggestion popups, mid-session.
15
+ * An inline object here silently killed the `/` menu on its first re-render.
16
+ */
17
+ const BUBBLE_OPTIONS = { placement: "top", offset: 8 };
18
+ /** Only over a real text selection: not an empty caret, not a node selection (a
19
+ * dragged block), and not inside a code block, where inline marks are noise. */
20
+ const shouldShowBubble = ({ editor: current, state: editorState }) => {
21
+ const { selection } = editorState;
22
+ if (!current.isEditable || selection.empty)
23
+ return false;
24
+ if (!(selection instanceof TextSelection))
25
+ return false;
26
+ if (current.isActive("codeBlock"))
27
+ return false;
28
+ return editorState.doc.textBetween(selection.from, selection.to).trim().length > 0;
29
+ };
30
+ /**
31
+ * The formatting controls, shown only over a text selection — the Notion model.
32
+ * There is no standing toolbar: an empty editor is just a page, and the controls
33
+ * appear when there is something to apply them to. Block changes live under
34
+ * "Turn into", the same list the `/` menu and the block grip use.
35
+ */
36
+ export function BubbleToolbar({ editor }) {
37
+ const state = useEditorState({
38
+ editor,
39
+ selector: ({ editor: current }) => ({
40
+ bold: current.isActive("bold"),
41
+ italic: current.isActive("italic"),
42
+ strike: current.isActive("strike"),
43
+ code: current.isActive("code"),
44
+ link: current.isActive("link"),
45
+ linkHref: current.getAttributes("link").href ?? "",
46
+ block: activeBlockType(current),
47
+ }),
48
+ });
49
+ if (!state)
50
+ return null;
51
+ const chain = () => editor.chain().focus();
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`, 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
+ }
55
+ function MarkToggle({ label, pressed, onToggle, children, }) {
56
+ return (_jsx(IconButton, { "aria-label": label, title: label, pressed: pressed, onClick: onToggle, children: children }));
57
+ }
58
+ /** Set, change or clear the link on the current selection. */
59
+ function LinkControl({ editor, active, href }) {
60
+ const [open, setOpen] = useState(false);
61
+ const [draft, setDraft] = useState("");
62
+ const apply = () => {
63
+ const url = draft.trim();
64
+ const valid = /^https?:\/\//i.test(url) || (url.startsWith("/") && !url.startsWith("//"));
65
+ if (url && valid) {
66
+ editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
67
+ }
68
+ else if (!url) {
69
+ editor.chain().focus().extendMarkRange("link").unsetLink().run();
70
+ }
71
+ setOpen(false);
72
+ };
73
+ return (_jsxs(PopoverRoot, { open: open, onOpenChange: (next) => {
74
+ setOpen(next);
75
+ if (next)
76
+ setDraft(href);
77
+ }, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(IconButton, { "aria-label": "Link", title: "Link", pressed: active, children: _jsx(LinkIcon, { className: "size-4" }) }) }), _jsxs(PopoverContent, { className: "w-80 space-y-2", children: [_jsx("p", { className: "text-sm font-medium", children: "Link" }), _jsx(TextInput, { value: draft, onChange: (event) => setDraft(event.target.value), placeholder: "https://\u2026", "aria-label": "Link address", onKeyDown: (event) => {
78
+ if (event.key === "Enter") {
79
+ event.preventDefault();
80
+ apply();
81
+ }
82
+ } }), _jsxs("div", { className: "flex justify-end gap-2", children: [active ? (_jsx("button", { type: "button", className: `${ghostButtonClass} h-8 px-3`, onClick: () => {
83
+ editor.chain().focus().extendMarkRange("link").unsetLink().run();
84
+ setOpen(false);
85
+ }, children: "Remove" })) : null, _jsx("button", { type: "button", className: primaryButtonClass, onClick: apply, children: "Apply" })] })] })] }));
86
+ }
87
+ //# sourceMappingURL=bubble-toolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bubble-toolbar.js","sourceRoot":"","sources":["../../src/editor/bubble-toolbar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { RichTextContent, richTextPreview, safeHref } from "./content.js";
2
+ //# sourceMappingURL=content-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-index.d.ts","sourceRoot":"","sources":["../../src/editor/content-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { RichTextContent, richTextPreview, safeHref } from "./content.js";
2
+ //# sourceMappingURL=content-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-index.js","sourceRoot":"","sources":["../../src/editor/content-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Read-only display for what `RichTextEditor` writes — the Markdown dialect the
3
+ * editor produces (headings, lists incl. task lists, quotes, code fences,
4
+ * bold/italic/strike/inline code, links, `@`-references, `#hashtags`), with a
5
+ * bare newline shown as a line break so legacy plain-text values in the same
6
+ * columns read exactly as they always did.
7
+ *
8
+ * Separate from a guide renderer deliberately: a help centre wants guide-scale
9
+ * headings and link rewriting; a note wants task lists, fences and line breaks.
10
+ * Folding both dialects and both type scales into one would serve neither well.
11
+ *
12
+ * This is a trust boundary: whatever is stored in a text column is drawn here,
13
+ * often in front of a *different* person. Everything comes out as React
14
+ * elements with checked hrefs — never as markup.
15
+ *
16
+ * Server-safe: no hooks, so views can render bodies without a client boundary.
17
+ * Styled by `.house-prose` in `@connextar/house/house.css`.
18
+ */
19
+ export declare function RichTextContent({ content, className }: {
20
+ content: string;
21
+ className?: string;
22
+ }): import("react").JSX.Element;
23
+ /** Only hrefs safe to hand a browser; anything else renders as plain text. */
24
+ export declare function safeHref(href: string): string | null;
25
+ /**
26
+ * A plain-text preview of a Markdown body — for list cards and search rows.
27
+ * Strips block and inline syntax rather than rendering it.
28
+ */
29
+ export declare function richTextPreview(content: string, max?: number): string;
30
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +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;AAsPD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAclE"}
@@ -0,0 +1,256 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Link } from "../internal/next-link.js";
3
+ import { cx } from "../internal/cx.js";
4
+ /**
5
+ * Read-only display for what `RichTextEditor` writes — the Markdown dialect the
6
+ * editor produces (headings, lists incl. task lists, quotes, code fences,
7
+ * bold/italic/strike/inline code, links, `@`-references, `#hashtags`), with a
8
+ * bare newline shown as a line break so legacy plain-text values in the same
9
+ * columns read exactly as they always did.
10
+ *
11
+ * Separate from a guide renderer deliberately: a help centre wants guide-scale
12
+ * headings and link rewriting; a note wants task lists, fences and line breaks.
13
+ * Folding both dialects and both type scales into one would serve neither well.
14
+ *
15
+ * This is a trust boundary: whatever is stored in a text column is drawn here,
16
+ * often in front of a *different* person. Everything comes out as React
17
+ * elements with checked hrefs — never as markup.
18
+ *
19
+ * Server-safe: no hooks, so views can render bodies without a client boundary.
20
+ * Styled by `.house-prose` in `@connextar/house/house.css`.
21
+ */
22
+ export function RichTextContent({ content, className }) {
23
+ return _jsx("div", { className: cx("house-prose", className), children: renderBlocks(content) });
24
+ }
25
+ /* ── Inline ───────────────────────────────────────────────────────────── */
26
+ // Link labels exclude `[` and both halves are bounded: `[^\]]+` let every `[`
27
+ // of a long run swallow the rest and backtrack, so a 100 KB run of `[` stalled
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;
30
+ const ESCAPED = /\\([\\`*_{}[\]()#+\-.!>~|])/g;
31
+ /** The editor's serialiser backslash-escapes Markdown punctuation in literal text (`\#`, `\*`). */
32
+ function unescapeMarkdown(text) {
33
+ return text.replace(ESCAPED, "$1");
34
+ }
35
+ /** Only hrefs safe to hand a browser; anything else renders as plain text. */
36
+ export function safeHref(href) {
37
+ if (href.startsWith("/")) {
38
+ // "Internal" must mean same-origin after every normalisation a browser
39
+ // applies — `//evil.com` is protocol-relative and `/\evil.com` becomes
40
+ // `https://evil.com/` because browsers treat `\` as `/` in special-scheme
41
+ // URLs. Resolving against a sentinel origin catches all of these at once.
42
+ try {
43
+ return new URL(href, "https://internal.invalid").origin === "https://internal.invalid" ? href : null;
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ }
49
+ try {
50
+ return ["http:", "https:", "mailto:"].includes(new URL(href).protocol) ? href : null;
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ function renderInline(text, keyPrefix) {
57
+ const nodes = [];
58
+ let last = 0;
59
+ let n = 0;
60
+ INLINE.lastIndex = 0;
61
+ for (const match of text.matchAll(INLINE)) {
62
+ const index = match.index ?? 0;
63
+ if (index > last)
64
+ nodes.push(unescapeMarkdown(text.slice(last, index)));
65
+ const key = `${keyPrefix}-${n++}`;
66
+ if (match[1]) {
67
+ nodes.push(_jsx("code", { children: match[2] }, key));
68
+ }
69
+ else if (match[3]) {
70
+ const href = safeHref(match[5] ?? "");
71
+ const label = renderInline(match[4] ?? "", key);
72
+ if (!href) {
73
+ nodes.push(_jsx("span", { children: label }, key));
74
+ }
75
+ else if (href.startsWith("/")) {
76
+ // Internal — an `@`-reference from the editor, or a hand-written app
77
+ // link. Marked so the navigation trail carries the way back across the
78
+ // jump: the trail provider listens for clicks on the attribute, which
79
+ // is what lets this renderer stay hook-free.
80
+ nodes.push(_jsx(Link, { href: href, "data-trail-carry": "", children: label }, key));
81
+ }
82
+ else {
83
+ nodes.push(_jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", children: label }, key));
84
+ }
85
+ }
86
+ else if (match[6]) {
87
+ nodes.push(_jsx("strong", { children: renderInline(match[7] ?? "", key) }, key));
88
+ }
89
+ else if (match[8]) {
90
+ nodes.push(_jsx("s", { children: renderInline(match[9] ?? "", key) }, key));
91
+ }
92
+ else if (match[10]) {
93
+ nodes.push(_jsx("em", { children: renderInline(match[11] ?? "", key) }, key));
94
+ }
95
+ else if (match[12]) {
96
+ nodes.push(_jsx("em", { children: renderInline(match[13] ?? "", key) }, key));
97
+ }
98
+ else if (match[14]) {
99
+ nodes.push(_jsxs("span", { className: "house-hashtag", children: ["#", match[15]] }, key));
100
+ }
101
+ last = index + match[0].length;
102
+ }
103
+ if (last < text.length)
104
+ nodes.push(unescapeMarkdown(text.slice(last)));
105
+ return nodes;
106
+ }
107
+ /** Paragraph text where a bare newline is a visible break. */
108
+ function renderWithBreaks(lines, keyPrefix) {
109
+ return lines.flatMap((line, index) => {
110
+ const rendered = renderInline(line, `${keyPrefix}-l${index}`);
111
+ return index === 0 ? rendered : [_jsx("br", {}, `${keyPrefix}-b${index}`), ...rendered];
112
+ });
113
+ }
114
+ const LIST_LINE = /^(\s*)(?:([-*+])|(\d+)[.)])\s+(?:\[([ xX])\]\s+)?(.*)$/;
115
+ function parseListLine(line) {
116
+ const match = line.match(LIST_LINE);
117
+ if (!match)
118
+ return null;
119
+ return {
120
+ indent: match[1]?.length ?? 0,
121
+ ordered: match[3] !== undefined,
122
+ task: match[4] === undefined ? null : match[4] !== " ",
123
+ text: match[5] ?? "",
124
+ };
125
+ }
126
+ /** Build a (possibly nested) list from consecutive list lines. */
127
+ function renderList(items, keyPrefix) {
128
+ const render = (from, to, key) => {
129
+ const first = items[from];
130
+ if (!first)
131
+ return null;
132
+ const rows = [];
133
+ let i = from;
134
+ let n = 0;
135
+ while (i < to) {
136
+ const item = items[i];
137
+ if (!item)
138
+ break;
139
+ // Deeper lines nest under the previous row.
140
+ let childEnd = i + 1;
141
+ while (childEnd < to && (items[childEnd]?.indent ?? 0) > first.indent)
142
+ childEnd++;
143
+ const children = childEnd > i + 1 ? render(i + 1, childEnd, `${key}-c${n}`) : null;
144
+ rows.push(item.task !== null ? (_jsxs("li", { className: cx(item.task && "house-task-done"), children: [_jsx("input", { type: "checkbox", checked: item.task, readOnly: true, disabled: true, "aria-label": item.text }), _jsxs("span", { children: [renderInline(item.text, `${key}-i${n}`), children] })] }, n)) : (_jsxs("li", { children: [renderInline(item.text, `${key}-i${n}`), children] }, n)));
145
+ i = childEnd;
146
+ n++;
147
+ }
148
+ if (first.task !== null) {
149
+ return (_jsx("ul", { className: "house-task-list", children: rows }, key));
150
+ }
151
+ return first.ordered ? _jsx("ol", { children: rows }, key) : _jsx("ul", { children: rows }, key);
152
+ };
153
+ return render(0, items.length, keyPrefix);
154
+ }
155
+ /* ── Blocks ───────────────────────────────────────────────────────────── */
156
+ const RULE = /^(-{3,}|\*{3,}|_{3,})$/;
157
+ const HEADING = /^(#{1,6})\s+(.*)$/;
158
+ function renderBlocks(content) {
159
+ const lines = content.replace(/\r\n/g, "\n").split("\n");
160
+ const at = (index) => lines[index] ?? "";
161
+ const blocks = [];
162
+ let i = 0;
163
+ let key = 0;
164
+ while (i < lines.length) {
165
+ const line = at(i);
166
+ const trimmed = line.trim();
167
+ if (trimmed === "") {
168
+ i++;
169
+ continue;
170
+ }
171
+ // Code fence — verbatim until the closing fence (or the end).
172
+ if (trimmed.startsWith("```")) {
173
+ const body = [];
174
+ i++;
175
+ while (i < lines.length && !at(i).trim().startsWith("```")) {
176
+ body.push(at(i));
177
+ i++;
178
+ }
179
+ i++; // closing fence
180
+ blocks.push(_jsx("pre", { children: _jsx("code", { children: body.join("\n") }) }, key++));
181
+ continue;
182
+ }
183
+ if (RULE.test(trimmed)) {
184
+ blocks.push(_jsx("hr", {}, key++));
185
+ i++;
186
+ continue;
187
+ }
188
+ const heading = trimmed.match(HEADING);
189
+ if (heading) {
190
+ const level = Math.min(heading[1]?.length ?? 1, 3);
191
+ const nodes = renderInline(heading[2] ?? "", `h${key}`);
192
+ blocks.push(level === 1 ? (_jsx("h1", { children: nodes }, key++)) : level === 2 ? (_jsx("h2", { children: nodes }, key++)) : (_jsx("h3", { children: nodes }, key++)));
193
+ i++;
194
+ continue;
195
+ }
196
+ if (trimmed.startsWith(">")) {
197
+ const quote = [];
198
+ while (i < lines.length && at(i).trim().startsWith(">")) {
199
+ quote.push(at(i).trim().replace(/^>\s?/, ""));
200
+ i++;
201
+ }
202
+ blocks.push(_jsx("blockquote", { children: renderWithBreaks(quote, `q${key}`) }, key++));
203
+ continue;
204
+ }
205
+ if (parseListLine(line)) {
206
+ const items = [];
207
+ while (i < lines.length) {
208
+ const item = parseListLine(at(i));
209
+ if (!item)
210
+ break;
211
+ items.push(item);
212
+ i++;
213
+ }
214
+ blocks.push(_jsx("div", { children: renderList(items, `list${key}`) }, key++));
215
+ continue;
216
+ }
217
+ // Paragraph — consecutive plain lines, each newline a visible break.
218
+ const para = [];
219
+ while (i < lines.length) {
220
+ const next = at(i);
221
+ const t = next.trim();
222
+ if (t === "" ||
223
+ t.startsWith("```") ||
224
+ t.startsWith(">") ||
225
+ HEADING.test(t) ||
226
+ RULE.test(t) ||
227
+ LIST_LINE.test(next)) {
228
+ break;
229
+ }
230
+ para.push(next);
231
+ i++;
232
+ }
233
+ blocks.push(_jsx("p", { children: renderWithBreaks(para, `p${key}`) }, key++));
234
+ }
235
+ return blocks;
236
+ }
237
+ /**
238
+ * A plain-text preview of a Markdown body — for list cards and search rows.
239
+ * Strips block and inline syntax rather than rendering it.
240
+ */
241
+ export function richTextPreview(content, max = 160) {
242
+ // A preview needs the start of the note, not all 100 KB of it.
243
+ const text = content
244
+ .slice(0, Math.max(2000, max * 12))
245
+ .replace(/```[\s\S]*?(```|$)/g, " ")
246
+ .replace(/^#{1,6}\s+/gm, "")
247
+ .replace(/^\s*(?:[-*+]|\d+[.)])\s+(?:\[[ xX]\]\s+)?/gm, "")
248
+ .replace(/^>\s?/gm, "")
249
+ .replace(/\[([^[\]\n]{1,500})\]\([^)\s]{1,2048}\)/g, "$1")
250
+ .replace(/(\*\*|~~|`|\*|_)/g, "")
251
+ .replace(ESCAPED, "$1")
252
+ .replace(/\s+/g, " ")
253
+ .trim();
254
+ return text.length > max ? `${text.slice(0, max - 1)}…` : text;
255
+ }
256
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/editor/content.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { type SuggestionSources } from "./suggestions.js";
2
+ /**
3
+ * Notion-style writing anywhere an app asks for prose: notes, descriptions,
4
+ * instructions, feedback.
5
+ *
6
+ * **Blocks, not a toolbar.** There is no standing formatting bar. Formatting
7
+ * appears as a bubble over a text selection (with Turn into); new blocks come
8
+ * from typing `/` — a filterable menu — or from the `+` beside any block; every
9
+ * block has a grip to drag it elsewhere or open its menu (turn into, duplicate,
10
+ * move up, move down, delete); `:` completes an emoji shortcode. `@` references
11
+ * and `#` tags work when the app passes `sources`. Markdown shortcuts still work
12
+ * while typing (`# `, `- `, `1. `, `[] `, `> `, `**bold**`, "```").
13
+ *
14
+ * It reads and writes **Markdown strings**, deliberately: the fields it replaces
15
+ * are plain-text columns, Markdown needs no sanitiser because nothing HTML-shaped
16
+ * is stored or rendered, and old plain-text values open unchanged (a bare
17
+ * newline stays a line break). That is also why the block vocabulary is exactly
18
+ * what Markdown can say. Read-only display is `RichTextContent`.
19
+ */
20
+ export interface RichTextEditorProps {
21
+ value: string;
22
+ onChange: (markdown: string) => void;
23
+ onBlur?: () => void;
24
+ placeholder?: string;
25
+ /**
26
+ * "field" sits inside a form like a big textarea (bubble and `/`, no gutter);
27
+ * "document" is a full-page editor (block grips, wider gutter, taller).
28
+ */
29
+ variant?: "field" | "document";
30
+ disabled?: boolean;
31
+ autoFocus?: boolean;
32
+ /** Where `@` and `#` get their rows. Omit either and that trigger stays inert. */
33
+ sources?: SuggestionSources;
34
+ /**
35
+ * How a link in the text is followed. "click": an `@`-reference opens on a
36
+ * plain click, as in Notion — for a page that autosaves. "modifier" (the
37
+ * default): only Ctrl/⌘-click follows, so a form with unsaved fields is never
38
+ * left by a stray click on a mention. Any link opens with Ctrl/⌘.
39
+ */
40
+ followLinks?: "click" | "modifier";
41
+ /** Which internal links count as references for `followLinks="click"`. Defaults to an `@` label. */
42
+ isReference?: (href: string, text: string) => boolean;
43
+ /** How today's date is written by the `/` menu. */
44
+ formatDate?: (date: Date) => string;
45
+ id?: string;
46
+ className?: string;
47
+ "aria-invalid"?: boolean;
48
+ "aria-describedby"?: string;
49
+ "aria-label"?: string;
50
+ }
51
+ export declare function RichTextEditor({ value, onChange, onBlur, placeholder, variant, disabled, autoFocus, sources, followLinks, isReference, formatDate, id, className, ...aria }: RichTextEditorProps): import("react").JSX.Element;
52
+ //# sourceMappingURL=editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/editor/editor.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAML,KAAK,iBAAiB,EAEvB,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kFAAkF;IAClF,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACnC,oGAAoG;IACpG,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACtD,mDAAmD;IACnD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IACpC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,MAAM,EACN,WAAgC,EAChC,OAAiB,EACjB,QAAgB,EAChB,SAAiB,EACjB,OAAO,EACP,WAAwB,EACxB,WAAgC,EAChC,UAAU,EACV,EAAE,EACF,SAAS,EACT,GAAG,IAAI,EACR,EAAE,mBAAmB,+BA2KrB"}