Docs - #97
Merged
Merged
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Prep for autogenerated documentation on the darkly website
What this branch does
Darkly's website is a separate, private repo. This branch builds the producer half of the boundary between them: one artifact per release that describes everything Darkly registers, complete enough that the consumer needs no Darkly source and no Darkly knowledge to render it. Getting there required unifying the registries it projects from, so most of the diff is that unification rather than the export itself.
The docs artifact
.github/workflows/docs-artifact.ymlpacks one tarball per release tag:metadata.json, resolvedicons.json, anddocs/manual/— prose, registry projection and icons under oneversion, so a consumer can never pair prose from one build with metadata from another. The consumer is pull-based and deliberately unnamed; this repo is public and knows nothing about who reads the artifact.bin/export-docswrites the self-describing JSON. Everything requiring Darkly knowledge to compute is computed here: layered preset resolution, chord rendering for both platform conventions, unit-suffixed display strings. It needs no GPU — every registry constructor is pure, so the catalogs build from&'staticregistration data alone.frontend/scripts/export-doc-icons.mjsresolves icon names to SVG. An icon name is not self-describing andlocal:icons exist nowhere but this repo, so the artifact carries resolved markup rather than asking a consumer to own an icon toolchain.docs/manual/is the hand-written half — pure markdown, no consumer components, or the public repo acquires an invisible dependency on private code.One catalog shape for every registry
catalog.rsis the core of it. Filters, veils, voids, blend modes, tools, layer kinds and layer filters all answer the same four questions — name, appearance, behaviour, settable parameters — and each answered them through its own flat*TypeInfostruct and its own engine query.Catalog/CatalogEntryreplaces all of them.Each registration type builds its own entry in its own file, so nothing in
catalog.rsbranches on which registry it is looking at, and adding a veil still touches nothing outsidegpu/veils/.build.rsgenerates the enumeration of catalog-producing registries from the module directories it already scans — a registry cannot be silently left out of the projection. Tools joined the same registry (three lines per tool file).The UI pickers, the settings surface and the metadata export now consume one shape instead of three.
Actions and hotkeys became Rust-owned
action.rsplusactions/*.rssplit an action into two halves. The documentable half — id, label, icon, one-line description — is static data living beside thepresets/*.yamlbindings that name the same ids. The behavioural half closes over Svelte runes and stays infrontend/src/actions/. They join by id, andaction_metadata_join.test.tsholds the two sides to it.Categories are one file each (
edit.rs,view.rs,layers.rs, …), the same many-items-per-file shapeconfig/sections/uses and the shape GIMP's per-domainGimpActionEntrytables use.build.rsdiscovers them.config/chord.rsmoves binding-grammar parsing and chord rendering into Rust. The artifact ships chords already rendered for both Mac and non-Mac conventions — a second implementation of that table on the consumer side is exactly what the artifact exists to avoid.frontend/src/config/schema.tsis deleted; the schema now comes from Rust.Preview system unification
gpu/veil_preview.rsandgpu/void_preview.rsare gone, absorbed intogpu/preview.rs. An entry declares that it has a preview (aPreviewAnimon its registration) and how it moves as code (preview_at); one driver renders both the editor's pickers and the documentation frames, so a preview can't look one way in the app and another in the docs.Two invariants hold it together:
preview_at(0.5)produces the same state whether it followspreview_at(0.4)or nothing at all — which is what lets a sequence be rebuilt, resumed or sampled out of order.preview_at_is_absoluteintests/picker_preview.rsenforces it across every entry.docs_render/renders nothing of its own. The motion belongs to the entry; what's left in the module is only what a headless run needs — a fixed synthetic subject instead of the user's canvas, a blocking capture sink, PNGs on disk, and an index beside them. Blend modes and brushes get the two leftover renderers, since neither is an effect over one image.bin/render-docsis a separate binary fromexport-docson purpose: folding them together would drag the GPU-free metadata export behind a GPU device and thetestingfeature it doesn't need. Preview encoding (poster + looping H.264) is not in this branch.Brush engine
brush/warp_field.rs). A warp terminal's whole stroke is expressible as one coordinate map, so rasterising the intermediate states was both wasteful and destructive — at liquify's 4 px dab spacing a pixel passes under dozens of dabs per swipe, and a chain of bilinear filters is a low-pass cascade, not a bilinear filter. The scratch holds the map; one resample at the end turns it back into pixels.PortDef::min/max), so a control whose registration range is a poor fit becomes usable without a helper node doing arithmetic in the graph. The range lives on the instance port, so the brush bar and the node editor both see it.units.rs— display units for numeric values, at the crate root because node-graph ports and effect parameters both declare one and neither owns the table.Frontend
lib/scrubDrag.tsgives value scrubs a proper drag lifecycle: preview locally while the pointer moves, commit once on release. The intermediate values of a scrub are transient session state — sending each one to the engine made every frame of a gesture a committed mutation, recompiling the brush graph and re-deriving its previews for values the user was only passing through. It's kept free of DOM and app state so it unit-tests headlessly under vitest.Also:
wasm-watch.mjsfor the dev loop, and tool glyph handling.Spelling
Registry prose, parameter labels, descriptions and option labels went
colour→colorthroughout. These strings are published in the artifact, so the inconsistency was user-visible.Tests
New:
docs_export.rs,docs_render.rs,picker_preview.rs,brush_preview_staging.rs,port_ranges.rs,warp_field.rs,action_metadata_join.test.ts,scrubDrag.test.ts,toolGlyph.test.ts.veil_preview.rsandvoid_preview.rswere removed along with the modules they covered.