Skip to content

Pixelwright 0.3.2 - #5

Merged
maximwas merged 8 commits into
mainfrom
develop
Oct 17, 2026
Merged

maximwas merged 8 commits into
mainfrom
develop

Conversation

@maximwas

Copy link
Copy Markdown
Owner

Pixelwright 0.3.2: fixes found while building designs from scratch with design_apply, and a banner in the plugin window when a newer version is out.

Added

  • The plugin's window says when a newer Pixelwright is out, with links to what is new and to the steps to update. Closed, it stays closed until the next version. The server asks npm once a day; PIXELWRIGHT_NO_UPDATE_CHECK=1 turns that off, and the plugin itself never goes online.

Fixed

  • design_apply answers x/y and Figma's own names with the CSS that writes them, and takes a bare number as px.
  • A new text that fills its row takes the row's width; border-top and the other single sides draw on a new frame.
  • src on a shape or a frame points to background="url(…)", which fills any layer with a picture.
  • screenshot with a clip on a layer too big to render whole renders the opaque layer holding the region.
  • Colour variables with transparency read as the token alone and are written at the opacity asked.
  • tokens_apply says a mode past the plan's limit in plain words.

The full list is in CHANGELOG.md under 0.3.2.

Checked:

  • 1024 unit tests, lint, typecheck, check:pack (0.3.2, 34 tools) and the docs build pass.
  • In Figma: the filling text, the single border side, colour variables with transparency (opacity as Figma stores it) and the banner, shown and closed.

… as px

An agent writing <Image x="539" width="363"> got 'Did you mean id?' for x and an error for the width.
Attributes written out of habit (x, y, fill, stroke, rotation, corner-radius) now get the CSS that says the same,
and sizes, places, gaps, paddings and radii take a bare number as px. A bare line height stays a multiple.
…er side draws

Seen live in a blank file: a new <Text flex="1"> stayed 0 px wide, a letter a line, and border-top on a new frame
left every stroke weight at 0. Figma makes a text 0 wide and does not lay it out again when it is set to fill; the
writer now resizes such a text keeping the fill. The first stroke side set gives a layer weights per side with the
others at 0, so the top side skipped for already reading 1 ended at 0; every side is now written.

The fake Figma makes new layers as Figma does (a text 0 wide, a frame's stroke sides reading 1 until one is set),
which changes the G3 apply-writes goldens: new layers now list those values. No write calls changed.
…, which fills any layer

A session wanting to fill an existing avatar ellipse with a photo found no way: src on an <Ellipse> answered 'A
frame's image is its background', and the guide said url() fills a frame. background="url(…)" already fills any
layer that takes a background, an existing ellipse included (now pinned by a plugin test); the hint now names it
with the file, and the guide says so. The core apply golden changes for that hint's words only.
…que layer holding it

A session clipping a region of a long landing frame got RESULT_TOO_LARGE: a clip rendered the whole layer, then cut
it, and Figma's export has no region of its own. The plugin's new read-only cover operation finds the deepest layer
under the region that shows it alone (an opaque solid fill holding the region clear of its corners, nothing painted
after it over the region, no mask before it, nothing faded, blended, blurred or turned on the way down); the server
asks for it only when the whole render is too heavy, renders it on its own box and cuts the region there. An older
plugin without cover, or no such layer, keeps the refusal.

The operations golden gains cover's input and output. The plugin's main.js budget goes from 350 to 360 kB: with the
operation the bundle came to 352.1 kB.
A Starter file allows one mode a collection, and tokens_apply passed on Figma's 'in addMode: Limited to 1 modes
only'. The error now says how many modes the plan allows and which mode, with its values, is left out, and that a
dry run cannot know the plan (the Plugin API does not tell it); the tokens guide says the same.
… the next one

The window says 'Pixelwright X.Y.Z is out' at the top with two links, What's new (that version's section of the
website's changelog) and How to update (the README's steps), and a close button; a closed banner stays closed until
a newer version (the version kept in figma.clientStorage). The plugin still never goes online: the server asks npm
for pixelwright@latest at most once a day on the computer (kept in ~/.pixelwright/latest.json, quiet offline, off
with PIXELWRIGHT_NO_UPDATE_CHECK) and tells every plugin window over the bridge as an event, a window that says
hello later included. The window shows it only when it is newer than its own version; main opens only those links.

The stdio e2e test turns the check off, so no test asks npm.
…at the opacity asked

Checked live in Figma: a paint newly bound to a colour variable takes the variable's colour and its alpha as the
paint's opacity, whatever opacity it was given, and a lowered opacity set on a paint already bound stays (it is the
whole of it, rendered once). So:
- design_read wrote a 14% hairline variable as color-mix(var(--line) 14%, transparent), its own alpha read as an
  extra opacity; it now divides the variable's alpha out: var(--line), and color-mix(... 50%) only past it.
- design_apply's color-mix(var(--x) N%) lost its N%: Figma replaced it with the alpha. The paint is now made of the
  variable's colour and alpha times N for the layer it goes on (resolveForConsumer, else the default mode), and the
  opacity Figma replaced is set again after (opacitiesAgain). A bound paint no longer starts from a black placeholder,
  so a text run Figma does not resolve still shows the variable's colour.

The feedback's 172 instances whose bound fills lost transparency against the main component most likely came from
the same mismatch between what was read and what Figma stores (not reproduced on its file).
@maximwas
maximwas merged commit 03e1848 into main Oct 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant