@zuilib/text-editor 0.2.0 → 0.2.1
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/CHANGELOG.md +42 -0
- package/DRAWING_FORMAT.md +149 -0
- package/README.md +121 -133
- package/dist/index.d.ts +135 -1
- package/dist/index.js +113 -1
- package/package.json +4 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Changelog — @zuilib/text-editor
|
|
2
|
+
|
|
3
|
+
## 0.2.1
|
|
4
|
+
|
|
5
|
+
- `DRAWING_FORMAT.md`: authoritative spec of the ```drawing JSON payload,
|
|
6
|
+
written for programmatic/LLM consumption; ships in the npm package
|
|
7
|
+
- New export `DRAWING_DATA_JSON_SCHEMA` (JSON Schema draft-07) for
|
|
8
|
+
validating or structured-output-generating drawing payloads
|
|
9
|
+
- New exports `parseDrawingData` / `serializeDrawingData`
|
|
10
|
+
- This changelog; README overhaul
|
|
11
|
+
|
|
12
|
+
## 0.2.0
|
|
13
|
+
|
|
14
|
+
- **Outline** (`outline` prop, default off): docked, collapsible
|
|
15
|
+
table-of-contents sidebar — live heading list, click-to-scroll, current
|
|
16
|
+
section highlighted
|
|
17
|
+
- **Section folding** (`foldable` prop, default on): collapse everything
|
|
18
|
+
under a heading via a gutter chevron; view-layer only (markdown
|
|
19
|
+
untouched); auto-expands if the cursor enters a folded section
|
|
20
|
+
|
|
21
|
+
## 0.1.0
|
|
22
|
+
|
|
23
|
+
- **Tables**: GFM pipe tables round-trip through markdown; artifact-style
|
|
24
|
+
rendering; in-place editing via Lexical `TablePlugin`; new peer deps
|
|
25
|
+
`@lexical/table` and `@lexical/utils`
|
|
26
|
+
- **Toolbar** (`toolbar` prop, default on): inline formatting, insert
|
|
27
|
+
table, insert drawing
|
|
28
|
+
- **Drawing canvas**: Excalidraw-style diagrams embedded as ```drawing
|
|
29
|
+
fenced JSON blocks — see `DRAWING_FORMAT.md`
|
|
30
|
+
- Shapes: rectangle, ellipse, triangle, pentagon, arrow, line, text
|
|
31
|
+
- Boxes are cards with three attached text slots (label / content /
|
|
32
|
+
footer) that move, resize, and wrap with the shape
|
|
33
|
+
- Connectors bind to boxes and track them; one-way or two-way arrows;
|
|
34
|
+
midpoint labels; straight, elbow, or waypoint-routed paths
|
|
35
|
+
- Stroke/fill palettes; dark mode via canvas color inversion
|
|
36
|
+
- Round-trip test suite (`pnpm test`)
|
|
37
|
+
|
|
38
|
+
## 0.0.2 and earlier
|
|
39
|
+
|
|
40
|
+
- Markdown editor wrapping Lexical: `edit-md` / `edit-raw` / `view` modes,
|
|
41
|
+
markdown shortcuts, checklists, fenced code highlighting, YAML
|
|
42
|
+
frontmatter block, controlled `value`/`onChange`
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# The `drawing` block format
|
|
2
|
+
|
|
3
|
+
`@zuilib/text-editor` documents are plain markdown. Diagrams are embedded as
|
|
4
|
+
a fenced code block with the language `drawing`, containing a single JSON
|
|
5
|
+
object:
|
|
6
|
+
|
|
7
|
+
````md
|
|
8
|
+
```drawing
|
|
9
|
+
{"version":1,"height":320,"shapes":[ ... ]}
|
|
10
|
+
```
|
|
11
|
+
````
|
|
12
|
+
|
|
13
|
+
This document is the authoritative spec of that JSON payload. It is written
|
|
14
|
+
so it can be handed to a program or an LLM that needs to **generate or edit
|
|
15
|
+
drawings**. A machine-readable JSON Schema of the same rules is exported
|
|
16
|
+
from the package as `DRAWING_DATA_JSON_SCHEMA`.
|
|
17
|
+
|
|
18
|
+
Malformed payloads never crash the editor: anything that fails validation
|
|
19
|
+
degrades to an empty canvas (invalid shapes are dropped individually).
|
|
20
|
+
|
|
21
|
+
## Coordinate system
|
|
22
|
+
|
|
23
|
+
- Origin `(0,0)` is the canvas's top-left; x grows right, y grows down.
|
|
24
|
+
- Units are CSS pixels.
|
|
25
|
+
- The canvas is as wide as the editor (fluid). Keep shapes within roughly
|
|
26
|
+
x ∈ [0, 700] to be safe on typical layouts.
|
|
27
|
+
- `height` is the canvas height in pixels (minimum 80; 300–400 is typical).
|
|
28
|
+
|
|
29
|
+
## Top-level object
|
|
30
|
+
|
|
31
|
+
| Field | Type | Notes |
|
|
32
|
+
|-----------|-----------|-----------------------------------------|
|
|
33
|
+
| `version` | `1` | Literal `1` |
|
|
34
|
+
| `height` | `number` | Canvas height in px |
|
|
35
|
+
| `shapes` | `Shape[]` | Render order: later shapes draw on top |
|
|
36
|
+
|
|
37
|
+
## Shape object
|
|
38
|
+
|
|
39
|
+
All shapes share these required fields:
|
|
40
|
+
|
|
41
|
+
| Field | Type | Meaning |
|
|
42
|
+
|---------------|----------|--------------------------------------------------------------------|
|
|
43
|
+
| `id` | `string` | Unique within the drawing; bindings reference it |
|
|
44
|
+
| `type` | `string` | `rect` \| `ellipse` \| `triangle` \| `pentagon` \| `arrow` \| `line` \| `text` |
|
|
45
|
+
| `x`, `y` | `number` | Boxes/text: top-left of the bounding box. Connectors: start point. |
|
|
46
|
+
| `w`, `h` | `number` | Boxes/text: size (non-negative). Connectors: delta to the end point (`end = (x+w, y+h)`; may be negative). |
|
|
47
|
+
| `stroke` | `string` | CSS color of the outline and of all text on the shape |
|
|
48
|
+
| `fill` | `string` | CSS color of the interior; `"transparent"` for none |
|
|
49
|
+
| `strokeWidth` | `number` | Use `2` |
|
|
50
|
+
|
|
51
|
+
### Boxes (`rect`, `ellipse`, `triangle`, `pentagon`) — "cards"
|
|
52
|
+
|
|
53
|
+
Boxes are card-like: they can carry up to three text slots that render
|
|
54
|
+
inside the shape and move/resize/wrap with it:
|
|
55
|
+
|
|
56
|
+
| Field | Renders as |
|
|
57
|
+
|----------|-----------------------------------------------|
|
|
58
|
+
| `label` | Small bold heading at the top of the box |
|
|
59
|
+
| `text` | Main content, centered |
|
|
60
|
+
| `footer` | Small dim line at the bottom |
|
|
61
|
+
|
|
62
|
+
Text wraps automatically to the box width; `\n` forces a line break.
|
|
63
|
+
Triangles are apex-up isoceles; pentagons are apex-up, inscribed in the
|
|
64
|
+
bounding box. Prefer these slots over floating `text` shapes — slot text is
|
|
65
|
+
attached to the card.
|
|
66
|
+
|
|
67
|
+
### `text` — free-floating annotation
|
|
68
|
+
|
|
69
|
+
`text` holds the content. `w`/`h` are advisory (the editor recomputes them
|
|
70
|
+
from the content); position is the top-left of the first line. Use only for
|
|
71
|
+
annotations that belong to no box (the editor deletes a text shape when its
|
|
72
|
+
content is emptied).
|
|
73
|
+
|
|
74
|
+
### Connectors (`arrow`, `line`)
|
|
75
|
+
|
|
76
|
+
Geometry: from `(x, y)` to `(x+w, y+h)`. `arrow` has a head at the end;
|
|
77
|
+
`line` has none.
|
|
78
|
+
|
|
79
|
+
| Field | Type | Meaning |
|
|
80
|
+
|-----------------|------------|-------------------------------------------------------------------------|
|
|
81
|
+
| `text` | `string` | Label rendered at the path midpoint on a small backing plate |
|
|
82
|
+
| `bidirectional` | `boolean` | Arrows only: heads on both ends |
|
|
83
|
+
| `startBinding` | `string` | id of the box the start attaches to |
|
|
84
|
+
| `endBinding` | `string` | id of the box the end attaches to |
|
|
85
|
+
| `routing` | `"elbow"` | Orthogonal auto-routing with up to two right-angle bends |
|
|
86
|
+
| `elbow` | `number` | 0–1: middle-segment position along the span (default 0.5) |
|
|
87
|
+
| `waypoints` | `Point[]` | Explicit intermediate path points (`{x,y}`), ordered start→end |
|
|
88
|
+
|
|
89
|
+
**Bindings.** When `startBinding`/`endBinding` name a box id, the editor
|
|
90
|
+
re-anchors that endpoint onto the box's border (aimed at the other end, with
|
|
91
|
+
a small gap) and keeps it attached as the box moves. Generated endpoints
|
|
92
|
+
therefore only need to be approximately right — place them near the intended
|
|
93
|
+
boxes and the resolver snaps them. Don't bind both ends of one connector to
|
|
94
|
+
the same box. Bindings to ids that don't exist are silently dropped.
|
|
95
|
+
|
|
96
|
+
**Routing.** Omit `routing` for a straight (possibly diagonal) connector.
|
|
97
|
+
`"elbow"` renders an orthogonal path: it runs along the dominant axis, turns
|
|
98
|
+
through a perpendicular middle segment (positioned by `elbow`), and turns
|
|
99
|
+
again. If `waypoints` is non-empty it defines the path (`start → waypoints…
|
|
100
|
+
→ end`) and `routing`/`elbow` are ignored. Waypoints are absolute canvas
|
|
101
|
+
coordinates; align consecutive points on x or y to get right angles.
|
|
102
|
+
|
|
103
|
+
## Recommended colors
|
|
104
|
+
|
|
105
|
+
Any CSS color works; the editor's palette (dark-mode safe — the canvas
|
|
106
|
+
inverts colors Excalidraw-style in dark themes):
|
|
107
|
+
|
|
108
|
+
- Strokes: `#1e1e1e` (default), `#e03131` red, `#2f9e44` green, `#1971c2` blue, `#f08c00` orange
|
|
109
|
+
- Fills: `transparent`, `#ffc9c9`, `#b2f2bb`, `#a5d8ff`, `#ffec99`
|
|
110
|
+
|
|
111
|
+
Pair a colored stroke with its pastel fill (`#1971c2` + `#a5d8ff`, etc.).
|
|
112
|
+
|
|
113
|
+
## Examples
|
|
114
|
+
|
|
115
|
+
Two bound cards with a labeled arrow:
|
|
116
|
+
|
|
117
|
+
````md
|
|
118
|
+
```drawing
|
|
119
|
+
{"version":1,"height":260,"shapes":[
|
|
120
|
+
{"id":"web","type":"rect","x":40,"y":70,"w":170,"h":100,"stroke":"#1971c2","fill":"#a5d8ff","strokeWidth":2,"label":"CLIENT","text":"Web App","footer":"React"},
|
|
121
|
+
{"id":"api","type":"rect","x":330,"y":70,"w":170,"h":100,"stroke":"#2f9e44","fill":"#b2f2bb","strokeWidth":2,"label":"SERVICE","text":"API","footer":"Kotlin"},
|
|
122
|
+
{"id":"e1","type":"arrow","x":216,"y":120,"w":108,"h":0,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"startBinding":"web","endBinding":"api","text":"REST"}
|
|
123
|
+
]}
|
|
124
|
+
```
|
|
125
|
+
````
|
|
126
|
+
|
|
127
|
+
An elbow arrow and a hand-routed multi-bend line:
|
|
128
|
+
|
|
129
|
+
````md
|
|
130
|
+
```drawing
|
|
131
|
+
{"version":1,"height":300,"shapes":[
|
|
132
|
+
{"id":"a","type":"rect","x":40,"y":40,"w":150,"h":80,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"text":"A"},
|
|
133
|
+
{"id":"b","type":"ellipse","x":420,"y":180,"w":150,"h":80,"stroke":"#e03131","fill":"#ffc9c9","strokeWidth":2,"text":"B"},
|
|
134
|
+
{"id":"e1","type":"arrow","x":196,"y":80,"w":224,"h":140,"stroke":"#1e1e1e","fill":"transparent","strokeWidth":2,"startBinding":"a","endBinding":"b","routing":"elbow"},
|
|
135
|
+
{"id":"e2","type":"line","x":115,"y":126,"w":380,"h":54,"stroke":"#1971c2","fill":"transparent","strokeWidth":2,"startBinding":"a","endBinding":"b","waypoints":[{"x":115,"y":260},{"x":495,"y":260}]}
|
|
136
|
+
]}
|
|
137
|
+
```
|
|
138
|
+
````
|
|
139
|
+
|
|
140
|
+
## Generation checklist
|
|
141
|
+
|
|
142
|
+
1. One JSON object, single ```drawing fence, no comments or trailing commas.
|
|
143
|
+
2. Every `id` unique; every binding references an existing box id.
|
|
144
|
+
3. Boxes ≥ 120×70 when they carry text slots; leave ~60px between cards for
|
|
145
|
+
connectors and labels.
|
|
146
|
+
4. Box text goes in `label`/`text`/`footer` — not in floating `text` shapes.
|
|
147
|
+
5. Connectors between cards should bind both ends; approximate endpoints are
|
|
148
|
+
fine (the editor snaps them to borders).
|
|
149
|
+
6. `height` large enough to contain every shape plus ~20px margin.
|
package/README.md
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
# @zuilib/text-editor
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
3
|
+
A markdown editor for ZUI built on [Lexical](https://lexical.dev/). Plain
|
|
4
|
+
markdown in, plain markdown out — with an artifact-style editing experience
|
|
5
|
+
on top: rich tables, an embedded Excalidraw-style diagram canvas, a
|
|
6
|
+
document outline, and collapsible sections.
|
|
7
|
+
|
|
8
|
+
**Features**
|
|
9
|
+
|
|
10
|
+
- **Three modes**: rich WYSIWYG (`edit-md`), raw markdown (`edit-raw`),
|
|
11
|
+
read-only render (`view`) — all driven by one controlled `value` string
|
|
12
|
+
- **Markdown shortcuts** while typing: headings, lists, checklists,
|
|
13
|
+
blockquotes, links, fenced code (with syntax highlighting), tables
|
|
14
|
+
- **Tables**: GFM pipe tables, edited in place (tab between cells, ranges,
|
|
15
|
+
inline formatting), styled like Claude artifacts
|
|
16
|
+
- **Diagrams**: a drawing canvas embedded in the document — cards with
|
|
17
|
+
attached text slots, bound arrows that follow their cards, elbow and
|
|
18
|
+
multi-waypoint routing, labels, color palettes, dark mode
|
|
19
|
+
- **Outline**: optional table-of-contents sidebar with click-to-scroll and
|
|
20
|
+
current-section highlight
|
|
21
|
+
- **Section folding**: collapse everything under a heading, view-layer only
|
|
22
|
+
- **Toolbar**: inline formatting plus insert-table / insert-drawing
|
|
23
|
+
- YAML **frontmatter** block support (`---` at the top)
|
|
24
|
+
|
|
25
|
+
Everything round-trips through the markdown string: tables as GFM,
|
|
26
|
+
diagrams as ` ```drawing ` fenced JSON ([format spec](./DRAWING_FORMAT.md)),
|
|
27
|
+
frontmatter as `---` blocks. Feature history: [CHANGELOG](./CHANGELOG.md).
|
|
28
28
|
|
|
29
29
|
## Installation
|
|
30
30
|
|
|
@@ -34,42 +34,8 @@ pnpm add @zuilib/text-editor @zuilib/core \
|
|
|
34
34
|
@lexical/code @lexical/list @lexical/link @lexical/table @lexical/utils
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```json
|
|
40
|
-
{
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@zuilib/text-editor": "workspace:*",
|
|
43
|
-
"@zuilib/core": "workspace:*",
|
|
44
|
-
"lexical": "^0.35.0",
|
|
45
|
-
"@lexical/react": "^0.35.0",
|
|
46
|
-
"@lexical/markdown": "^0.35.0",
|
|
47
|
-
"@lexical/rich-text": "^0.35.0",
|
|
48
|
-
"@lexical/code": "^0.35.0",
|
|
49
|
-
"@lexical/list": "^0.35.0",
|
|
50
|
-
"@lexical/link": "^0.35.0",
|
|
51
|
-
"@lexical/table": "^0.35.0",
|
|
52
|
-
"@lexical/utils": "^0.35.0"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Import rules
|
|
58
|
-
|
|
59
|
-
| Rule | Detail |
|
|
60
|
-
|------|--------|
|
|
61
|
-
| **Named export** | `import { MarkdownEditor } from '@zuilib/text-editor'` |
|
|
62
|
-
| **Types** | `import type { MarkdownEditorProps } from '@zuilib/text-editor'` |
|
|
63
|
-
| **Styles** | `import '@zuilib/text-editor/styles.css'` and `@zuilib/core/styles.css` |
|
|
64
|
-
| **Controlled** | Always pass `value` + `onChange` for persisted content |
|
|
65
|
-
| **Mode switches** | Switching `edit-raw` → `edit-md` re-mounts Lexical with latest markdown (cursor-safe) |
|
|
66
|
-
|
|
67
|
-
## Exports
|
|
68
|
-
|
|
69
|
-
| Subpath | Exports |
|
|
70
|
-
|---------|---------|
|
|
71
|
-
| `@zuilib/text-editor` | `MarkdownEditor` (default re-exported as named), `MarkdownEditorProps` |
|
|
72
|
-
| `@zuilib/text-editor/styles.css` | Editor chrome + Lexical theme classes |
|
|
37
|
+
All `lexical`/`@lexical/*` packages are peer dependencies at `^0.35.0`;
|
|
38
|
+
`react`/`react-dom` at `^18 || ^19`.
|
|
73
39
|
|
|
74
40
|
## Quick start
|
|
75
41
|
|
|
@@ -81,32 +47,12 @@ import { MarkdownEditor } from '@zuilib/text-editor'
|
|
|
81
47
|
|
|
82
48
|
function Notes() {
|
|
83
49
|
const [value, setValue] = useState('# Hello\n\n- [ ] Try checklists')
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<MarkdownEditor
|
|
87
|
-
value={value}
|
|
88
|
-
onChange={setValue}
|
|
89
|
-
placeholder="Start writing…"
|
|
90
|
-
/>
|
|
91
|
-
)
|
|
50
|
+
return <MarkdownEditor value={value} onChange={setValue} outline />
|
|
92
51
|
}
|
|
93
52
|
```
|
|
94
53
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
| `mode` | UI | `onChange` |
|
|
98
|
-
|--------|-----|------------|
|
|
99
|
-
| `'edit-md'` (default) | Lexical rich editor + markdown shortcuts | Emits markdown string |
|
|
100
|
-
| `'edit-raw'` | Plain `<textarea>` with markdown source | Emits markdown string |
|
|
101
|
-
| `'view'` | Read-only rendered content | No editing (`onChange` unused) |
|
|
102
|
-
|
|
103
|
-
```tsx
|
|
104
|
-
<MarkdownEditor mode="edit-md" value={md} onChange={setMd} />
|
|
105
|
-
<MarkdownEditor mode="edit-raw" value={md} onChange={setMd} />
|
|
106
|
-
<MarkdownEditor mode="view" value={md} />
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Toggle modes in parent state; the editor preserves content via an internal ref when remounting Lexical after raw editing.
|
|
54
|
+
The component is controlled: pass `value` and persist what `onChange`
|
|
55
|
+
emits. The emitted string is always plain markdown.
|
|
110
56
|
|
|
111
57
|
## Props (`MarkdownEditorProps`)
|
|
112
58
|
|
|
@@ -115,25 +61,29 @@ Toggle modes in parent state; the editor preserves content via an internal ref w
|
|
|
115
61
|
| `value` | `string` | `''` | Markdown source (controlled) |
|
|
116
62
|
| `onChange` | `(value: string) => void` | — | Called on every edit |
|
|
117
63
|
| `mode` | `'edit-md' \| 'edit-raw' \| 'view'` | `'edit-md'` | Editing surface |
|
|
118
|
-
| `placeholder` | `string` | `'Start writing...'` | Empty
|
|
64
|
+
| `placeholder` | `string` | `'Start writing...'` | Empty-state hint |
|
|
119
65
|
| `readOnly` | `boolean` | `false` | Disables editing in Lexical modes |
|
|
120
66
|
| `autoFocus` | `boolean` | `false` | Focus on mount |
|
|
121
67
|
| `className` | `string` | — | Root wrapper class |
|
|
122
|
-
| `toolbar` | `boolean` | `true` | Formatting/insert toolbar
|
|
123
|
-
| `outline` | `boolean` | `false` | Table-of-contents sidebar
|
|
124
|
-
| `foldable` | `boolean` | `true` | Collapse sections under
|
|
125
|
-
|
|
126
|
-
## Markdown features
|
|
68
|
+
| `toolbar` | `boolean` | `true` | Formatting/insert toolbar (`edit-md`) |
|
|
69
|
+
| `outline` | `boolean` | `false` | Table-of-contents sidebar |
|
|
70
|
+
| `foldable` | `boolean` | `true` | Collapse sections under headings |
|
|
127
71
|
|
|
128
|
-
|
|
72
|
+
### Modes
|
|
129
73
|
|
|
130
|
-
|
|
74
|
+
| `mode` | UI | Notes |
|
|
75
|
+
|--------|-----|-------|
|
|
76
|
+
| `'edit-md'` | Lexical rich editor | Shortcuts, toolbar, tables, canvas |
|
|
77
|
+
| `'edit-raw'` | Plain `<textarea>` | Direct markdown source editing |
|
|
78
|
+
| `'view'` | Read-only render | Outline/folding still work |
|
|
131
79
|
|
|
132
|
-
|
|
80
|
+
Switching `edit-raw` → `edit-md` re-mounts Lexical with the latest text
|
|
81
|
+
(cursor-safe).
|
|
133
82
|
|
|
134
83
|
## Tables
|
|
135
84
|
|
|
136
|
-
|
|
85
|
+
Type a `| a | b |` row or use the toolbar's insert-table button. GFM
|
|
86
|
+
round-trip:
|
|
137
87
|
|
|
138
88
|
```md
|
|
139
89
|
| Metric | Q1 | Q2 |
|
|
@@ -141,72 +91,110 @@ GFM pipe tables round-trip through markdown and render artifact-style (rounded o
|
|
|
141
91
|
| Revenue | $1.2M | $1.8M |
|
|
142
92
|
```
|
|
143
93
|
|
|
144
|
-
|
|
94
|
+
Rendering is artifact-style (rounded outer border, shaded header row).
|
|
95
|
+
Editing is in place: Tab/arrows between cells, cell range selection, inline
|
|
96
|
+
formatting inside cells. Cell content is single-line in markdown; newlines
|
|
97
|
+
are escaped as `\n`.
|
|
98
|
+
|
|
99
|
+
## Diagrams (drawing canvas)
|
|
100
|
+
|
|
101
|
+
The toolbar's insert-drawing button embeds a canvas; the drawing persists
|
|
102
|
+
in the markdown as a ` ```drawing ` fenced JSON block, fully specified in
|
|
103
|
+
**[DRAWING_FORMAT.md](./DRAWING_FORMAT.md)**.
|
|
104
|
+
|
|
105
|
+
- **Shapes**: rectangle, ellipse, triangle, pentagon, arrow, line, text —
|
|
106
|
+
with stroke/fill palettes. Draw by picking a tool and dragging.
|
|
107
|
+
- **Cards**: every box carries three text slots that move, resize, and wrap
|
|
108
|
+
with it — a bold **label** on top, **content** in the center, a dim
|
|
109
|
+
**footer** at the bottom. Click a selected box (or double-click its
|
|
110
|
+
top/middle/bottom strip, or press Enter) to edit a slot.
|
|
111
|
+
- **Bound connectors**: an arrow drawn from one card to another attaches to
|
|
112
|
+
both — moving a card moves its arrows, endpoints anchored to the border.
|
|
113
|
+
Drag an endpoint off/onto a card to detach/re-attach.
|
|
114
|
+
- **Routing**: straight (diagonal) by default; toggle **elbow** for right
|
|
115
|
+
angles, or drag the dashed "+" handles on a selected connector to add any
|
|
116
|
+
number of **waypoints** (they snap to neighbors' axes for clean 90°
|
|
117
|
+
bends). One-way / two-way arrowhead toggle; midpoint **labels**.
|
|
118
|
+
- **Canvas**: resizable height, dot grid, white surface that inverts
|
|
119
|
+
Excalidraw-style in dark mode (`.dark` ancestor class).
|
|
145
120
|
|
|
146
|
-
##
|
|
147
|
-
|
|
148
|
-
The toolbar's "Insert drawing" button embeds an Excalidraw-style canvas for simple diagrams: rectangles, ellipses, triangles, pentagons, arrows, lines, and text labels, with a stroke and fill color palette.
|
|
121
|
+
## Outline & section folding
|
|
149
122
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
- `Delete`/`Backspace` removes the selected shape; drag the bottom pill to resize the canvas
|
|
154
|
-
- Boxes (rects/ellipses) have three built-in text slots that move with the shape: a bold **label** at the top, main **content** in the center, and a dimmer **footer** at the bottom. Double-click the top strip of a box to edit the label, the middle for content, the bottom strip for the footer (or click a selected box again, or press Enter for content). Clearing a slot removes it; the box stays.
|
|
155
|
-
- **Arrows bind to boxes**: draw an arrow starting or ending on a box and it attaches to the box border — moving or resizing the box drags the arrow along. Endpoints re-anchor toward the other end automatically. Drag an endpoint off a box to detach it; drop it on another box to re-attach. Deleting a box releases its arrows.
|
|
156
|
-
- A selected arrow shows a **direction toggle** in the toolbar: one-way (head at the end) or two-way (heads on both ends).
|
|
157
|
-
- A selected connector also shows a **routing toggle**: straight (freely diagonal) or **elbow** — an orthogonal path with right-angle bends. The elbow's middle segment has a drag handle to reposition the bend; its position is stored as a fraction of the span so it stays put while bound boxes move.
|
|
158
|
-
- **Waypoints** for arbitrary multi-segment paths: a selected connector shows dashed "+" handles at each segment midpoint — drag one to insert a bend point there. Waypoints snap to their neighbors' axes near-alignment so right angles are easy; drag freely for diagonals. Double-click a waypoint to remove it. Adding a point to an elbow connector converts its corners into editable waypoints. Selecting a routing mode from the toolbar clears waypoints.
|
|
159
|
-
- **Arrows and lines can carry a label**: double-click the connector (or select it and press Enter) to edit text that rides the midpoint on a small backing plate, and moves as the connector moves.
|
|
160
|
-
- The standalone **Text** tool is for free-floating annotations (e.g. labeling an arrow); double-click to edit
|
|
123
|
+
`outline` docks a collapsible table-of-contents sidebar: live heading list
|
|
124
|
+
indented by level, click to scroll, current section highlighted. Not part
|
|
125
|
+
of the document — pure UI. Available in `edit-md` and `view`.
|
|
161
126
|
|
|
162
|
-
|
|
127
|
+
`foldable` (default on) shows a chevron in the gutter of each heading on
|
|
128
|
+
hover; clicking collapses the section (until the next heading of the same
|
|
129
|
+
or higher level). Folding never changes the markdown; fold state resets on
|
|
130
|
+
remount; a folded section auto-expands if the cursor enters it.
|
|
163
131
|
|
|
164
|
-
|
|
165
|
-
```drawing
|
|
166
|
-
{"version":1,"height":320,"shapes":[...]}
|
|
167
|
-
```
|
|
168
|
-
````
|
|
132
|
+
## For AI agents / programmatic authoring
|
|
169
133
|
|
|
170
|
-
|
|
134
|
+
Documents are plain markdown, so LLMs can generate them — including
|
|
135
|
+
diagrams:
|
|
171
136
|
|
|
172
|
-
|
|
137
|
+
- **[DRAWING_FORMAT.md](./DRAWING_FORMAT.md)** is the authoritative
|
|
138
|
+
` ```drawing ` payload spec, written to be pasted into a prompt (ships in
|
|
139
|
+
the npm package next to this README).
|
|
140
|
+
- `DRAWING_DATA_JSON_SCHEMA` (exported) is the same contract as JSON Schema
|
|
141
|
+
— use it to validate generated payloads or as a structured-output/tool
|
|
142
|
+
schema.
|
|
143
|
+
- `parseDrawingData(json)` is the editor's own lenient parser (invalid
|
|
144
|
+
shapes drop out; never throws); `serializeDrawingData` is its inverse.
|
|
145
|
+
- A ready-made Claude Code skill lives in the monorepo at
|
|
146
|
+
`.claude/skills/text-editor-documents/` — copy it into consuming repos so
|
|
147
|
+
agents there know the dialect.
|
|
173
148
|
|
|
174
|
-
|
|
149
|
+
## Exports
|
|
175
150
|
|
|
176
|
-
|
|
151
|
+
| Export | Purpose |
|
|
152
|
+
|--------|---------|
|
|
153
|
+
| `MarkdownEditor`, `MarkdownEditorProps` | The component |
|
|
154
|
+
| `@zuilib/text-editor/styles.css` | Editor chrome + theme styles (required) |
|
|
155
|
+
| `TABLE` | GFM table markdown transformer |
|
|
156
|
+
| `DRAWING`, `DrawingNode`, `$createDrawingNode`, `$isDrawingNode` | Drawing node + markdown transformer |
|
|
157
|
+
| `FRONTMATTER`, `FrontmatterNode`, `$createFrontmatterNode`, `$isFrontmatterNode` | Frontmatter node + transformer |
|
|
158
|
+
| `DrawingData`, `DrawingShape`, `DrawingShapeType` | Drawing payload types |
|
|
159
|
+
| `parseDrawingData`, `serializeDrawingData` | Drawing payload (de)serialization |
|
|
160
|
+
| `DRAWING_DATA_JSON_SCHEMA` | JSON Schema of the drawing payload |
|
|
177
161
|
|
|
178
162
|
## Form integration
|
|
179
163
|
|
|
180
|
-
With `@zuilib/form`:
|
|
181
|
-
|
|
182
164
|
```tsx
|
|
183
165
|
<FormField control={form.control} name="body">
|
|
184
166
|
{({ field }) => (
|
|
185
|
-
<MarkdownEditor
|
|
186
|
-
value={field.value}
|
|
187
|
-
onChange={field.onChange}
|
|
188
|
-
mode="edit-md"
|
|
189
|
-
/>
|
|
167
|
+
<MarkdownEditor value={field.value} onChange={field.onChange} />
|
|
190
168
|
)}
|
|
191
169
|
</FormField>
|
|
192
170
|
```
|
|
193
171
|
|
|
194
|
-
|
|
172
|
+
Load both CSS entry points (`@zuilib/core/styles.css`,
|
|
173
|
+
`@zuilib/text-editor/styles.css`) in the app layout. Dark mode follows the
|
|
174
|
+
ZUI convention: a `dark` class on `<html>`.
|
|
195
175
|
|
|
196
176
|
## Architecture notes (for extenders)
|
|
197
177
|
|
|
198
|
-
- Source: `src/MarkdownEditor.tsx
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
-
|
|
178
|
+
- Source: `src/MarkdownEditor.tsx`; plugins in `src/plugins/`; drawing
|
|
179
|
+
canvas in `src/components/`; custom nodes in `src/nodes/`;
|
|
180
|
+
transformers in `src/transformers/`
|
|
181
|
+
- Markdown import/export via `@lexical/markdown` transformers; order
|
|
182
|
+
matters: `FRONTMATTER` and `DRAWING` claim their blocks before `CODE`,
|
|
183
|
+
`CHECK_LIST` before `UNORDERED_LIST`
|
|
184
|
+
- Drawing geometry (bindings resolver, elbow/waypoint paths, wrapping) is
|
|
185
|
+
pure and lives in `src/components/drawingGeometry.ts`
|
|
186
|
+
- Tests: `pnpm test` runs a headless-Lexical markdown round-trip suite
|
|
187
|
+
(`tests/roundtrip.mjs`)
|
|
202
188
|
|
|
203
189
|
## Related packages
|
|
204
190
|
|
|
205
191
|
- `@zuilib/core` — design tokens and base styles
|
|
206
192
|
- `@zuilib/form` — react-hook-form wiring
|
|
207
193
|
|
|
208
|
-
## Build (maintainers)
|
|
194
|
+
## Build & release (maintainers)
|
|
209
195
|
|
|
210
196
|
```bash
|
|
211
|
-
pnpm --filter @zuilib/text-editor build
|
|
197
|
+
pnpm --filter @zuilib/text-editor build # tsup → dist/
|
|
198
|
+
pnpm --filter @zuilib/text-editor test # round-trip suite
|
|
199
|
+
pnpm --filter @zuilib/text-editor publish --access public
|
|
212
200
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -104,6 +104,8 @@ type DrawingData = Readonly<{
|
|
|
104
104
|
height: number;
|
|
105
105
|
shapes: readonly DrawingShape[];
|
|
106
106
|
}>;
|
|
107
|
+
declare function serializeDrawingData(data: DrawingData): string;
|
|
108
|
+
declare function parseDrawingData(json: string): DrawingData;
|
|
107
109
|
|
|
108
110
|
type SerializedDrawingNode = Spread<{
|
|
109
111
|
data: string;
|
|
@@ -147,4 +149,136 @@ declare const DRAWING: MultilineElementTransformer;
|
|
|
147
149
|
*/
|
|
148
150
|
declare const TABLE: ElementTransformer;
|
|
149
151
|
|
|
150
|
-
|
|
152
|
+
/**
|
|
153
|
+
* JSON Schema (draft-07) for the payload of a ```drawing fenced block.
|
|
154
|
+
*
|
|
155
|
+
* Use it to validate LLM- or tool-generated drawings before embedding them,
|
|
156
|
+
* or pass it as a structured-output / tool schema so a model is forced to
|
|
157
|
+
* emit valid payloads. Kept in sync with `parseDrawingData` / `isValidShape`
|
|
158
|
+
* in drawingTypes.ts — update both together.
|
|
159
|
+
*/
|
|
160
|
+
declare const DRAWING_DATA_JSON_SCHEMA: {
|
|
161
|
+
readonly $schema: "http://json-schema.org/draft-07/schema#";
|
|
162
|
+
readonly title: "DrawingData";
|
|
163
|
+
readonly description: "Vector drawing embedded in markdown as a ```drawing fenced code block";
|
|
164
|
+
readonly type: "object";
|
|
165
|
+
readonly required: readonly ["version", "height", "shapes"];
|
|
166
|
+
readonly additionalProperties: false;
|
|
167
|
+
readonly properties: {
|
|
168
|
+
readonly version: {
|
|
169
|
+
readonly const: 1;
|
|
170
|
+
};
|
|
171
|
+
readonly height: {
|
|
172
|
+
readonly type: "number";
|
|
173
|
+
readonly minimum: 80;
|
|
174
|
+
readonly description: "Canvas height in pixels (width is fluid)";
|
|
175
|
+
};
|
|
176
|
+
readonly shapes: {
|
|
177
|
+
readonly type: "array";
|
|
178
|
+
readonly items: {
|
|
179
|
+
readonly $ref: "#/definitions/shape";
|
|
180
|
+
};
|
|
181
|
+
readonly description: "Render order: later shapes draw on top";
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
readonly definitions: {
|
|
185
|
+
readonly point: {
|
|
186
|
+
readonly type: "object";
|
|
187
|
+
readonly required: readonly ["x", "y"];
|
|
188
|
+
readonly additionalProperties: false;
|
|
189
|
+
readonly properties: {
|
|
190
|
+
readonly x: {
|
|
191
|
+
readonly type: "number";
|
|
192
|
+
};
|
|
193
|
+
readonly y: {
|
|
194
|
+
readonly type: "number";
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
readonly shape: {
|
|
199
|
+
readonly type: "object";
|
|
200
|
+
readonly required: readonly ["id", "type", "x", "y", "w", "h", "stroke", "fill", "strokeWidth"];
|
|
201
|
+
readonly additionalProperties: false;
|
|
202
|
+
readonly properties: {
|
|
203
|
+
readonly id: {
|
|
204
|
+
readonly type: "string";
|
|
205
|
+
readonly description: "Unique within the drawing; connector bindings reference it";
|
|
206
|
+
};
|
|
207
|
+
readonly type: {
|
|
208
|
+
readonly enum: readonly ["rect", "ellipse", "triangle", "pentagon", "arrow", "line", "text"];
|
|
209
|
+
};
|
|
210
|
+
readonly x: {
|
|
211
|
+
readonly type: "number";
|
|
212
|
+
readonly description: "Boxes/text: left edge of the bounding box. Connectors: start point x.";
|
|
213
|
+
};
|
|
214
|
+
readonly y: {
|
|
215
|
+
readonly type: "number";
|
|
216
|
+
readonly description: "Boxes/text: top edge of the bounding box. Connectors: start point y.";
|
|
217
|
+
};
|
|
218
|
+
readonly w: {
|
|
219
|
+
readonly type: "number";
|
|
220
|
+
readonly description: "Boxes/text: width (non-negative). Connectors: delta x to the end point (may be negative).";
|
|
221
|
+
};
|
|
222
|
+
readonly h: {
|
|
223
|
+
readonly type: "number";
|
|
224
|
+
readonly description: "Boxes/text: height (non-negative). Connectors: delta y to the end point (may be negative).";
|
|
225
|
+
};
|
|
226
|
+
readonly stroke: {
|
|
227
|
+
readonly type: "string";
|
|
228
|
+
readonly description: "CSS color of the outline (and of any text)";
|
|
229
|
+
};
|
|
230
|
+
readonly fill: {
|
|
231
|
+
readonly type: "string";
|
|
232
|
+
readonly description: "CSS color of the interior; \"transparent\" for none";
|
|
233
|
+
};
|
|
234
|
+
readonly strokeWidth: {
|
|
235
|
+
readonly type: "number";
|
|
236
|
+
readonly description: "Outline width; use 2";
|
|
237
|
+
};
|
|
238
|
+
readonly text: {
|
|
239
|
+
readonly type: "string";
|
|
240
|
+
readonly description: "Standalone text content; center content of a box; midpoint label of a connector";
|
|
241
|
+
};
|
|
242
|
+
readonly label: {
|
|
243
|
+
readonly type: "string";
|
|
244
|
+
readonly description: "Boxes only: small bold heading at the top";
|
|
245
|
+
};
|
|
246
|
+
readonly footer: {
|
|
247
|
+
readonly type: "string";
|
|
248
|
+
readonly description: "Boxes only: small dim line at the bottom";
|
|
249
|
+
};
|
|
250
|
+
readonly startBinding: {
|
|
251
|
+
readonly type: "string";
|
|
252
|
+
readonly description: "Connectors only: id of the box the start attaches to. The editor re-anchors the endpoint onto that box’s border.";
|
|
253
|
+
};
|
|
254
|
+
readonly endBinding: {
|
|
255
|
+
readonly type: "string";
|
|
256
|
+
readonly description: "Connectors only: id of the box the end attaches to";
|
|
257
|
+
};
|
|
258
|
+
readonly bidirectional: {
|
|
259
|
+
readonly type: "boolean";
|
|
260
|
+
readonly description: "Arrows only: arrowheads on both ends";
|
|
261
|
+
};
|
|
262
|
+
readonly routing: {
|
|
263
|
+
readonly const: "elbow";
|
|
264
|
+
readonly description: "Connectors only: orthogonal (right-angled) auto-routing. Ignored when waypoints are present.";
|
|
265
|
+
};
|
|
266
|
+
readonly elbow: {
|
|
267
|
+
readonly type: "number";
|
|
268
|
+
readonly minimum: 0;
|
|
269
|
+
readonly maximum: 1;
|
|
270
|
+
readonly description: "Elbow middle-segment position as a fraction of the span (default 0.5)";
|
|
271
|
+
};
|
|
272
|
+
readonly waypoints: {
|
|
273
|
+
readonly type: "array";
|
|
274
|
+
readonly items: {
|
|
275
|
+
readonly $ref: "#/definitions/point";
|
|
276
|
+
};
|
|
277
|
+
readonly description: "Connectors only: intermediate path points in canvas coordinates, ordered start→end. Takes precedence over routing.";
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
export { $createDrawingNode, $createFrontmatterNode, $isDrawingNode, $isFrontmatterNode, DRAWING, DRAWING_DATA_JSON_SCHEMA, type DrawingData, DrawingNode, type DrawingShape, type DrawingShapeType, FRONTMATTER, FrontmatterNode, MarkdownEditor, type Props as MarkdownEditorProps, type SerializedDrawingNode, type SerializedFrontmatterNode, TABLE, parseDrawingData, serializeDrawingData };
|
package/dist/index.js
CHANGED
|
@@ -2689,15 +2689,127 @@ function MarkdownEditor({
|
|
|
2689
2689
|
autoFocus && /* @__PURE__ */ jsx6(AutoFocusPlugin, {})
|
|
2690
2690
|
] }) }, mountKey);
|
|
2691
2691
|
}
|
|
2692
|
+
|
|
2693
|
+
// src/components/drawingSchema.ts
|
|
2694
|
+
var DRAWING_DATA_JSON_SCHEMA = {
|
|
2695
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
2696
|
+
title: "DrawingData",
|
|
2697
|
+
description: "Vector drawing embedded in markdown as a ```drawing fenced code block",
|
|
2698
|
+
type: "object",
|
|
2699
|
+
required: ["version", "height", "shapes"],
|
|
2700
|
+
additionalProperties: false,
|
|
2701
|
+
properties: {
|
|
2702
|
+
version: { const: 1 },
|
|
2703
|
+
height: {
|
|
2704
|
+
type: "number",
|
|
2705
|
+
minimum: 80,
|
|
2706
|
+
description: "Canvas height in pixels (width is fluid)"
|
|
2707
|
+
},
|
|
2708
|
+
shapes: {
|
|
2709
|
+
type: "array",
|
|
2710
|
+
items: { $ref: "#/definitions/shape" },
|
|
2711
|
+
description: "Render order: later shapes draw on top"
|
|
2712
|
+
}
|
|
2713
|
+
},
|
|
2714
|
+
definitions: {
|
|
2715
|
+
point: {
|
|
2716
|
+
type: "object",
|
|
2717
|
+
required: ["x", "y"],
|
|
2718
|
+
additionalProperties: false,
|
|
2719
|
+
properties: { x: { type: "number" }, y: { type: "number" } }
|
|
2720
|
+
},
|
|
2721
|
+
shape: {
|
|
2722
|
+
type: "object",
|
|
2723
|
+
required: ["id", "type", "x", "y", "w", "h", "stroke", "fill", "strokeWidth"],
|
|
2724
|
+
additionalProperties: false,
|
|
2725
|
+
properties: {
|
|
2726
|
+
id: {
|
|
2727
|
+
type: "string",
|
|
2728
|
+
description: "Unique within the drawing; connector bindings reference it"
|
|
2729
|
+
},
|
|
2730
|
+
type: {
|
|
2731
|
+
enum: ["rect", "ellipse", "triangle", "pentagon", "arrow", "line", "text"]
|
|
2732
|
+
},
|
|
2733
|
+
x: {
|
|
2734
|
+
type: "number",
|
|
2735
|
+
description: "Boxes/text: left edge of the bounding box. Connectors: start point x."
|
|
2736
|
+
},
|
|
2737
|
+
y: {
|
|
2738
|
+
type: "number",
|
|
2739
|
+
description: "Boxes/text: top edge of the bounding box. Connectors: start point y."
|
|
2740
|
+
},
|
|
2741
|
+
w: {
|
|
2742
|
+
type: "number",
|
|
2743
|
+
description: "Boxes/text: width (non-negative). Connectors: delta x to the end point (may be negative)."
|
|
2744
|
+
},
|
|
2745
|
+
h: {
|
|
2746
|
+
type: "number",
|
|
2747
|
+
description: "Boxes/text: height (non-negative). Connectors: delta y to the end point (may be negative)."
|
|
2748
|
+
},
|
|
2749
|
+
stroke: {
|
|
2750
|
+
type: "string",
|
|
2751
|
+
description: "CSS color of the outline (and of any text)"
|
|
2752
|
+
},
|
|
2753
|
+
fill: {
|
|
2754
|
+
type: "string",
|
|
2755
|
+
description: 'CSS color of the interior; "transparent" for none'
|
|
2756
|
+
},
|
|
2757
|
+
strokeWidth: { type: "number", description: "Outline width; use 2" },
|
|
2758
|
+
text: {
|
|
2759
|
+
type: "string",
|
|
2760
|
+
description: "Standalone text content; center content of a box; midpoint label of a connector"
|
|
2761
|
+
},
|
|
2762
|
+
label: {
|
|
2763
|
+
type: "string",
|
|
2764
|
+
description: "Boxes only: small bold heading at the top"
|
|
2765
|
+
},
|
|
2766
|
+
footer: {
|
|
2767
|
+
type: "string",
|
|
2768
|
+
description: "Boxes only: small dim line at the bottom"
|
|
2769
|
+
},
|
|
2770
|
+
startBinding: {
|
|
2771
|
+
type: "string",
|
|
2772
|
+
description: "Connectors only: id of the box the start attaches to. The editor re-anchors the endpoint onto that box\u2019s border."
|
|
2773
|
+
},
|
|
2774
|
+
endBinding: {
|
|
2775
|
+
type: "string",
|
|
2776
|
+
description: "Connectors only: id of the box the end attaches to"
|
|
2777
|
+
},
|
|
2778
|
+
bidirectional: {
|
|
2779
|
+
type: "boolean",
|
|
2780
|
+
description: "Arrows only: arrowheads on both ends"
|
|
2781
|
+
},
|
|
2782
|
+
routing: {
|
|
2783
|
+
const: "elbow",
|
|
2784
|
+
description: "Connectors only: orthogonal (right-angled) auto-routing. Ignored when waypoints are present."
|
|
2785
|
+
},
|
|
2786
|
+
elbow: {
|
|
2787
|
+
type: "number",
|
|
2788
|
+
minimum: 0,
|
|
2789
|
+
maximum: 1,
|
|
2790
|
+
description: "Elbow middle-segment position as a fraction of the span (default 0.5)"
|
|
2791
|
+
},
|
|
2792
|
+
waypoints: {
|
|
2793
|
+
type: "array",
|
|
2794
|
+
items: { $ref: "#/definitions/point" },
|
|
2795
|
+
description: "Connectors only: intermediate path points in canvas coordinates, ordered start\u2192end. Takes precedence over routing."
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
};
|
|
2692
2801
|
export {
|
|
2693
2802
|
$createDrawingNode,
|
|
2694
2803
|
$createFrontmatterNode,
|
|
2695
2804
|
$isDrawingNode,
|
|
2696
2805
|
$isFrontmatterNode,
|
|
2697
2806
|
DRAWING,
|
|
2807
|
+
DRAWING_DATA_JSON_SCHEMA,
|
|
2698
2808
|
DrawingNode,
|
|
2699
2809
|
FRONTMATTER,
|
|
2700
2810
|
FrontmatterNode,
|
|
2701
2811
|
MarkdownEditor,
|
|
2702
|
-
TABLE
|
|
2812
|
+
TABLE,
|
|
2813
|
+
parseDrawingData,
|
|
2814
|
+
serializeDrawingData
|
|
2703
2815
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zuilib/text-editor",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "ZUI — A markdown editor component wrapping Lexical",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
"**/*.css"
|
|
10
10
|
],
|
|
11
11
|
"files": [
|
|
12
|
-
"dist"
|
|
12
|
+
"dist",
|
|
13
|
+
"DRAWING_FORMAT.md",
|
|
14
|
+
"CHANGELOG.md"
|
|
13
15
|
],
|
|
14
16
|
"exports": {
|
|
15
17
|
".": {
|