8. The assets folder

Images and fonts of login.design are stored in login.design.assets/ in the same directory (PLT-2).

8.1 Location#

Images and fonts of login.design are stored in login.design.assets/ in the same directory (PLT-2). The folder is created with the first asset and is not needed when the document has none. Renaming or moving the design file in the editor moves the folder with it; “Save As” copies it.

8.2 Content-hash names#

Each file is named by the SHA-256 of its bytes, in lowercase hex, with the sha256- prefix and its extension:

text
login.design
login.design.assets/
  sha256-9c2f0e6b1a7d3c5e8f4b2a1d0c9e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e.png
  sha256-4e7a1d0c3b6f9e2a5d8c1b4f7a0e3d6c9b2f5a8e1d4c7b0a3f6e9d2c5b8a1f4e.woff2
  • The hash without the extension is the reference used in the file: imageHash of image paints, the key of tree.assets.
  • The same image used a hundred times, or added twice, is one file (NFR-3).
  • Two branches that add the same image add the same file, with the same content: no conflict.
  • Files are never modified. An edited image is a new file with a new hash.

Images are stored as given (PNG, JPEG, WebP, GIF, AVIF), up to 10 MB each (CLI-001). SVG files dropped on the canvas become vector nodes (EXP-4) and are not stored as assets, except when placed as an image fill.

8.3 Fonts#

Fonts come from three sources (TXT-6): the fonts bundled with the extension, the workspace folders in ud.fonts.folders, and the operating system. The design file stores only fontName (family and style); the font file is found at render time.

A user can embed a font in the document, so that the design renders the same on every machine and in CI: the font file is copied into the assets folder and registered with asset.add (kind: "font", family, style). Embedded fonts are looked up first. Embedding is a choice because fonts are licensed: committing a font to a repository is the user’s decision, and the editor says so when it embeds one.

The font’s licence bits decide whether it can be embedded at all. Before copying a font file, a writer reads the fsType field of its OS/2 table and embeds the font only when the field allows it: fsType 0 (installable embedding), or bit 3 set (0x0008, editable embedding). A font that is restricted (bit 1, 0x0002), preview-and-print only (bit 2, 0x0004), or bitmap-embedding only (bit 9, 0x0200) is not copied: the writer warns and the document keeps the reference only, fontName on the nodes, to be resolved from the workspace or the operating system as usual.

text
Font "Brand Sans Bold" was not embedded: its licence (OS/2 fsType 0x0004, preview and print) does not allow embedding. The design refers to it by name; install it where the file is rendered.

A font file placed in the assets folder by hand is used whatever its fsType says; the check is on the writer, not the reader, and ud lint reports an embedded font whose bits forbid embedding.

8.4 Writing order#

A writer stores the file in the assets folder before it appends the events that refer to it (asset.add, then the paint), and writes the file atomically (to a temporary name, then renamed). A reader that sees a reference therefore finds the file, except when a commit left it out.

8.5 Garbage collection#

An asset file is used when its hash appears in tree.assets, in an image paint anywhere in the tree or the WAL (including library copies, styles and unapplied lines), or in a named version still reachable in the WAL. Other files are unused.

Unused files are not deleted on their own: another branch, a stash or an undo may still need them. ud assets gc lists the unused files; ud assets gc --delete deletes them. The editor offers it after a consolidation. Run it on the main branch, after merging the branches that add images, like consolidation.

8.6 Git attributes#

The extension offers to add these lines to the repository’s .gitattributes (COL-4):

gitattributes
*.design merge=union
*.design.assets/** binary

merge=union merges the WAL by keeping the lines of both sides (section 6). binary stops git from diffing or merging asset files, which never need either: equal names have equal content. Repositories that keep large images in Git LFS can use instead:

gitattributes
*.design.assets/** filter=lfs diff=lfs merge=lfs -text

The format does not depend on LFS; the extension reads whatever git checks out, and an LFS pointer file that was not fetched counts as a missing asset (8.7).

8.7 Missing and damaged assets#

Situation Behaviour Warning
An imageHash with no file The paint renders as a grey checkerboard placeholder with an image icon, at the paint’s place; the paint is kept unchanged; exports render the placeholder and report it. Image sha256-9c2f…1d0e is missing from login.design.assets/.
A file whose bytes do not match its name (hash check on first load) Treated as missing. Image sha256-9c2f…1d0e is damaged: its content does not match its name.
An LFS pointer instead of the file Treated as missing. Image sha256-9c2f…1d0e is a Git LFS pointer; run git lfs pull.
A font in tree.assets with no file The font is looked up in the other sources; if absent, the fallback font is used and the font is listed as missing (TXT-6). Font "Brand Sans Bold" is missing.
A file in the folder that tree.assets does not register Usable by any reference to its hash; unused until then. none

Missing assets are listed by ud validate and in the editor’s problems strip. Dropping the original image again restores it, because it gets the same hash.