anniedrawing 0.3.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 +33 -0
- package/LICENSE +21 -0
- package/NOTICE +292 -0
- package/README.md +162 -0
- package/dist/agent/describe.d.ts +12 -0
- package/dist/agent/index.d.ts +10 -0
- package/dist/agent/index.js +2 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/place.d.ts +4 -0
- package/dist/agent/query.d.ts +3 -0
- package/dist/agent/toolDefs.d.ts +343 -0
- package/dist/board.d.ts +193 -0
- package/dist/core/catalog.d.ts +22 -0
- package/dist/core/clipboard.d.ts +2 -0
- package/dist/core/defaults.d.ts +19 -0
- package/dist/core/doc.d.ts +2 -0
- package/dist/core/ids.d.ts +5 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.js +1 -0
- package/dist/core/item.d.ts +25 -0
- package/dist/core/links.d.ts +21 -0
- package/dist/core/locks.d.ts +3 -0
- package/dist/core/migrate.d.ts +5 -0
- package/dist/core/paste.d.ts +27 -0
- package/dist/core/schema.d.ts +644 -0
- package/dist/core/types.d.ts +313 -0
- package/dist/docs/agents-repository.md +56 -0
- package/dist/docs/agents.md +157 -0
- package/dist/docs/api.md +258 -0
- package/dist/docs/board-js.md +345 -0
- package/dist/docs/code-of-conduct.md +11 -0
- package/dist/docs/contributing.md +35 -0
- package/dist/docs/decisions.md +107 -0
- package/dist/docs/extensions.md +122 -0
- package/dist/docs/format.md +79 -0
- package/dist/docs/index.html +993 -0
- package/dist/docs/license.txt +21 -0
- package/dist/docs/llms-full.txt +345 -0
- package/dist/docs/llms.txt +90 -0
- package/dist/docs/mcp.md +97 -0
- package/dist/docs/notice.txt +292 -0
- package/dist/docs/nunito-OFL.txt +93 -0
- package/dist/docs/releasing.md +38 -0
- package/dist/docs/security.md +33 -0
- package/dist/favicon.svg +1 -0
- package/dist/fellow.d.ts +7 -0
- package/dist/fellow.js +2 -0
- package/dist/fellow.js.map +1 -0
- package/dist/geo/box.d.ts +13 -0
- package/dist/geo/index.d.ts +5 -0
- package/dist/geo/picker.d.ts +25 -0
- package/dist/geo/router.d.ts +11 -0
- package/dist/geo/vec.d.ts +8 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -0
- package/dist/input/autosave.d.ts +2 -0
- package/dist/input/cursors.d.ts +8 -0
- package/dist/input/measure.d.ts +6 -0
- package/dist/input/urlPaste.d.ts +18 -0
- package/dist/kinds/index.d.ts +2 -0
- package/dist/kinds/registry.d.ts +45 -0
- package/dist/porter/index.d.ts +5 -0
- package/dist/porter/indexedPng.d.ts +13 -0
- package/dist/porter/json.d.ts +3 -0
- package/dist/porter/png.d.ts +10 -0
- package/dist/porter/svg.d.ts +9 -0
- package/dist/shared/board-Bya0O1I7.js +2 -0
- package/dist/shared/board-Bya0O1I7.js.map +1 -0
- package/dist/shared/cards-DWgSVE54.js +2 -0
- package/dist/shared/cards-DWgSVE54.js.map +1 -0
- package/dist/shared/defaults-C-aC_B4z.js +2 -0
- package/dist/shared/defaults-C-aC_B4z.js.map +1 -0
- package/dist/shared/describe-DaWyf3qV.js +3 -0
- package/dist/shared/describe-DaWyf3qV.js.map +1 -0
- package/dist/shared/paste-C22i8o-g.js +2 -0
- package/dist/shared/paste-C22i8o-g.js.map +1 -0
- package/dist/shared/picker-Dv_i4iNP.js +2 -0
- package/dist/shared/picker-Dv_i4iNP.js.map +1 -0
- package/dist/shared/ui-Cay6AVqT.js +2 -0
- package/dist/shared/ui-Cay6AVqT.js.map +1 -0
- package/dist/shared/urlPaste-DN4JtgeB.js +2 -0
- package/dist/shared/urlPaste-DN4JtgeB.js.map +1 -0
- package/dist/stage/cards.d.ts +2 -0
- package/dist/stage/index.d.ts +3 -0
- package/dist/stage/itemView.d.ts +22 -0
- package/dist/stage/lens.d.ts +26 -0
- package/dist/stage/paint.d.ts +23 -0
- package/dist/stage/presence.d.ts +50 -0
- package/dist/stage/stage.d.ts +60 -0
- package/dist/style.css +2 -0
- package/dist/ui/icons.d.ts +2 -0
- package/dist/ui/index.d.ts +16 -0
- package/dist/ui/index.js +1 -0
- package/dist/ui/version.d.ts +3 -0
- package/llms-full.txt +345 -0
- package/llms.txt +90 -0
- package/package.json +120 -0
|
@@ -0,0 +1,993 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<meta
|
|
7
|
+
name="description"
|
|
8
|
+
content="Operator manual for AnnieDrawing: install the local demo, embed the board, apply document operations, and use the agent tools."
|
|
9
|
+
/>
|
|
10
|
+
<title>AnnieDrawing documentation</title>
|
|
11
|
+
<style>
|
|
12
|
+
:root {
|
|
13
|
+
color-scheme: light;
|
|
14
|
+
--ink: #103639;
|
|
15
|
+
--muted: #607672;
|
|
16
|
+
--green: #05d9ab;
|
|
17
|
+
--mint: #aaf1ac;
|
|
18
|
+
--lilac: #8f93f9;
|
|
19
|
+
--paper: #fafcf8;
|
|
20
|
+
--line: #dce6df;
|
|
21
|
+
}
|
|
22
|
+
* {
|
|
23
|
+
box-sizing: border-box;
|
|
24
|
+
}
|
|
25
|
+
html {
|
|
26
|
+
scroll-behavior: smooth;
|
|
27
|
+
scroll-padding-top: 100px;
|
|
28
|
+
overflow-x: hidden;
|
|
29
|
+
}
|
|
30
|
+
html,
|
|
31
|
+
body {
|
|
32
|
+
max-width: 100%;
|
|
33
|
+
}
|
|
34
|
+
body {
|
|
35
|
+
margin: 0;
|
|
36
|
+
background: var(--paper);
|
|
37
|
+
color: var(--ink);
|
|
38
|
+
font-family: ui-rounded, 'Nunito', system-ui, sans-serif;
|
|
39
|
+
font-size: 16px;
|
|
40
|
+
line-height: 1.65;
|
|
41
|
+
}
|
|
42
|
+
a {
|
|
43
|
+
color: inherit;
|
|
44
|
+
text-underline-offset: 4px;
|
|
45
|
+
}
|
|
46
|
+
a:hover {
|
|
47
|
+
color: #087662;
|
|
48
|
+
}
|
|
49
|
+
button,
|
|
50
|
+
a {
|
|
51
|
+
touch-action: manipulation;
|
|
52
|
+
}
|
|
53
|
+
a:focus-visible,
|
|
54
|
+
button:focus-visible {
|
|
55
|
+
outline: 3px solid #08866b;
|
|
56
|
+
outline-offset: 5px;
|
|
57
|
+
border-radius: 4px;
|
|
58
|
+
}
|
|
59
|
+
.skip {
|
|
60
|
+
position: fixed;
|
|
61
|
+
left: 20px;
|
|
62
|
+
top: -80px;
|
|
63
|
+
background: white;
|
|
64
|
+
padding: 12px 24px;
|
|
65
|
+
z-index: 20;
|
|
66
|
+
}
|
|
67
|
+
.skip:focus {
|
|
68
|
+
top: 12px;
|
|
69
|
+
}
|
|
70
|
+
header {
|
|
71
|
+
height: 80px;
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: space-between;
|
|
75
|
+
gap: 8px;
|
|
76
|
+
min-width: 0;
|
|
77
|
+
padding: 0 max(5vw, 24px);
|
|
78
|
+
position: sticky;
|
|
79
|
+
top: 0;
|
|
80
|
+
background: #fafcf8ee;
|
|
81
|
+
backdrop-filter: blur(16px);
|
|
82
|
+
border-bottom: 1px solid var(--line);
|
|
83
|
+
z-index: 10;
|
|
84
|
+
}
|
|
85
|
+
.brand {
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: 11px;
|
|
89
|
+
min-width: 0;
|
|
90
|
+
text-decoration: none;
|
|
91
|
+
font-size: 20px;
|
|
92
|
+
font-weight: 800;
|
|
93
|
+
letter-spacing: -0.7px;
|
|
94
|
+
}
|
|
95
|
+
.brand svg {
|
|
96
|
+
width: 36px;
|
|
97
|
+
height: 36px;
|
|
98
|
+
}
|
|
99
|
+
.header-note {
|
|
100
|
+
font-size: 12px;
|
|
101
|
+
font-weight: 700;
|
|
102
|
+
color: var(--muted);
|
|
103
|
+
letter-spacing: 0.6px;
|
|
104
|
+
margin-left: 12px;
|
|
105
|
+
}
|
|
106
|
+
.open {
|
|
107
|
+
font-size: 13px;
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
text-decoration: none;
|
|
110
|
+
background: var(--ink);
|
|
111
|
+
color: white;
|
|
112
|
+
padding: 10px 18px;
|
|
113
|
+
border-radius: 10px;
|
|
114
|
+
}
|
|
115
|
+
.open:hover {
|
|
116
|
+
background: #1c5053;
|
|
117
|
+
color: white;
|
|
118
|
+
}
|
|
119
|
+
.shell,
|
|
120
|
+
main,
|
|
121
|
+
aside,
|
|
122
|
+
.code,
|
|
123
|
+
table {
|
|
124
|
+
min-width: 0;
|
|
125
|
+
max-width: 100%;
|
|
126
|
+
}
|
|
127
|
+
.shell {
|
|
128
|
+
max-width: 1230px;
|
|
129
|
+
margin: auto;
|
|
130
|
+
display: grid;
|
|
131
|
+
grid-template-columns: 220px minmax(0, 1fr);
|
|
132
|
+
gap: 76px;
|
|
133
|
+
padding: 60px 40px 90px;
|
|
134
|
+
}
|
|
135
|
+
aside {
|
|
136
|
+
position: sticky;
|
|
137
|
+
top: 125px;
|
|
138
|
+
height: max-content;
|
|
139
|
+
}
|
|
140
|
+
aside p {
|
|
141
|
+
font-size: 11px;
|
|
142
|
+
text-transform: uppercase;
|
|
143
|
+
letter-spacing: 1.5px;
|
|
144
|
+
font-weight: 800;
|
|
145
|
+
margin: 0 0 18px;
|
|
146
|
+
color: var(--muted);
|
|
147
|
+
}
|
|
148
|
+
nav {
|
|
149
|
+
display: grid;
|
|
150
|
+
gap: 3px;
|
|
151
|
+
}
|
|
152
|
+
nav a {
|
|
153
|
+
font-size: 14px;
|
|
154
|
+
text-decoration: none;
|
|
155
|
+
padding: 8px 12px;
|
|
156
|
+
border-radius: 9px;
|
|
157
|
+
}
|
|
158
|
+
nav a:hover,
|
|
159
|
+
nav a.active {
|
|
160
|
+
background: #e6f2e6;
|
|
161
|
+
color: #165845;
|
|
162
|
+
}
|
|
163
|
+
nav .external {
|
|
164
|
+
margin-top: 20px;
|
|
165
|
+
border-top: 1px solid var(--line);
|
|
166
|
+
padding-top: 18px;
|
|
167
|
+
}
|
|
168
|
+
.eyebrow {
|
|
169
|
+
font-size: 12px;
|
|
170
|
+
font-weight: 800;
|
|
171
|
+
letter-spacing: 1.6px;
|
|
172
|
+
text-transform: uppercase;
|
|
173
|
+
display: flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
gap: 9px;
|
|
176
|
+
}
|
|
177
|
+
.dot {
|
|
178
|
+
width: 8px;
|
|
179
|
+
height: 8px;
|
|
180
|
+
background: var(--green);
|
|
181
|
+
border-radius: 50%;
|
|
182
|
+
}
|
|
183
|
+
h1 {
|
|
184
|
+
font-size: clamp(32px, 5vw, 64px);
|
|
185
|
+
line-height: 1.08;
|
|
186
|
+
letter-spacing: -2.7px;
|
|
187
|
+
max-width: 650px;
|
|
188
|
+
font-weight: 750;
|
|
189
|
+
margin: 25px 0;
|
|
190
|
+
overflow-wrap: anywhere;
|
|
191
|
+
}
|
|
192
|
+
h1 span {
|
|
193
|
+
position: relative;
|
|
194
|
+
display: inline-block;
|
|
195
|
+
}
|
|
196
|
+
h1 span:after {
|
|
197
|
+
content: '';
|
|
198
|
+
height: 9px;
|
|
199
|
+
position: absolute;
|
|
200
|
+
bottom: 1px;
|
|
201
|
+
left: 0;
|
|
202
|
+
right: 0;
|
|
203
|
+
background: var(--mint);
|
|
204
|
+
z-index: -1;
|
|
205
|
+
border-radius: 50%;
|
|
206
|
+
transform: rotate(-2deg);
|
|
207
|
+
}
|
|
208
|
+
.lede {
|
|
209
|
+
font-size: 18px;
|
|
210
|
+
line-height: 1.7;
|
|
211
|
+
color: var(--muted);
|
|
212
|
+
max-width: 610px;
|
|
213
|
+
margin: 25px 0 36px;
|
|
214
|
+
}
|
|
215
|
+
.intro-art {
|
|
216
|
+
margin: 38px 0 54px;
|
|
217
|
+
border: 1px solid var(--line);
|
|
218
|
+
border-radius: 18px;
|
|
219
|
+
overflow: hidden;
|
|
220
|
+
background: white;
|
|
221
|
+
}
|
|
222
|
+
.intro-art svg {
|
|
223
|
+
width: 100%;
|
|
224
|
+
height: auto;
|
|
225
|
+
display: block;
|
|
226
|
+
}
|
|
227
|
+
.art-label {
|
|
228
|
+
display: flex;
|
|
229
|
+
justify-content: space-between;
|
|
230
|
+
padding: 12px 20px;
|
|
231
|
+
font-size: 11px;
|
|
232
|
+
color: var(--muted);
|
|
233
|
+
border-top: 1px solid var(--line);
|
|
234
|
+
letter-spacing: 0.4px;
|
|
235
|
+
}
|
|
236
|
+
.chapter {
|
|
237
|
+
border-top: 1px solid var(--line);
|
|
238
|
+
padding: 38px 0 34px;
|
|
239
|
+
}
|
|
240
|
+
.chapter:target h2 {
|
|
241
|
+
color: #007d65;
|
|
242
|
+
}
|
|
243
|
+
.number {
|
|
244
|
+
font-size: 11px;
|
|
245
|
+
color: #47766b;
|
|
246
|
+
letter-spacing: 1px;
|
|
247
|
+
font-weight: 700;
|
|
248
|
+
display: block;
|
|
249
|
+
margin-bottom: 10px;
|
|
250
|
+
}
|
|
251
|
+
h2 {
|
|
252
|
+
font-size: 29px;
|
|
253
|
+
line-height: 1.25;
|
|
254
|
+
letter-spacing: -0.8px;
|
|
255
|
+
margin: 0 0 20px;
|
|
256
|
+
}
|
|
257
|
+
h3 {
|
|
258
|
+
font-size: 18px;
|
|
259
|
+
margin: 28px 0 12px;
|
|
260
|
+
}
|
|
261
|
+
p {
|
|
262
|
+
margin: 14px 0;
|
|
263
|
+
}
|
|
264
|
+
.muted {
|
|
265
|
+
color: var(--muted);
|
|
266
|
+
}
|
|
267
|
+
code {
|
|
268
|
+
font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
|
|
269
|
+
font-size: 0.86em;
|
|
270
|
+
background: #e9efe9;
|
|
271
|
+
border-radius: 4px;
|
|
272
|
+
padding: 2px 5px;
|
|
273
|
+
overflow-wrap: anywhere;
|
|
274
|
+
}
|
|
275
|
+
.code {
|
|
276
|
+
position: relative;
|
|
277
|
+
margin: 22px 0;
|
|
278
|
+
}
|
|
279
|
+
pre {
|
|
280
|
+
white-space: pre;
|
|
281
|
+
overflow: auto;
|
|
282
|
+
max-width: 100%;
|
|
283
|
+
padding: 24px;
|
|
284
|
+
background: #16383b;
|
|
285
|
+
border-radius: 13px;
|
|
286
|
+
color: #e0f3e7;
|
|
287
|
+
font-size: 13px;
|
|
288
|
+
line-height: 1.85;
|
|
289
|
+
tab-size: 2;
|
|
290
|
+
}
|
|
291
|
+
pre code {
|
|
292
|
+
background: none;
|
|
293
|
+
padding: 0;
|
|
294
|
+
font-size: inherit;
|
|
295
|
+
overflow-wrap: normal;
|
|
296
|
+
}
|
|
297
|
+
.copy {
|
|
298
|
+
position: absolute;
|
|
299
|
+
right: 12px;
|
|
300
|
+
top: 12px;
|
|
301
|
+
border: 1px solid #68807b;
|
|
302
|
+
background: #24484a;
|
|
303
|
+
color: #e8f5eb;
|
|
304
|
+
padding: 5px 10px;
|
|
305
|
+
border-radius: 6px;
|
|
306
|
+
font: inherit;
|
|
307
|
+
font-size: 11px;
|
|
308
|
+
cursor: pointer;
|
|
309
|
+
}
|
|
310
|
+
.callout {
|
|
311
|
+
border-left: 3px solid var(--lilac);
|
|
312
|
+
padding: 3px 0 3px 19px;
|
|
313
|
+
margin: 24px 0;
|
|
314
|
+
color: #4c6560;
|
|
315
|
+
font-size: 14px;
|
|
316
|
+
}
|
|
317
|
+
.columns {
|
|
318
|
+
display: grid;
|
|
319
|
+
grid-template-columns: 1fr 1fr;
|
|
320
|
+
gap: 26px;
|
|
321
|
+
margin-top: 25px;
|
|
322
|
+
}
|
|
323
|
+
.columns h3 {
|
|
324
|
+
margin-top: 0;
|
|
325
|
+
}
|
|
326
|
+
.link-row {
|
|
327
|
+
display: flex;
|
|
328
|
+
flex-wrap: wrap;
|
|
329
|
+
gap: 12px;
|
|
330
|
+
margin-top: 22px;
|
|
331
|
+
}
|
|
332
|
+
.pill {
|
|
333
|
+
border: 1px solid var(--line);
|
|
334
|
+
border-radius: 8px;
|
|
335
|
+
padding: 9px 14px;
|
|
336
|
+
font-size: 13px;
|
|
337
|
+
text-decoration: none;
|
|
338
|
+
background: white;
|
|
339
|
+
}
|
|
340
|
+
table {
|
|
341
|
+
border-collapse: collapse;
|
|
342
|
+
width: 100%;
|
|
343
|
+
font-size: 14px;
|
|
344
|
+
margin: 20px 0;
|
|
345
|
+
}
|
|
346
|
+
td,
|
|
347
|
+
th {
|
|
348
|
+
text-align: left;
|
|
349
|
+
padding: 12px 0;
|
|
350
|
+
border-bottom: 1px solid var(--line);
|
|
351
|
+
vertical-align: top;
|
|
352
|
+
}
|
|
353
|
+
th {
|
|
354
|
+
font-size: 11px;
|
|
355
|
+
letter-spacing: 1px;
|
|
356
|
+
text-transform: uppercase;
|
|
357
|
+
color: var(--muted);
|
|
358
|
+
}
|
|
359
|
+
td:first-child {
|
|
360
|
+
width: 43%;
|
|
361
|
+
padding-right: 20px;
|
|
362
|
+
}
|
|
363
|
+
.shortcut-grid {
|
|
364
|
+
display: grid;
|
|
365
|
+
grid-template-columns: 1fr 1fr;
|
|
366
|
+
gap: 0 32px;
|
|
367
|
+
}
|
|
368
|
+
.shortcut {
|
|
369
|
+
display: flex;
|
|
370
|
+
justify-content: space-between;
|
|
371
|
+
border-bottom: 1px solid var(--line);
|
|
372
|
+
padding: 11px 0;
|
|
373
|
+
font-size: 14px;
|
|
374
|
+
}
|
|
375
|
+
kbd {
|
|
376
|
+
font:
|
|
377
|
+
12px ui-monospace,
|
|
378
|
+
monospace;
|
|
379
|
+
min-width: 25px;
|
|
380
|
+
text-align: center;
|
|
381
|
+
background: white;
|
|
382
|
+
border: 1px solid #d7e0da;
|
|
383
|
+
border-bottom-width: 2px;
|
|
384
|
+
border-radius: 5px;
|
|
385
|
+
padding: 2px 6px;
|
|
386
|
+
}
|
|
387
|
+
.foot {
|
|
388
|
+
border-top: 1px solid var(--line);
|
|
389
|
+
display: flex;
|
|
390
|
+
flex-direction: column;
|
|
391
|
+
gap: 12px;
|
|
392
|
+
padding-top: 24px;
|
|
393
|
+
margin-top: 20px;
|
|
394
|
+
font-size: 12px;
|
|
395
|
+
color: var(--muted);
|
|
396
|
+
}
|
|
397
|
+
.foot-row {
|
|
398
|
+
display: flex;
|
|
399
|
+
justify-content: space-between;
|
|
400
|
+
gap: 16px;
|
|
401
|
+
flex-wrap: wrap;
|
|
402
|
+
}
|
|
403
|
+
.foot a {
|
|
404
|
+
font-weight: 650;
|
|
405
|
+
}
|
|
406
|
+
.foot-note {
|
|
407
|
+
margin: 0;
|
|
408
|
+
max-width: 62ch;
|
|
409
|
+
overflow-wrap: anywhere;
|
|
410
|
+
}
|
|
411
|
+
@media (max-width: 900px) {
|
|
412
|
+
.shell {
|
|
413
|
+
gap: 35px;
|
|
414
|
+
grid-template-columns: 180px 1fr;
|
|
415
|
+
padding: 40px 25px;
|
|
416
|
+
}
|
|
417
|
+
.header-note {
|
|
418
|
+
display: none;
|
|
419
|
+
}
|
|
420
|
+
h1 {
|
|
421
|
+
font-size: 47px;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
@media (max-width: 650px) {
|
|
425
|
+
header {
|
|
426
|
+
height: 68px;
|
|
427
|
+
padding: 0 18px;
|
|
428
|
+
}
|
|
429
|
+
.brand {
|
|
430
|
+
font-size: 17px;
|
|
431
|
+
}
|
|
432
|
+
.brand svg {
|
|
433
|
+
width: 30px;
|
|
434
|
+
height: 30px;
|
|
435
|
+
}
|
|
436
|
+
.open {
|
|
437
|
+
padding: 9px 12px;
|
|
438
|
+
}
|
|
439
|
+
.shell {
|
|
440
|
+
display: block;
|
|
441
|
+
padding: 28px 20px 55px;
|
|
442
|
+
}
|
|
443
|
+
aside {
|
|
444
|
+
position: static;
|
|
445
|
+
margin-bottom: 30px;
|
|
446
|
+
}
|
|
447
|
+
aside p {
|
|
448
|
+
display: none;
|
|
449
|
+
}
|
|
450
|
+
nav {
|
|
451
|
+
display: flex;
|
|
452
|
+
overflow: auto;
|
|
453
|
+
padding-bottom: 12px;
|
|
454
|
+
gap: 5px;
|
|
455
|
+
}
|
|
456
|
+
nav a {
|
|
457
|
+
white-space: nowrap;
|
|
458
|
+
background: #edf3eb;
|
|
459
|
+
font-size: 12px;
|
|
460
|
+
}
|
|
461
|
+
nav .external {
|
|
462
|
+
display: none;
|
|
463
|
+
}
|
|
464
|
+
h1 {
|
|
465
|
+
font-size: clamp(28px, 10vw, 36px);
|
|
466
|
+
letter-spacing: -1.2px;
|
|
467
|
+
}
|
|
468
|
+
header .open {
|
|
469
|
+
flex: 0 0 auto;
|
|
470
|
+
}
|
|
471
|
+
nav {
|
|
472
|
+
max-width: 100%;
|
|
473
|
+
}
|
|
474
|
+
.lede {
|
|
475
|
+
font-size: 17px;
|
|
476
|
+
}
|
|
477
|
+
.columns {
|
|
478
|
+
grid-template-columns: 1fr;
|
|
479
|
+
gap: 8px;
|
|
480
|
+
}
|
|
481
|
+
.shortcut-grid {
|
|
482
|
+
grid-template-columns: 1fr;
|
|
483
|
+
}
|
|
484
|
+
pre {
|
|
485
|
+
padding: 22px 18px;
|
|
486
|
+
font-size: 11px;
|
|
487
|
+
}
|
|
488
|
+
.copy {
|
|
489
|
+
right: 8px;
|
|
490
|
+
top: 8px;
|
|
491
|
+
}
|
|
492
|
+
td:first-child {
|
|
493
|
+
width: 48%;
|
|
494
|
+
}
|
|
495
|
+
.intro-art {
|
|
496
|
+
margin: 30px 0 38px;
|
|
497
|
+
}
|
|
498
|
+
.art-label {
|
|
499
|
+
font-size: 9px;
|
|
500
|
+
padding: 10px 12px;
|
|
501
|
+
}
|
|
502
|
+
.foot {
|
|
503
|
+
gap: 20px;
|
|
504
|
+
}
|
|
505
|
+
.chapter {
|
|
506
|
+
padding: 30px 0;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
@media (prefers-reduced-motion: reduce) {
|
|
510
|
+
html {
|
|
511
|
+
scroll-behavior: auto;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
@media (prefers-color-scheme: dark) {
|
|
515
|
+
:root {
|
|
516
|
+
color-scheme: dark;
|
|
517
|
+
--paper: #122f32;
|
|
518
|
+
--ink: #e9f7f3;
|
|
519
|
+
--muted: #a2bcb5;
|
|
520
|
+
--line: #365451;
|
|
521
|
+
}
|
|
522
|
+
header {
|
|
523
|
+
background: #122f32ee;
|
|
524
|
+
}
|
|
525
|
+
.open {
|
|
526
|
+
background: #aaf1ac;
|
|
527
|
+
color: #103639;
|
|
528
|
+
}
|
|
529
|
+
.open:hover {
|
|
530
|
+
background: #c5f7c8;
|
|
531
|
+
color: #103639;
|
|
532
|
+
}
|
|
533
|
+
nav a:hover,
|
|
534
|
+
nav a.active {
|
|
535
|
+
background: #28524a;
|
|
536
|
+
color: #c6f7d6;
|
|
537
|
+
}
|
|
538
|
+
h1 span:after {
|
|
539
|
+
background: #39664c;
|
|
540
|
+
}
|
|
541
|
+
.intro-art {
|
|
542
|
+
background: #fcfdf9;
|
|
543
|
+
}
|
|
544
|
+
code {
|
|
545
|
+
background: #294745;
|
|
546
|
+
}
|
|
547
|
+
.pill,
|
|
548
|
+
kbd {
|
|
549
|
+
background: #1e4042;
|
|
550
|
+
color: #e9f7f3;
|
|
551
|
+
border-color: #456560;
|
|
552
|
+
}
|
|
553
|
+
.callout {
|
|
554
|
+
color: #b5c9c4;
|
|
555
|
+
}
|
|
556
|
+
.number {
|
|
557
|
+
color: #aaf1ac;
|
|
558
|
+
}
|
|
559
|
+
@media (max-width: 650px) {
|
|
560
|
+
nav a {
|
|
561
|
+
background: #254844;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
</style>
|
|
566
|
+
</head>
|
|
567
|
+
<body>
|
|
568
|
+
<a href="#content" class="skip">Skip to documentation</a>
|
|
569
|
+
<header>
|
|
570
|
+
<a class="brand" href="../"
|
|
571
|
+
><svg viewBox="0 0 36 36" fill="none" aria-hidden="true">
|
|
572
|
+
<rect width="36" height="36" rx="11" fill="#AAF1AC" />
|
|
573
|
+
<path
|
|
574
|
+
d="m10 25 6-15c.5-1.3 2.3-1.3 2.8 0L25 25M13 19h9"
|
|
575
|
+
stroke="#103639"
|
|
576
|
+
stroke-width="2.6"
|
|
577
|
+
stroke-linecap="round"
|
|
578
|
+
stroke-linejoin="round"
|
|
579
|
+
/>
|
|
580
|
+
<circle cx="26" cy="10" r="3" fill="#8F93F9" /></svg
|
|
581
|
+
>AnnieDrawing<span class="header-note">DOCUMENTATION</span></a
|
|
582
|
+
><a class="open" href="../">Open the demo</a>
|
|
583
|
+
</header>
|
|
584
|
+
<div class="shell">
|
|
585
|
+
<aside>
|
|
586
|
+
<p>Contents</p>
|
|
587
|
+
<nav aria-label="Documentation">
|
|
588
|
+
<a href="#install">Installation</a><a href="#embed">Embedding</a
|
|
589
|
+
><a href="#editor">Editor</a><a href="#api">API</a><a href="#agents">Agents</a
|
|
590
|
+
><a href="#format">Format and export</a><a href="#extensions">Extensions</a
|
|
591
|
+
><a href="#contribute">Contributing</a
|
|
592
|
+
><a class="external" href="board-js.md">Board JavaScript</a
|
|
593
|
+
><a class="external" href="llms-full.txt">Full AI reference</a>
|
|
594
|
+
</nav>
|
|
595
|
+
</aside>
|
|
596
|
+
<main id="content">
|
|
597
|
+
<div class="eyebrow"><span class="dot"></span> Manual</div>
|
|
598
|
+
<h1>AnnieDrawing documentation</h1>
|
|
599
|
+
<p class="lede">
|
|
600
|
+
AnnieDrawing is a TypeScript library that renders a drawing board in the browser with HTML
|
|
601
|
+
and SVG. The document is JSON. Saved edits go through <code>apply</code>. Frontierz
|
|
602
|
+
maintains the project. The license is MIT.
|
|
603
|
+
</p>
|
|
604
|
+
<p>
|
|
605
|
+
Detailed references are linked from each chapter. Install the library with
|
|
606
|
+
<code>npm install anniedrawing</code>.
|
|
607
|
+
</p>
|
|
608
|
+
<section class="chapter" id="install">
|
|
609
|
+
<span class="number">1</span>
|
|
610
|
+
<h2>Installation and the local demo</h2>
|
|
611
|
+
<p>
|
|
612
|
+
Developing this repository, installing it from git, and running the MCP example need
|
|
613
|
+
Node.js 24 or newer. The published library is ES2022. From a source checkout:
|
|
614
|
+
</p>
|
|
615
|
+
<div class="code">
|
|
616
|
+
<button class="copy" type="button" aria-label="Copy install commands">Copy</button>
|
|
617
|
+
<pre><code>npm ci
|
|
618
|
+
npm run dev</code></pre>
|
|
619
|
+
</div>
|
|
620
|
+
<p>
|
|
621
|
+
Vite listens on port 5173 by default. Open
|
|
622
|
+
<a href="../">http://127.0.0.1:5173</a> for the editor. If that port is taken, the
|
|
623
|
+
server prints the next free address. <code>npm run check</code> runs TypeScript, unit
|
|
624
|
+
tests, the library build, the gzipped size budget, dependency license review, and
|
|
625
|
+
production-dependency audit.
|
|
626
|
+
</p>
|
|
627
|
+
<p>
|
|
628
|
+
Hosts install with <code>npm install anniedrawing</code>. The library does not require a
|
|
629
|
+
UI framework, account, backend, or drawing canvas.
|
|
630
|
+
</p>
|
|
631
|
+
<p class="muted">
|
|
632
|
+
The demo stores the current drawing in the browser. Its Export control offers PNG, SVG,
|
|
633
|
+
and AnnieDoc. Export a <code>.annie</code> file for a portable copy. New files use
|
|
634
|
+
format version 2 and <code>pages</code>. Version 1 files with <code>sheets</code>
|
|
635
|
+
migrate on load.
|
|
636
|
+
</p>
|
|
637
|
+
</section>
|
|
638
|
+
<section class="chapter" id="embed">
|
|
639
|
+
<span class="number">2</span>
|
|
640
|
+
<h2>Embedding</h2>
|
|
641
|
+
<p>
|
|
642
|
+
Pass a sized host element to <code>createBoard</code> and keep the returned board
|
|
643
|
+
reference. Call <code>board.destroy()</code> when the host is removed.
|
|
644
|
+
</p>
|
|
645
|
+
<div class="code">
|
|
646
|
+
<button class="copy" type="button" aria-label="Copy board example">Copy</button>
|
|
647
|
+
<pre><code>import { createBoard } from 'anniedrawing'
|
|
648
|
+
import 'anniedrawing/style.css'
|
|
649
|
+
|
|
650
|
+
const board = createBoard(document.querySelector('#board'), {
|
|
651
|
+
theme: 'auto',
|
|
652
|
+
ui: {
|
|
653
|
+
menu: true,
|
|
654
|
+
export: ['png', 'svg'],
|
|
655
|
+
},
|
|
656
|
+
autosaveKey: 'my-drawing',
|
|
657
|
+
})
|
|
658
|
+
|
|
659
|
+
board.apply([{ op: 'add', item: {
|
|
660
|
+
kind: 'note', x: 120, y: 100,
|
|
661
|
+
text: { value: 'Note' },
|
|
662
|
+
style: { fill: 'moss' },
|
|
663
|
+
} }])
|
|
664
|
+
|
|
665
|
+
// When the host is removed:
|
|
666
|
+
// board.destroy()</code></pre>
|
|
667
|
+
</div>
|
|
668
|
+
<div class="callout">
|
|
669
|
+
The host must have nonzero width and height, for example
|
|
670
|
+
<code>#board { height: 600px; }</code>. Await <code>board.ready</code> before edits that
|
|
671
|
+
depend on restored autosave content. <code>theme</code> is <code>light</code> when
|
|
672
|
+
omitted, <code>dark</code>, or <code>auto</code> for the system.
|
|
673
|
+
<code>ui: false</code> omits editor chrome. <code>ui.menu</code> is the AnnieDrawing
|
|
674
|
+
control (default on). <code>ui.export</code> lists <code>png</code>, <code>svg</code>,
|
|
675
|
+
and <code>json</code> for AnnieDoc. An imported board defaults to PNG and SVG. This demo
|
|
676
|
+
also offers AnnieDoc.
|
|
677
|
+
</div>
|
|
678
|
+
<p>
|
|
679
|
+
For an embed next to a live agent, import <code>createFellowBoard</code> from
|
|
680
|
+
<code>anniedrawing/fellow</code>. It hides chrome, skips the global hook, skips unfurl,
|
|
681
|
+
keeps agent work off ordinary undo, and fits the camera to new agent items.
|
|
682
|
+
<code>createBoard</code> leaves <code>window.__anniedrawing</code> off unless
|
|
683
|
+
<code>exposeGlobal: true</code>. This demo sets that option so agents can find the
|
|
684
|
+
board.
|
|
685
|
+
</p>
|
|
686
|
+
<p>
|
|
687
|
+
For Node.js or workers, import <code>createDoc</code> from
|
|
688
|
+
<code>anniedrawing/core</code>. It exposes the same document operations without creating
|
|
689
|
+
DOM nodes. <code>board.changesSince(since)</code> and
|
|
690
|
+
<code>describe({ since })</code> return a session delta without re-reading the scene.
|
|
691
|
+
</p>
|
|
692
|
+
</section>
|
|
693
|
+
<section class="chapter" id="editor">
|
|
694
|
+
<span class="number">3</span>
|
|
695
|
+
<h2>Editor</h2>
|
|
696
|
+
<p>
|
|
697
|
+
The toolbar shows select, hand, eraser, then Shapes, draw, text, sticky note, and image.
|
|
698
|
+
Shapes contains rectangle, ellipse, diamond, line, and arrow. Drag to draw.
|
|
699
|
+
Double-click, or double-tap on a touchscreen, to write inside a shape or note. Press and
|
|
700
|
+
hold an item, or right-click it, for actions.
|
|
701
|
+
</p>
|
|
702
|
+
<p>
|
|
703
|
+
Use the hand tool or hold Space to pan. Zoom with the controls or a trackpad gesture.
|
|
704
|
+
Fit the view with <kbd>2</kbd>. Hold Shift to keep a resize proportional. Select an item
|
|
705
|
+
to open its inspector. Fill, Line, and Color choose colors. Line also sets thickness and
|
|
706
|
+
pattern. Text-capable shapes show size, alignment, and font. A selected video or link
|
|
707
|
+
card can change its URL from the inspector. More arrangement options opens align,
|
|
708
|
+
distribute, group, and stacking. Pages lists pages. The AnnieDrawing menu holds
|
|
709
|
+
appearance, documentation, GitHub, and the package version unless the host hides it.
|
|
710
|
+
This demo's Export control offers PNG, SVG, and AnnieDoc; an imported board defaults to
|
|
711
|
+
PNG and SVG.
|
|
712
|
+
</p>
|
|
713
|
+
<div class="shortcut-grid">
|
|
714
|
+
<div class="shortcut"><span>Select / move</span><kbd>V</kbd></div>
|
|
715
|
+
<div class="shortcut"><span>Sticky note</span><kbd>N</kbd></div>
|
|
716
|
+
<div class="shortcut"><span>Rectangle</span><kbd>R</kbd></div>
|
|
717
|
+
<div class="shortcut"><span>Text</span><kbd>T</kbd></div>
|
|
718
|
+
<div class="shortcut"><span>Connector</span><kbd>A</kbd></div>
|
|
719
|
+
<div class="shortcut"><span>Freehand</span><kbd>P</kbd></div>
|
|
720
|
+
<div class="shortcut"><span>Pan</span><kbd>Space + drag</kbd></div>
|
|
721
|
+
<div class="shortcut"><span>Fit drawing</span><kbd>2</kbd></div>
|
|
722
|
+
</div>
|
|
723
|
+
<p class="muted">The full keyboard table is in <a href="api.md">API reference</a>.</p>
|
|
724
|
+
</section>
|
|
725
|
+
<section class="chapter" id="api">
|
|
726
|
+
<span class="number">4</span>
|
|
727
|
+
<h2>Public API</h2>
|
|
728
|
+
<table>
|
|
729
|
+
<thead>
|
|
730
|
+
<tr>
|
|
731
|
+
<th>Read</th>
|
|
732
|
+
<th>Result</th>
|
|
733
|
+
</tr>
|
|
734
|
+
</thead>
|
|
735
|
+
<tbody>
|
|
736
|
+
<tr>
|
|
737
|
+
<td><code>board.read()</code></td>
|
|
738
|
+
<td>Deep JSON copy of the document</td>
|
|
739
|
+
</tr>
|
|
740
|
+
<tr>
|
|
741
|
+
<td><code>board.get(id)</code></td>
|
|
742
|
+
<td>One item, or <code>undefined</code></td>
|
|
743
|
+
</tr>
|
|
744
|
+
<tr>
|
|
745
|
+
<td><code>board.query({ kind: 'note' })</code></td>
|
|
746
|
+
<td>Items matching the filters (AND)</td>
|
|
747
|
+
</tr>
|
|
748
|
+
<tr>
|
|
749
|
+
<td><code>board.describe()</code></td>
|
|
750
|
+
<td>Deterministic text with IDs</td>
|
|
751
|
+
</tr>
|
|
752
|
+
<tr>
|
|
753
|
+
<td><code>board.kindsSince(since?)</code></td>
|
|
754
|
+
<td>Built-in kinds added or changed after that catalog version</td>
|
|
755
|
+
</tr>
|
|
756
|
+
</tbody>
|
|
757
|
+
</table>
|
|
758
|
+
<table>
|
|
759
|
+
<thead>
|
|
760
|
+
<tr>
|
|
761
|
+
<th>Write</th>
|
|
762
|
+
<th>Result</th>
|
|
763
|
+
</tr>
|
|
764
|
+
</thead>
|
|
765
|
+
<tbody>
|
|
766
|
+
<tr>
|
|
767
|
+
<td><code>board.apply(ops, options)</code></td>
|
|
768
|
+
<td>Validates and commits one atomic batch</td>
|
|
769
|
+
</tr>
|
|
770
|
+
<tr>
|
|
771
|
+
<td><code>board.undo()</code> / <code>redo()</code></td>
|
|
772
|
+
<td>Walks committed history</td>
|
|
773
|
+
</tr>
|
|
774
|
+
<tr>
|
|
775
|
+
<td><code>board.select(ids)</code></td>
|
|
776
|
+
<td>Selects items in the current view</td>
|
|
777
|
+
</tr>
|
|
778
|
+
<tr>
|
|
779
|
+
<td><code>board.view.fit(ids?)</code></td>
|
|
780
|
+
<td>Fits the camera to content or listed IDs</td>
|
|
781
|
+
</tr>
|
|
782
|
+
</tbody>
|
|
783
|
+
</table>
|
|
784
|
+
<p>
|
|
785
|
+
Operations include <code>add</code>, <code>set</code>, <code>remove</code>,
|
|
786
|
+
<code>order</code>, and <code>reparent</code>, plus page, media, and document metadata
|
|
787
|
+
changes. <code>place</code> takes exactly one of <code>rightOf</code>,
|
|
788
|
+
<code>leftOf</code>, <code>above</code>, <code>below</code>, <code>inside</code>, or
|
|
789
|
+
<code>near</code>. A dry run validates a batch without saving it. Failed batches apply
|
|
790
|
+
nothing.
|
|
791
|
+
</p>
|
|
792
|
+
<div class="link-row">
|
|
793
|
+
<a class="pill" href="api.md">API reference</a
|
|
794
|
+
><a class="pill" href="format.md">Document format</a>
|
|
795
|
+
</div>
|
|
796
|
+
</section>
|
|
797
|
+
<section class="chapter" id="agents">
|
|
798
|
+
<span class="number">5</span>
|
|
799
|
+
<h2>Agents</h2>
|
|
800
|
+
<p>
|
|
801
|
+
The document is JSON with stable item IDs. An agent can describe the scene, query items,
|
|
802
|
+
and apply a batch. Every batch succeeds together or changes nothing. This demo sets
|
|
803
|
+
<code>exposeGlobal: true</code> so the board is on <code>window.__anniedrawing</code>.
|
|
804
|
+
Other hosts must pass that option.
|
|
805
|
+
</p>
|
|
806
|
+
<div class="code">
|
|
807
|
+
<button class="copy" type="button" aria-label="Copy live agent example">Copy</button>
|
|
808
|
+
<pre><code>const board = window.__anniedrawing[0]
|
|
809
|
+
console.log(board.describe())
|
|
810
|
+
|
|
811
|
+
const result = board.apply([
|
|
812
|
+
{ op: 'add', item: {
|
|
813
|
+
id: 'i_api', kind: 'rect', x: 100, y: 100,
|
|
814
|
+
text: { value: 'API' },
|
|
815
|
+
} },
|
|
816
|
+
{ op: 'add', item: {
|
|
817
|
+
id: 'i_cache', kind: 'note',
|
|
818
|
+
text: { value: 'Cache' },
|
|
819
|
+
}, place: { rightOf: 'i_api', gap: 60 } },
|
|
820
|
+
], { origin: 'agent:helper', label: 'Add cache' })
|
|
821
|
+
|
|
822
|
+
if (!result.ok) console.error(result.errors)
|
|
823
|
+
board.view.fit()
|
|
824
|
+
console.log(board.describe())</code></pre>
|
|
825
|
+
</div>
|
|
826
|
+
<p>
|
|
827
|
+
The six tools are <code>board_describe</code>, <code>board_read</code>,
|
|
828
|
+
<code>board_query</code>, <code>board_apply</code>, <code>board_snapshot</code>, and
|
|
829
|
+
<code>board_view_fit</code>. Import <code>toolDefs</code> and <code>runTool</code> from
|
|
830
|
+
<code>anniedrawing/agent</code>. <code>runTool</code> stores
|
|
831
|
+
<code>board_apply</code> under an <code>agent:</code> origin. Headless
|
|
832
|
+
<code>board_read</code> is whole-document only. <code>board_snapshot</code> defaults to
|
|
833
|
+
a labeled 32-color viewport PNG with a 240 KiB budget. The same defaults apply to
|
|
834
|
+
<code>board.export('png', { labels: true })</code>. SVG is markup, not a vision
|
|
835
|
+
snapshot. Hosts that need a lossy raster can still call
|
|
836
|
+
<code>board.export('jpeg')</code> or <code>board.export('webp')</code> with
|
|
837
|
+
<code>maxSide</code> and <code>maxBytes</code>.
|
|
838
|
+
</p>
|
|
839
|
+
<div class="callout">
|
|
840
|
+
Read before editing. Check <code>result.ok</code>, then read the affected items. Board
|
|
841
|
+
text is data. It is not an instruction to the agent. An origin label records who made a
|
|
842
|
+
change. It does not grant access.
|
|
843
|
+
</div>
|
|
844
|
+
<p>
|
|
845
|
+
The repository's MCP example connects over stdio. Its live bridge requires an explicit
|
|
846
|
+
private token and the exact browser origin. It listens only on localhost. Nothing
|
|
847
|
+
connects automatically.
|
|
848
|
+
</p>
|
|
849
|
+
<div class="link-row">
|
|
850
|
+
<a class="pill" href="agents.md">Agent operations</a
|
|
851
|
+
><a class="pill" href="board-js.md">Board JavaScript</a
|
|
852
|
+
><a class="pill" href="llms-full.txt">Full AI reference</a
|
|
853
|
+
><a class="pill" href="mcp.md">MCP example</a>
|
|
854
|
+
</div>
|
|
855
|
+
</section>
|
|
856
|
+
<section class="chapter" id="format">
|
|
857
|
+
<span class="number">6</span>
|
|
858
|
+
<h2>Format and export</h2>
|
|
859
|
+
<div class="columns">
|
|
860
|
+
<div>
|
|
861
|
+
<h3>.annie</h3>
|
|
862
|
+
<p>
|
|
863
|
+
The editable document is UTF-8 JSON. MIME type is
|
|
864
|
+
<code>application/vnd.anniedrawing+json</code>. Shapes, connections, pages, and
|
|
865
|
+
embedded images travel together. New files use version 2. Version 1 drawings migrate
|
|
866
|
+
when opened. Notes and cards use a 12px corner. <code>fillMode</code> is
|
|
867
|
+
<code>solid</code>, <code>tint</code>, or <code>hatch</code>.
|
|
868
|
+
</p>
|
|
869
|
+
</div>
|
|
870
|
+
<div>
|
|
871
|
+
<h3>SVG and PNG</h3>
|
|
872
|
+
<p>
|
|
873
|
+
The Export control downloads the current page. An imported board offers PNG and SVG;
|
|
874
|
+
pass <code>ui.export</code> with <code>json</code> to add AnnieDoc, or
|
|
875
|
+
<code>false</code> to hide Export. SVG is vector. PNG downloads stay truecolor at 2×
|
|
876
|
+
resolution. Pass <code>labels: true</code> and <code>colors: 32</code> when a vision
|
|
877
|
+
model needs item IDs in a compact image. Programmatic <code>board.export</code>
|
|
878
|
+
accepts JSON, SVG, PNG, JPEG, and WebP.
|
|
879
|
+
</p>
|
|
880
|
+
</div>
|
|
881
|
+
</div>
|
|
882
|
+
<div class="code">
|
|
883
|
+
<button class="copy" type="button" aria-label="Copy export example">Copy</button>
|
|
884
|
+
<pre><code>const editable = await board.export('json', { scope: 'doc' })
|
|
885
|
+
const vector = await board.export('svg', { padding: 32 })
|
|
886
|
+
const image = await board.export('png', {
|
|
887
|
+
scope: 'viewport', scale: 2, labels: true, colors: 32, maxBytes: 245760,
|
|
888
|
+
})
|
|
889
|
+
const compact = await board.export('jpeg', { maxSide: 1280, maxBytes: 245760 })</code></pre>
|
|
890
|
+
</div>
|
|
891
|
+
<p class="muted">
|
|
892
|
+
Browser storage is not a backup service. Remote images are subject to CORS. Custom HTML
|
|
893
|
+
cannot be assumed to rasterize identically across browsers. Custom kinds can supply
|
|
894
|
+
their own SVG output.
|
|
895
|
+
</p>
|
|
896
|
+
</section>
|
|
897
|
+
<section class="chapter" id="extensions">
|
|
898
|
+
<span class="number">7</span>
|
|
899
|
+
<h2>Extensions</h2>
|
|
900
|
+
<div class="columns">
|
|
901
|
+
<div>
|
|
902
|
+
<h3>Custom kinds</h3>
|
|
903
|
+
<p>
|
|
904
|
+
Register a kind with appearance, geometry, and optional editing handles. The same
|
|
905
|
+
definition can paint the live board and emit portable SVG. Keep callbacks in
|
|
906
|
+
application code. The file stores the kind name and JSON fields only.
|
|
907
|
+
</p>
|
|
908
|
+
</div>
|
|
909
|
+
<div>
|
|
910
|
+
<h3>HTML</h3>
|
|
911
|
+
<p>
|
|
912
|
+
Pass an explicit sanitizer when the application needs HTML content. Identity
|
|
913
|
+
functions are rejected. Plain text never goes through HTML parsing. A sanitizer is
|
|
914
|
+
not a sandbox. Opening a drawing never loads an executable callback.
|
|
915
|
+
</p>
|
|
916
|
+
</div>
|
|
917
|
+
</div>
|
|
918
|
+
<a class="pill" href="extensions.md">Extension reference</a>
|
|
919
|
+
</section>
|
|
920
|
+
<section class="chapter" id="contribute">
|
|
921
|
+
<span class="number">8</span>
|
|
922
|
+
<h2>Contributing and release</h2>
|
|
923
|
+
<p>
|
|
924
|
+
AnnieDrawing is an independent MIT-licensed project by Frontierz. Contributions must be
|
|
925
|
+
original. Keep the headless model free of DOM access. Commit through operations. Include
|
|
926
|
+
a DCO sign-off on commits.
|
|
927
|
+
</p>
|
|
928
|
+
<div class="code">
|
|
929
|
+
<button class="copy" type="button" aria-label="Copy verification commands">Copy</button>
|
|
930
|
+
<pre><code>npm run check
|
|
931
|
+
npm run build:demo
|
|
932
|
+
npx playwright install chromium firefox webkit
|
|
933
|
+
npm run test:e2e
|
|
934
|
+
npm run test:perf</code></pre>
|
|
935
|
+
</div>
|
|
936
|
+
<p>
|
|
937
|
+
Report vulnerabilities and conduct concerns privately to
|
|
938
|
+
<a href="mailto:pau@frontierz.com">pau@frontierz.com</a>. Do not file security reports
|
|
939
|
+
as public issues. Publication to npm remains a maintainer action.
|
|
940
|
+
</p>
|
|
941
|
+
<div class="link-row">
|
|
942
|
+
<a class="pill" href="contributing.md">Contributing</a
|
|
943
|
+
><a class="pill" href="decisions.md">Design decisions</a
|
|
944
|
+
><a class="pill" href="releasing.md">Release checklist</a
|
|
945
|
+
><a class="pill" href="security.md">Security</a
|
|
946
|
+
><a class="pill" href="notice.txt">Licenses and credits</a>
|
|
947
|
+
</div>
|
|
948
|
+
</section>
|
|
949
|
+
<footer class="foot">
|
|
950
|
+
<div class="foot-row">
|
|
951
|
+
<span>AnnieDrawing documentation. MIT license.</span><a href="../">Back to the demo</a>
|
|
952
|
+
</div>
|
|
953
|
+
<p class="foot-note">
|
|
954
|
+
Pau, a member of the Frontierz core team, developed AnnieDrawing after a bet with Annie,
|
|
955
|
+
who was also at Frontierz: he said he could spend one weekend building an editor that
|
|
956
|
+
Frontierz and the AI Fellows could use, and that he would name it AnnieDrawing. He wrote
|
|
957
|
+
that editor over the weekend.
|
|
958
|
+
</p>
|
|
959
|
+
</footer>
|
|
960
|
+
</main>
|
|
961
|
+
</div>
|
|
962
|
+
<script>
|
|
963
|
+
document.querySelectorAll('.copy').forEach((button) => {
|
|
964
|
+
button.addEventListener('click', async () => {
|
|
965
|
+
const text = button.parentElement.querySelector('code').textContent;
|
|
966
|
+
try {
|
|
967
|
+
await navigator.clipboard.writeText(text);
|
|
968
|
+
button.textContent = 'Copied';
|
|
969
|
+
setTimeout(() => (button.textContent = 'Copy'), 1600);
|
|
970
|
+
} catch {
|
|
971
|
+
button.textContent = 'Select the code';
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
});
|
|
975
|
+
const links = [...document.querySelectorAll('nav a[href^="#"]')];
|
|
976
|
+
const observer = new IntersectionObserver(
|
|
977
|
+
(entries) => {
|
|
978
|
+
for (const entry of entries)
|
|
979
|
+
if (entry.isIntersecting) {
|
|
980
|
+
links.forEach((link) => {
|
|
981
|
+
const active = link.hash === '#' + entry.target.id;
|
|
982
|
+
link.classList.toggle('active', active);
|
|
983
|
+
if (active) link.setAttribute('aria-current', 'location');
|
|
984
|
+
else link.removeAttribute('aria-current');
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
},
|
|
988
|
+
{ rootMargin: '-20% 0px -65% 0px' },
|
|
989
|
+
);
|
|
990
|
+
document.querySelectorAll('.chapter').forEach((section) => observer.observe(section));
|
|
991
|
+
</script>
|
|
992
|
+
</body>
|
|
993
|
+
</html>
|