@daydreamui/paper 0.0.0-stage → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +277 -2
- package/dist/bridge.js +7278 -0
- package/dist/index.js +582 -0
- package/icon.svg +8 -0
- package/manifest.json +33 -0
- package/package.json +15 -4
package/README.md
CHANGED
|
@@ -1,3 +1,278 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Paper
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A local Daydream plugin that puts what is open in Paper desktop on the
|
|
4
|
+
canvas. The design stays in Paper; Daydream takes an image of it, or
|
|
5
|
+
converts it into a page of the project, and lets any agent connected to
|
|
6
|
+
Daydream read Paper through eight tools. Paper's export is HTML and CSS in
|
|
7
|
+
all but syntax, so Add as page is a converter and not a prompt: no agent
|
|
8
|
+
is asked, and the page lands in seconds. There is no plugin inside Paper.
|
|
9
|
+
Enable **Paper** in Daydream's Plugins page (⌥⌘P).
|
|
10
|
+
|
|
11
|
+
From this repository, install the plugin with:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pnpm install
|
|
15
|
+
pnpm ship plugins/daydream.paper --enable
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The build produces `plugins/daydream.paper/dist/index.js`. The install command
|
|
19
|
+
copies the plugin into the user's Daydream plugins folder and records its trust.
|
|
20
|
+
|
|
21
|
+
## Requirements
|
|
22
|
+
|
|
23
|
+
- Paper desktop, open on this machine, with the file you want to read open
|
|
24
|
+
in it. The plugin reads the file you are viewing.
|
|
25
|
+
- Nothing to turn on in Paper, and no paid seat: Paper serves its MCP server
|
|
26
|
+
on this machine, and the plugin reads it at `http://127.0.0.1:29979/mcp`.
|
|
27
|
+
|
|
28
|
+
What leaves the machine, and what does not. Paper is read locally, and the
|
|
29
|
+
project is never sent anywhere. The image fills a page uses are downloaded
|
|
30
|
+
from Paper's asset host (`app.paper.design` only; a fill served from
|
|
31
|
+
anywhere else is not downloaded, stays a url in the page's sheet and is
|
|
32
|
+
warned about). And a converted page links Google Fonts for the file's
|
|
33
|
+
font families that are not system fonts, one `<link>` per family, so
|
|
34
|
+
opening that page, on the canvas or anywhere, asks `fonts.googleapis.com`
|
|
35
|
+
for them when it renders. The weights a link asks for (and the italic, when
|
|
36
|
+
a node uses one) are the ones the page uses, read from its nodes' styles
|
|
37
|
+
and the tokens they refer to, because Google refuses a range for a static
|
|
38
|
+
family; a weight a static family lacks is the one case in which the link
|
|
39
|
+
still fails, and the page shows that font's fallback.
|
|
40
|
+
|
|
41
|
+
The panel's first line says what Paper answers, probed with one call of
|
|
42
|
+
the host part (the selection's read, which carries the file's name) when
|
|
43
|
+
the panel opens, when a project is opened and when the window comes to the
|
|
44
|
+
front. It
|
|
45
|
+
shows one of these, always in sentence case:
|
|
46
|
+
|
|
47
|
+
- "Looking for Paper desktop…" until the first probe answers.
|
|
48
|
+
- "Paper is not reachable: open Paper desktop with the file you want to
|
|
49
|
+
read" when Paper is closed or its server is off. Each gesture answers the
|
|
50
|
+
same sentence.
|
|
51
|
+
- `Amazing jewel · 3 selected`, the file you are viewing and how many nodes
|
|
52
|
+
are selected in it.
|
|
53
|
+
- `Amazing jewel · nothing selected`.
|
|
54
|
+
|
|
55
|
+
## The two gestures
|
|
56
|
+
|
|
57
|
+
Both take what is selected in Paper, and nothing else: one artboard, or
|
|
58
|
+
several, up to 12 at once (past that, each gesture refuses in one sentence
|
|
59
|
+
naming the cap). There is nothing to type; select in Paper, press here.
|
|
60
|
+
Each begins by reading the selection, and each kind of answer gets its own
|
|
61
|
+
sentence: nothing selected ("Select an artboard in Paper first."), Paper
|
|
62
|
+
not there (or refusing, in its own sentence), or Paper too slow to answer
|
|
63
|
+
("Paper took too long to answer; try again.").
|
|
64
|
+
|
|
65
|
+
1. **Add as image** takes each node's screenshot by its id, copies it into
|
|
66
|
+
the project's `assets/` (named by its bytes, so the same node twice is
|
|
67
|
+
one file), and lands it on the canvas as a `daydream.paper.reference`
|
|
68
|
+
item at free space, selected and brought into view, as one undo step.
|
|
69
|
+
Its title bar carries the node's name, as the selection listed it, and
|
|
70
|
+
renames it; nothing is drawn under the image. A screenshot wider than
|
|
71
|
+
1200 px lands at that width; a resize keeps the image's proportions,
|
|
72
|
+
and a double-click on a handle resets it. The payload is
|
|
73
|
+
`{src, name, nodeId}`: `src` a file of the project's own
|
|
74
|
+
(`assets/<file>`), `name` the node's, `nodeId` Paper's id. With several
|
|
75
|
+
nodes selected, one screenshot is taken per node and every image lands
|
|
76
|
+
in one row from free space, each 40 px right of the last, side by side
|
|
77
|
+
to compare, all selected, as one undo step; a node whose screenshot
|
|
78
|
+
Paper refuses is left out and named in the error line while the others
|
|
79
|
+
land.
|
|
80
|
+
2. **Add as page** converts each selected artboard into a page of the
|
|
81
|
+
project and lands it on the canvas, in the selection's order, with no
|
|
82
|
+
agent in between. For each artboard Daydream reads its tree, its
|
|
83
|
+
computed styles, each SVG's markup and the file's tokens from Paper,
|
|
84
|
+
writes the files under What lands, and lands the page as a viewport as
|
|
85
|
+
wide as the artboard. The status says `Added <name> as a page.` or `Added 3 pages:
|
|
86
|
+
Garden, Archive, Notes.`; the error line carries what the conversion
|
|
87
|
+
warned of, the remote files that stayed links, and any artboard that
|
|
88
|
+
failed while the others landed.
|
|
89
|
+
|
|
90
|
+
What the page is: faithful and plain. Every text is a `p`; every box is
|
|
91
|
+
a `div` with a class named after its Paper layer (a layer with a
|
|
92
|
+
default name, such as `Frame`, gets `<type>-<n>`, and every Text node
|
|
93
|
+
gets `text-<n>` whatever its layer is called); an SVG is
|
|
94
|
+
its markup with the class on the root; flex and absolute layout are as
|
|
95
|
+
Paper has them, the width is fixed at the artboard's, and there are no
|
|
96
|
+
media queries; the sheet sets `box-sizing: border-box` on everything,
|
|
97
|
+
as Paper does (its computed styles leave it out). Tokens stay
|
|
98
|
+
`var(--color-ink)`. Every element carries
|
|
99
|
+
`data-paper="<id>"`, the Paper node it came from. Making it semantic
|
|
100
|
+
(headings, lists, landmarks, a layout that flows) is a rework of a page
|
|
101
|
+
already on the canvas, afterwards, which an agent or the Impeccable
|
|
102
|
+
verbs do; the converter does not guess it.
|
|
103
|
+
|
|
104
|
+
### What lands
|
|
105
|
+
|
|
106
|
+
Add as page, and the `paper_page` tool, write these files at the project's
|
|
107
|
+
root:
|
|
108
|
+
|
|
109
|
+
- `<stem>.css`: the page's sheet. The stem is the artboard's name made
|
|
110
|
+
file-safe (`CSS Zen Garden` becomes `css-zen-garden`), with `-2`, `-3` and on
|
|
111
|
+
while `<stem>.html` or `<stem>.css` is taken.
|
|
112
|
+
- `<file>-tokens.css`: the Paper file's design tokens as a `:root {}`
|
|
113
|
+
sheet, named after the file (`amazing-jewel-tokens.css`), shared by every
|
|
114
|
+
page of that file. It is rebuilt from Paper's tokens, each passed through
|
|
115
|
+
the same guard as the page's styles (a value that would end its rule, or
|
|
116
|
+
load from somewhere a page may not, is left out and named). The
|
|
117
|
+
project's copy is never replaced. It is
|
|
118
|
+
**written** when absent; **kept** when it is there with Paper's text
|
|
119
|
+
already; **differs** when it is there with other text, in which case it
|
|
120
|
+
is kept as it is, the page links it as it is, and the error line says
|
|
121
|
+
"the project's tokens sheet differs from Paper's tokens and was kept";
|
|
122
|
+
and **none** when the file has no tokens, in which case the page links no
|
|
123
|
+
tokens sheet and nothing is written.
|
|
124
|
+
- `assets/paper-<name>-<hash>.<ext>`: each image fill the page uses,
|
|
125
|
+
downloaded from Paper's asset host and named from the whole url (the
|
|
126
|
+
last part of its path, then the first eight hex digits of the url's
|
|
127
|
+
sha256, then the extension the download's content type gives: a fill
|
|
128
|
+
served at a `.html` url that is a PNG is saved as a `.png`), so two
|
|
129
|
+
images from different places never share a file; one
|
|
130
|
+
already there is the same url's and is kept, one that cannot be
|
|
131
|
+
downloaded stays a url and is named in the error line.
|
|
132
|
+
- `<stem>.html`: the page itself, written by Daydream's `createPage` and
|
|
133
|
+
not by the host part, at the path the host chose (`<stem>.html`, `-2` and
|
|
134
|
+
on). Landing it and placing its viewport at the artboard's size is one
|
|
135
|
+
undo step; an undo takes the viewport off and leaves the files, as it
|
|
136
|
+
does for every page Daydream makes.
|
|
137
|
+
|
|
138
|
+
Add as page and the `paper_page` tool are one call of the host part,
|
|
139
|
+
`paper-page`: it reads Paper, writes the files, asks the browser part to
|
|
140
|
+
land the html (`land-page`) and, when that fails, takes its own files back
|
|
141
|
+
before it answers. A page is therefore either landed, with its path and
|
|
142
|
+
viewport, or a rejection that says what became of its files. A landing
|
|
143
|
+
that fails takes back what the call wrote, in three cases and no other.
|
|
144
|
+
|
|
145
|
+
- The host part's own write fails or is late: the call takes back what it
|
|
146
|
+
had written before it answers, and the failure names the cause.
|
|
147
|
+
- `createPage` rejects the page (its path was taken meanwhile, there is no
|
|
148
|
+
room): the host part removes the call's own files — the sheet, the
|
|
149
|
+
tokens sheet if this call wrote it, the assets this call wrote — each
|
|
150
|
+
only while it still holds the bytes the call wrote and no other page
|
|
151
|
+
uses it. The error line follows the failure with one of four sentences,
|
|
152
|
+
by what became of them:
|
|
153
|
+
- "It had written no files." when the call had written none;
|
|
154
|
+
- "The files it had written were removed: a.css, amazing-jewel-tokens.css."
|
|
155
|
+
when all went;
|
|
156
|
+
- "Of the files it had written, a.css was removed and
|
|
157
|
+
assets/paper-3f2a-1c9e04ab.jpg stayed, edited since or used by another page."
|
|
158
|
+
when some stayed, both lists named;
|
|
159
|
+
- "It could not take them back: a.css, assets/paper-3f2a-1c9e04ab.jpg." when
|
|
160
|
+
neither list says anything (files already gone), with no cause guessed at.
|
|
161
|
+
|
|
162
|
+
If the removal itself fails, the line says "Its files could not be
|
|
163
|
+
removed (<why>) and stayed: …".
|
|
164
|
+
|
|
165
|
+
- The canvas answers neither way and the page's html exists as Daydream
|
|
166
|
+
was given it (Daydream wrote it, so the page may be there), or the
|
|
167
|
+
project changed meanwhile: nothing is taken back, and the sentence says
|
|
168
|
+
the files were kept.
|
|
169
|
+
|
|
170
|
+
When the project changed after Paper was read, the files stay in the
|
|
171
|
+
project they were written to, and nothing more is done.
|
|
172
|
+
|
|
173
|
+
## The agent tools
|
|
174
|
+
|
|
175
|
+
The host part registers eight MCP tools, so any agent connected to Daydream
|
|
176
|
+
reads Paper through it with no Paper setup of its own. Each reads Paper
|
|
177
|
+
only, and answers one sentence as an error result when Paper does not
|
|
178
|
+
answer. A `fileId` left out is the file you are viewing. The reads are
|
|
179
|
+
marked read-only; `paper_screenshot` and `paper_page` are not, since they
|
|
180
|
+
write into the project.
|
|
181
|
+
|
|
182
|
+
| Tool | Takes | Answers |
|
|
183
|
+
| ------------------ | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
184
|
+
| `paper_info` | optional `fileId` | the file: its id and name, its pages, its artboards with their sizes, its font families, its tokens |
|
|
185
|
+
| `paper_selection` | none | what is selected in Paper: each node's id, name, type and size, with the file they are in |
|
|
186
|
+
| `paper_tree` | `nodeId`, optional `fileId`, optional `depth` (3 by default, at most 10) | the node's subtree as Paper's indented summary: type, layer name, id, size, and a text node's text |
|
|
187
|
+
| `paper_styles` | `nodeIds[]` (at most 500), optional `fileId` | the computed CSS of the nodes, batched: camelCase properties with units, tokens kept as `var(--name)` |
|
|
188
|
+
| `paper_jsx` | `nodeId`, optional `fileId`, optional `format` (`inline-styles` by default, or `tailwind`) | the node as JSX; how an SVG's markup is read |
|
|
189
|
+
| `paper_tokens` | optional `fileId`, optional `format` (`css` by default, or `json`) | the file's design tokens, as a `:root {}` stylesheet or structured |
|
|
190
|
+
| `paper_screenshot` | `nodeId`, optional `fileId` | the node's image as Paper sends it (JPEG today), written into the open project's `.daydream/paper/<node>.jpg` and answered as that path |
|
|
191
|
+
| `paper_page` | `nodeId`, optional `fileId` | the conversion Add as page runs, for the node: the files above written and the page landed on the canvas; the answer names the page's path and its viewport, and any remote file the canvas could not copy |
|
|
192
|
+
|
|
193
|
+
A tool's result cannot return an image, so a screenshot is a file in the
|
|
194
|
+
project's `.daydream/` scratch, never through a link, for the agent to read
|
|
195
|
+
with its own file tools. `paper_page` has the page landed by
|
|
196
|
+
the browser part, so it needs Daydream open on the project in a tab.
|
|
197
|
+
|
|
198
|
+
## What is not done
|
|
199
|
+
|
|
200
|
+
- No plugin inside Paper: Daydream reads Paper through Paper's own server
|
|
201
|
+
and adds nothing to Paper.
|
|
202
|
+
- No write-back: nothing changes in Paper, ever. A page edited in Daydream
|
|
203
|
+
does not go back to its artboard.
|
|
204
|
+
- No re-sync: a page converted once is the project's own file. Add as page
|
|
205
|
+
again makes a second page (`-2`) beside it; it does not update the first
|
|
206
|
+
from an artboard that changed.
|
|
207
|
+
- No files on disk: only the file open in Paper desktop is read, through
|
|
208
|
+
its server.
|
|
209
|
+
- No shared package with the Figma plugin yet. The transport and the probe
|
|
210
|
+
are copies of `packages/figma-devmode`'s and the unreachable sentence
|
|
211
|
+
follows its pattern; the client's session core, `land.ts` (the page half
|
|
212
|
+
is new) and `ReferenceItem.tsx` are adapted from the Figma package's and
|
|
213
|
+
plugin's. Each is marked as such at the top with the commit it was taken
|
|
214
|
+
at; the file-writing helpers (`bridge/files.ts`) follow the
|
|
215
|
+
Figma bridge's care and carry only the `mirrors-adapted` marker for its
|
|
216
|
+
`.daydream/` gitignore. One shared package is the follow-up.
|
|
217
|
+
- No semantic markup and no responsive rules (above).
|
|
218
|
+
|
|
219
|
+
## Limits
|
|
220
|
+
|
|
221
|
+
- One file at a time: the one you are viewing in Paper desktop. Another
|
|
222
|
+
file's nodes are read by giving a tool its `fileId`; the panel always
|
|
223
|
+
takes the file in view.
|
|
224
|
+
- Up to 12 nodes per gesture: a screenshot or a conversion each is a round
|
|
225
|
+
trip to Paper.
|
|
226
|
+
- The selection's listing is read under 5 s of its own: past that the
|
|
227
|
+
gesture says Paper was too slow, and nothing is asked further.
|
|
228
|
+
- A request to Paper is given 20 s and one call of the client — its
|
|
229
|
+
handshake, a session opened again and the retry included — 45 s in all,
|
|
230
|
+
under the 50 s the kernel allows a host-part call, so what the panel
|
|
231
|
+
hears is the client's sentence and never the kernel's. A large artboard's
|
|
232
|
+
conversion reads its styles 100 nodes at a time and may come near that.
|
|
233
|
+
- The page call has one budget, 45 s, for the whole of it: the reads, the
|
|
234
|
+
downloads, the writes and the landing, the panel's call and the
|
|
235
|
+
`paper_page` tool's alike, so it ends under the 50 s the kernel allows a
|
|
236
|
+
host-part call. Past it before the writes, the sentence is "Converting
|
|
237
|
+
<name> took longer than 45 s; nothing was written". The landing is given
|
|
238
|
+
what is left of the budget; when the canvas has not answered by then the
|
|
239
|
+
call is rejected with "<name> was converted, but the canvas did not answer
|
|
240
|
+
in time; its files were kept: …" and nothing is taken back, since the page
|
|
241
|
+
may still land.
|
|
242
|
+
- A call's writes are remembered for ten minutes, so the rollback of one
|
|
243
|
+
page never removes a file another page of that time uses; a host restart
|
|
244
|
+
forgets them.
|
|
245
|
+
- An agent calling `paper_page` while the panel lands pages may find an
|
|
246
|
+
asset or the tokens sheet shared between two pages. A rollback never
|
|
247
|
+
removes a file another live call's page uses; it names it as one that
|
|
248
|
+
stayed.
|
|
249
|
+
- A Text node whose text holds a line break cannot be read from Paper's
|
|
250
|
+
tree summary today (whether Paper escapes it is unverified), and fails
|
|
251
|
+
the conversion with a sentence naming the node.
|
|
252
|
+
- Shader and effect nodes (a lens distortion, say) have no HTML: they land
|
|
253
|
+
as plain `div`s and the conversion warns, naming the node.
|
|
254
|
+
- A node selected inside an SVG is refused with a sentence; select the SVG
|
|
255
|
+
itself, or its artboard.
|
|
256
|
+
- An artboard on a page other than the one Paper shows takes the shown
|
|
257
|
+
page's font list, so a font used only there is not linked.
|
|
258
|
+
- Images a page uses are downloaded once into `assets/`; a fill served
|
|
259
|
+
from anywhere but Paper's asset host, or one whose download fails, stays
|
|
260
|
+
a url, and that part of the page works only while that address does.
|
|
261
|
+
- The width is the artboard's. A page converted from a 1440 px artboard
|
|
262
|
+
does not reflow below that.
|
|
263
|
+
|
|
264
|
+
## Validation
|
|
265
|
+
|
|
266
|
+
`pnpm test` runs the shared parts (the payload rules, the channel answers'
|
|
267
|
+
shapes, the sentences), the gestures over a fake `dd` (the selection's
|
|
268
|
+
kinds, several nodes, a node refused among several, the pages landed with
|
|
269
|
+
their path and frame, the project changing under a gesture), and the host
|
|
270
|
+
part and the package's converter over their fixtures. `pnpm test:kernel
|
|
271
|
+
<daydream-checkout> plugins/daydream.paper` mounts the real shell with
|
|
272
|
+
host-part replies in memory: the state line in its states, an image landed
|
|
273
|
+
and selected with its file copied, three nodes in a row, nothing selected,
|
|
274
|
+
the unreachable sentence, Add as page landing a page at the artboard's
|
|
275
|
+
frame, one of three refused while two land, a landing the shell refuses
|
|
276
|
+
having its files taken back by the host part, and the handler the host's `paper_page` tool
|
|
277
|
+
lands its page through. The plugin requires a Daydream build reporting API 3.0. See the
|
|
278
|
+
repository’s kernel pin and release gate before shipping.
|