mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-08 19:42:12 +00:00
* Add craft-doc: read PhotoCraft, VectorCraft and EffectCraft documents without the apps
A new crate, craft-doc, reads the native files of three apps from bytes:
PhotoCraft .pcraft (a ZIP bundle), VectorCraft .vectorcraft (JSON, plain
or gzip, with the version 4 data after the JSON) and EffectCraft .ecproj
(JSON).
- sniff tells which app wrote a file from its first bytes.
- info gives the format version, the writer the file names, and whether
the version is one the crate reads.
- renditions returns VectorCraft's preview and PDF and PhotoCraft's
thumbnail and composite, when the file has them.
- outline returns PhotoCraft's canvas and layer tree, VectorCraft's
artboards and top-level layers, and EffectCraft's compositions with
their layers.
A file whose version is newer than the crate reads is refused with
Error::TooNew. Limits bound the JSON, each entry, the total bytes
decompressed and the JSON nesting, and each is checked before the bytes
it covers are allocated. ZIP entries are read by a small STORE and
DEFLATE reader in the crate. The crate depends on serde, serde_json,
thiserror and flate2 and builds for wasm32-unknown-unknown.
The tests build every document they read: JSON written by hand, PNG,
ZIP and gzip bytes assembled in the test. doc.yml runs fmt, clippy, the
tests and a wasm32 check.
* ci: do not keep the checkout token in the doc workflow
The checkout step sets persist-credentials: false, as jpeg.yml and media.yml do. No later step in the job uses the token.
* craft-doc: read each format's envelope through its format crate
craft-doc no longer keeps its own copies of the envelope types and
constants. It reads them with craft-pcraft-format (`MANIFEST`,
`FORMAT_VERSION`, `THUMB`, `COMPOSITE`, `check_manifest`),
craft-vectorcraft-format (`Head`, `Image`, `sniff`, `check`, `VERSION`,
`BLOB_MAGIC`, base64) and craft-ecproj-format (`Head::read`,
`SCHEMA_VERSION`). Its own base64 module is removed. A `.pcraft`
manifest is still read in one pass without building a
`serde_json::Value`, with the checks `read_manifest` applies. The
outlines are still read with craft-doc's read-only views of each
document, and the public API (`sniff`, `info`, `renditions`, `outline`,
`Limits`) does not change.
These inputs are now read as the format crates read them:
- A `.pcraft` manifest without `generator`, or with a `thumbnail` other
than `thumb.png` or a `composite` other than `composite/preview.png`,
is malformed for `renditions` and `outline`; `info` still reports its
version. A manifest with more than 4,194,304 JSON items is refused
with `LimitExceeded`.
- A `.vectorcraft` preview or PDF member without `mime` gives no
rendition.
- `sniff` takes `format` only from a top-level member, so
`{"meta":{"format":"vectorcraft"}}` is not a VectorCraft file.
tests/envelopes.rs writes a file of each format with the crates' types
and reads it through every call, and checks the inputs above.
doc.yml also runs when one of the three crates changes.
* craft-doc: sniff reads only top-level members of an EffectCraft project
`sniff` took any JSON object whose first member is `savedBy` for an
EffectCraft project when `"schema"` appeared anywhere in its first
bytes, so `{"savedBy":"1.0","metadata":{"schema":1}}` was claimed. It
now checks the top-level member names only, one at a time, without
keeping them.
* craft-doc: bound list elements with max_items; no rendition without a MIME type
Limits gains max_items (default 1,048,576): EffectCraft project items and
composition layers, VectorCraft artboards and layers, and PhotoCraft layers
at every level are counted before each one is read, and a file that lists
more gives Error::LimitExceeded. A list of empty objects within max_json no
longer expands into gigabytes of layers.
A VectorCraft preview or pdf member with an empty mime gives no rendition, as
one without a mime does; a preview may be PNG or JPEG. An EffectCraft
composition without a duration or a frame rate gets no timing instead of a
duration of 0.
125 lines
9.4 KiB
Markdown
125 lines
9.4 KiB
Markdown
Craft App Libraries
|
|
===================
|
|
|
|
<a href="https://sonarcloud.io/project/overview?id=storytold_craft-libs"><img alt="Scanned by SonarCloud" src="https://img.shields.io/badge/Scanned_by-SonarCloud-4b9fd5?style=flat-square&logo=sonarqubecloud&logoColor=white"></a>
|
|
|
|
This repo contains libraries used by the various Craft Apps. It's a Rust monorepo workspace, and the libraries can be included by any Craft Apps that need them.
|
|
|
|
In the future this may grow to include non-Rust library code.
|
|
|
|
If any libraries grow beyond Craft App usage, eg. RAW format support, they may be promoted out and into their own libraries for the broader ecosystem to take advantage of.
|
|
|
|
|
|
## Layout
|
|
|
|
A Cargo workspace (edition 2024, resolver 3). Each library is a crate under `crates/<name>`, named
|
|
`craft-<name>`, with `version`, `edition`, `license` and `repository` inherited from the workspace
|
|
(`license.workspace = true`, and so on) and `[lints] workspace = true`. Register each crate in
|
|
`[workspace.dependencies]` in the root `Cargo.toml`.
|
|
|
|
Apps depend on a crate by git:
|
|
|
|
```toml
|
|
craft-<name> = { git = "https://github.com/storytold/craft-libs", rev = "<commit>" }
|
|
```
|
|
|
|
## Libraries
|
|
|
|
- [`craft-platform`](crates/platform/README.md): optional native dialog lifecycle, Linux/BSD desktop appearance observation and browser download ownership; application policy stays in the apps.
|
|
|
|
- [`craft-ai-core`](crates/ai-core/README.md): the data model and contract for AI in the Craft Apps (connections, models, tools, requests, jobs, consent, history, route spec). Pure, no I/O, wasm-safe. Contract in [docs/ai-shared-layer.md](docs/ai-shared-layer.md).
|
|
- [`craft-pdf`](crates/pdf/README.md): independently optional PDF parsing, interpretation, rasterization and guarded authoring. Apps retain layout, fonts, editing and export policy; writer-only consumers do not enable the shared reader.
|
|
|
|
- [`craft-atomic`](crates/atomic/README.md): Crash-safe atomic file writing and replacement with same-directory staging, directory fsync, Apple `F_FULLFSYNC` fallback, transient lock backoff, and fault injection for the Craft suite.
|
|
- [`craft-cms`](crates/cms/README.md): pure-Rust ICC v2/v4 colour management: profile parsing
|
|
and writing, transforms, rendering intents, black point compensation, soft proofing, gamut
|
|
checks, 3D LUTs and built-in profiles (sRGB, Display P3, synthetic coated CMYK and others).
|
|
- [`craft-crw`](crates/crw/README.md): clean-room Canon CRW (CIFF) raw decoder, from LightCraft:
|
|
the heap container, the entropy coding derived by black-box analysis (frozen code tables), sensor
|
|
black and white levels and as-shot white balance. The complete derivation record (plan, sources
|
|
log, scripts, verification) is in `crates/crw/clean-room/`. Colour stays in each app.
|
|
- [`craft-dialogs`](crates/dialogs/README.md): native file and message dialogs that never block
|
|
the event loop: queued requests shown at the end of the frame and answered on a later frame,
|
|
free-standing Open and Folder panels and Save sheets on macOS, case-insensitive filters. What
|
|
to do with the answer stays in each app.
|
|
- [`craft-doc`](crates/doc/README.md): reads PhotoCraft `.pcraft`, VectorCraft `.vectorcraft`
|
|
and EffectCraft `.ecproj` documents without the apps: the kind and version, the previews and
|
|
PDF they carry, and their pages and layers. Rendering and editing stay in each app.
|
|
- [`craft-docpath`](crates/docpath/src/lib.rs): decides whether a path or `file:` URL stored in a
|
|
document may be opened. Paths stored in documents are followed only when they are local or on the
|
|
document's own network share; other network paths, device paths and non-file URLs are refused.
|
|
- [`craft-ecproj-format`](crates/ecproj-format/README.md): the envelope of EffectCraft `.ecproj`
|
|
project files: `savedBy`, the schema version and its check, and the file object with the
|
|
project and its saved view as type parameters. The project model stays in EffectCraft.
|
|
- [`craft-font-catalog`](crates/font-catalog/README.md): the installed fonts on every platform
|
|
(font folders, fontconfig and Flatpak host folders, CoreText, DirectWrite, the font store),
|
|
lookup by family, style, localized, legacy, full and PostScript names, family loads shared
|
|
between threads, and rescans when fonts are installed or removed.
|
|
- [`craft-font-manager`](crates/font-manager/README.md): Craft Font Manager as a library: search
|
|
and filters over the Google Fonts index, installed fonts by family, the font store interface,
|
|
and (`egui` feature) `FontsPanel`, the whole interface as one panel for the launcher's Fonts tab
|
|
and the standalone app.
|
|
- [`craft-font-store`](crates/font-store/README.md): the suite's font store: the pinned Google
|
|
Fonts and Noto indexes plus indexes the user adds (never curated), exact lookup by family and
|
|
style or PostScript name, and installs from each source's URLs (jsDelivr, then raw GitHub)
|
|
checked by size, sha256 and parsing, with the licence, a manifest, and removal. Off until the
|
|
user turns downloading on; agents can't.
|
|
- [`craft-fonts-build`](crates/fonts-build/README.md): embeds the optional craft-fonts faces
|
|
from an app's `build.rs` (`CRAFT_FONTS_DIR`, `CRAFT_FONTS_REQUIRED`, script filters) as a table
|
|
of `EmbeddedFace`s. No dependencies; the app picks the faces.
|
|
- [`craft-i18n`](crates/i18n/README.md): translations over the embedded craft-i18n catalogs:
|
|
lookup with fallback (`pt-br` → `pt` → English), plurals, language names, the system locale and
|
|
a pseudo locale. The catalogs stay a fully optional build input; apps keep `tl!` and their
|
|
language setting.
|
|
- [`craft-jpeg`](crates/jpeg/README.md): clean-room decoder for 12-bit and arithmetic-coded
|
|
JPEG (T.81 SOF0/SOF1 at 12 bits, SOF9, SOF10), from PhotoCraft, and a frame probe for routing.
|
|
Metadata stays in each app.
|
|
- [`craft-keymap`](crates/keymap/README.md): keyboard bindings: chords and their text forms,
|
|
scopes, conflicts, user overrides stored through craft-settings and import of other
|
|
applications' shortcut sets. Command catalogs, file readers and the shortcut editor UI stay
|
|
in each app.
|
|
- [`craft-media`](crates/media/README.md): bit-level I/O (`bitstream`), clean-room MP4/MOV
|
|
(`isobmff`) and Matroska/WebM (`matroska`) demuxers and muxers, from FilmCraft, and an ISO BMFF
|
|
box reader. Containers only; codecs stay in each app.
|
|
- [`craft-menu`](crates/menu/README.md): an app's menus as a macOS menu bar: the Mac layout
|
|
(app menu, Window, Help, system-key clashes), a platform backend trait, and key equivalents
|
|
fed back to egui as the input egui-winit would have made. Commands and their enabled state
|
|
stay in each app.
|
|
- [`craft-pcraft-format`](crates/pcraft-format/README.md): the envelope of PhotoCraft's `.pcraft`
|
|
bundle: `Manifest<D>` with the document as a type parameter, `TileRef`, the entry paths, the
|
|
manifest decode limits and the migration runner. The document model stays in PhotoCraft.
|
|
- [`craft-print`](crates/print/README.md): PDF submission to CUPS and Windows, printer discovery,
|
|
duplex/copies/colour and driver preferences. PDF generation stays in each app.
|
|
- [`craft-proof`](crates/proof/README.md): proofing per language (spelling, suggestions, grammar,
|
|
hyphenation, a Hunspell reader, user words, Language packs). The word lists and patterns are
|
|
craft-i18n's `language-data/`, embedded at build time from `CRAFT_I18N_DIR`: English and the
|
|
carry-over locales by default, the set `CRAFT_PROOF_EMBED` names otherwise (`en` for English
|
|
only); other languages come from installed Language packs.
|
|
|
|
- [`craft-quit`](crates/quit/src/lib.rs): native macOS quit, egui close handling and an optional
|
|
app menu. Unsaved-document decisions and save prompts stay in each app.
|
|
|
|
- [`craft-settings`](crates/settings/README.md): `config.toml` settings storage for every app: platform folders, portable mode and overrides, atomic saves while running, backup, damaged-file recovery and schema migrations. Policy in [docs/settings-storage.md](docs/settings-storage.md).
|
|
- [`craft-text`](crates/text/README.md): text processing below the composer. Its `hyphen` module finds
|
|
hyphenation points, with a bundled US English dictionary and patterns and optional hypher patterns
|
|
for 47 more languages (one cargo feature each).
|
|
- [`craft-ui`](crates/ui/README.md): SVG catalogs, icon buttons, tabs, pane controls, transactional docking, print settings and theme helpers for egui frontends;
|
|
assets, themes, localization and command handling stay in each app. Requires Rust 1.95 or later.
|
|
- [`craft-vectorcraft-format`](crates/vectorcraft-format/README.md): the envelope of VectorCraft's
|
|
`.vectorcraft` file: its members, versions, embedded images and the data after the JSON, with the
|
|
document as a type parameter. The document and its migrations stay in VectorCraft.
|
|
- [Shared UI component audit](docs/ui-components-audit.md): source inventory, extraction priorities
|
|
and compatibility boundaries across the Craft suite.
|
|
- [Theme infrastructure](docs/theme-infrastructure.md): eight-app comparison and the small shared
|
|
widget-state styling boundary.
|
|
- [Panel docking](docs/ui-docking.md): validated panel moves, floating groups, workspace adapters
|
|
and an optional egui docking surface.
|
|
|
|
## License and credits
|
|
|
|
craft-libs is dual-licensed under [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE), at your option.
|
|
Copyright (c) 2026 ArtCraft Team and the craft-libs contributors. Required notices are in [NOTICE](NOTICE).
|
|
|
|
Bundled fonts, icons, images and other assets keep their own open licenses; each one is listed
|
|
with its author, source and license in [ATTRIBUTION.md](ATTRIBUTION.md).
|