mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-24 10:27:00 -06:00
M0.8: AGENTS.md/CLAUDE.md, ATTRIBUTION.md, parity report, wasm compatibility
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b3b48281bd
commit
09a7082887
@@ -0,0 +1,126 @@
|
||||
# FigCraft — instructions for agents
|
||||
|
||||
FigCraft is a clean-room, open-source, pure-Rust (egui) reimplementation of the Figma design workflow:
|
||||
interface design, auto layout, components and variants, styles and variables, prototyping and
|
||||
inspection. It runs natively on macOS, Windows, Linux and FreeBSD, and in the browser via WASM.
|
||||
Siblings: `../vectorcraft` (Illustrator-class), `../photocraft` (Photoshop-class), `../designcraft`
|
||||
(InDesign-class) and the other Crafting Apps; same conventions.
|
||||
|
||||
Standards and learnings shared across the crafting apps live in `../../craftrules` (checked out
|
||||
next to `craft-apps/`, or `storytold/craftrules`). Read its `AGENTS.md` at the start of a session,
|
||||
follow its standards, and contribute reusable learnings back there. Never code: repos don't share
|
||||
code.
|
||||
|
||||
## Start every session here
|
||||
1. Read [`ROADMAP.md`](ROADMAP.md): where we stand, the prioritized gap list, and the time estimates.
|
||||
Unless the user gives you a task, pick work from that list.
|
||||
2. Read `plan/STATUS.md` and `plan/execution-plan.md` (local, gitignored) if present; behaviour
|
||||
reference notes are in `plan/figma/*.md`.
|
||||
3. Orient → plan → implement + test → verify (screenshot) → record (ROADMAP, devlog) → commit.
|
||||
|
||||
`plan/` is gitignored (local only).
|
||||
|
||||
## Non-negotiables
|
||||
|
||||
### Clean-room
|
||||
- Behaviour comes from public documentation and black-box observation of the running incumbent app
|
||||
with synthetic documents only. Never read, disassemble or copy anything inside the incumbent's
|
||||
application bundle, web bundle or network traffic (names and public listings only).
|
||||
- Never copy GPL/AGPL code.
|
||||
- Reference screenshots of the incumbent stay local under the gitignored `plan/figma/screenshots/`
|
||||
and are never committed, published or used as assets.
|
||||
|
||||
### Assets: no third-party product iconography or images — ever (absolute rule from the project owner)
|
||||
- **Never add, copy, trace, redraw-from, embed or ship any icon, image, illustration, cursor, logo,
|
||||
template, UI kit, preset library, font file or screenshot from Figma, Adobe, Avid, Autodesk or any
|
||||
other product, or from any source whose licence doesn't allow it.** This includes "lookalike"
|
||||
redraws of their icons. Breaking this rule is the worst thing you can do in this repo.
|
||||
- Every image, icon, font or other asset must be one of:
|
||||
- original work created for FigCraft by a contributor (licensed MIT OR Apache-2.0);
|
||||
- OSI open source;
|
||||
- public domain / CC0;
|
||||
- Creative Commons with redistribution allowed.
|
||||
- **Every asset file must have a row in [`ATTRIBUTION.md`](ATTRIBUTION.md)** (path, author, source,
|
||||
licence, notes). `cargo xtask assets` (part of `cargo xtask ci`) fails on any unlisted file under
|
||||
`assets/`, `docs/brand/` or `docs/images/`.
|
||||
- FigCraft's UI icons are drawn in code (`crates/ui-egui/src/icons.rs`) from simple primitives and
|
||||
are original. Keep it that way: new icons are new code, designed from scratch.
|
||||
- The app icon is generated in code (`cargo xtask icon`, `xtask/src/icon.rs`).
|
||||
- **Fonts live in [storytold/craft-fonts](https://github.com/storytold/craft-fonts), never in this
|
||||
repo.** The app uses it only through the optional `CRAFT_FONTS_DIR` build input
|
||||
(`.cargo/config.toml` points it at `../craft-fonts` for local builds; `crates/text/build.rs`
|
||||
embeds it). Everything must build, test and run without it (system fonts are scanned at runtime).
|
||||
- Demo and test content is synthetic or public domain; never personal photos or data.
|
||||
- Code and original assets are MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`, `NOTICE`). The
|
||||
ArtCraft logos in `docs/brand/` are trademarks, not open source, under
|
||||
`docs/brand/LICENSE-brand.txt`: never modify them or use them outside FigCraft.
|
||||
- If the provenance of an asset is unclear, don't add it.
|
||||
|
||||
### Never crash
|
||||
- No `unwrap()`, `expect()`, `panic!`, `unreachable!`, `todo!`, `unimplemented!` in shipped code
|
||||
(workspace clippy lints deny them; tests may use them). Return `Result`/`Option`; use `.get()` for
|
||||
data-derived indexes; slice strings only at char boundaries; check floats are finite; cap sizes.
|
||||
- `figcraft_engine::guard` turns a panicking command into `EngineError::Internal` and the document
|
||||
is rolled back; the desktop app also guards each UI frame and writes recovery copies. These are
|
||||
safety nets, not substitutes for `Result`.
|
||||
- `unsafe_code = "forbid"` workspace-wide.
|
||||
- Every crash fix comes with a regression test. The engine has a junk-parameter sweep over every
|
||||
command (`crates/engine/src/tests.rs`): extend fuzz/sweep tests when you add parsers or commands.
|
||||
|
||||
### Architecture
|
||||
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*`
|
||||
(`spec!(id, label, params doc, undoable, run)`) + tests. The menus, shortcuts, Actions palette,
|
||||
CLI, control channel and MCP server all dispatch the same command ids. Command ids follow the
|
||||
incumbent's menu catalog in `crates/engine/src/catalog.rs` (the parity metric: `cargo xtask parity`).
|
||||
- **Programmatic calls never open dialogs.** Commands only *request* UI (`Session::request_ui`); the
|
||||
control channel drops dialog requests.
|
||||
- **Layering** is enforced by `cargo xtask layers`: geom/color (L0) → doc (L1) → layout/text/pathops
|
||||
(L2) → render/format (L3) → svg/pdf (L4) → engine (L5) → ui-egui/mcp (L6) → apps. Nothing below
|
||||
L6 depends on egui/eframe/rfd/winit. **The UI crate is swappable.**
|
||||
- **The UI is thin**: panels read engine state and act through `app.run(id, params)` /
|
||||
`app.set_props(ids, props)`. Colours come from `theme::Tokens`.
|
||||
- **Rust only** (no handwritten JS/TS). **Never break wasm** (`cargo xtask wasm`).
|
||||
|
||||
### Quality gates (before every commit)
|
||||
`cargo xtask ci` (fmt, clippy -D warnings, tests, layers, assets, wasm). One task per commit with a
|
||||
milestone id in the message (`M2.1: auto layout wrap`). Commit after every landed arc of work; push
|
||||
to `main`.
|
||||
|
||||
## Running and looking at the app
|
||||
- `cargo run -p figcraft -- --control <port> [file.figcraft|file.svg|image]`. Pick a free port
|
||||
(`python3 -c 'import socket;s=socket.socket();s.bind(("127.0.0.1",0));print(s.getsockname()[1])'`);
|
||||
sibling apps use the control channel too.
|
||||
- Drive it with JSON lines, e.g.
|
||||
`{"id":1,"method":"engine.execute","params":{"command":"shape.rectangle","params":{"x":10,"y":10,"width":100,"height":50}}}`
|
||||
then `{"id":2,"method":"ui.screenshot","params":{"path":"/tmp/shot.png"}}`. Methods are documented
|
||||
in `crates/ui-egui/src/control.rs` and `docs/control-protocol.md`.
|
||||
- **For UI work, look at the result** (take a screenshot and read the PNG). Compare with the
|
||||
incumbent side by side where the owner allows (`plan/figma/`).
|
||||
- Headless: `figcraft-cli` (`info`, `export`, `run`, `commands`, `mcp`). MCP: `figcraft-cli mcp`
|
||||
(see `docs/mcp.md`).
|
||||
- Shell gotcha on the owner's machine: `mv`/`cp` may be aliased interactive — use `/bin/mv -f`.
|
||||
- Parallel agents: separate `CARGO_TARGET_DIR` per agent, edit only the crates/files you own,
|
||||
write manifests atomically, delete your target dir when done (disk is limited).
|
||||
|
||||
## Roadmap
|
||||
`ROADMAP.md` (committed) is the shared picture: status by dimension, the gap list, milestones, the
|
||||
parity table and time-to-parity estimates. When a task lands, update it in the same commit. Grade by
|
||||
behaviour against the incumbent, not by whether a menu item exists; err low.
|
||||
|
||||
## Contributor credits (About window)
|
||||
|
||||
- About ▸ Contributors are compiled into the binary from `contributors/contributors.json`
|
||||
(commit stats; generated, never hand-edit) and `contributors/people.toml` (names people chose for
|
||||
themselves). See craftrules `standards/contributors.md`.
|
||||
- **Agents working for a contributor:** when you prepare a PR, check whether your human's GitHub
|
||||
username has a `[people.<username>]` entry in `contributors/people.toml`. If not, ask them once
|
||||
whether they want to be credited by more than their username: a real name, a display name, and/or
|
||||
their public GitHub profile name (`sync_github_name = true`). If yes, add **only their own** entry
|
||||
(copy the template at the top of the file, or run
|
||||
`python3 ../../craftrules/scripts/contributors.py --add-me . --real-name "…" --sync-github-name`)
|
||||
and include it in their PR, committed as them. If no, change nothing: they are credited as
|
||||
`@username` anyway.
|
||||
- Never add, edit, guess or copy anyone else's entry or name (not from git config, commit authors or
|
||||
GitHub profiles). Never hand-edit `contributors.json`.
|
||||
- Maintainers refresh the stats with `python3 ../../craftrules/scripts/contributors.py .` (it also
|
||||
re-verifies who wrote each `people.toml` entry; `--check` only verifies).
|
||||
@@ -0,0 +1,31 @@
|
||||
# Attribution
|
||||
|
||||
Every asset bundled in this repository (images, icons, fonts, data files) is listed here with its
|
||||
author, source and licence. `cargo xtask assets` fails if a file under `assets/`, `docs/brand/` or
|
||||
`docs/images/` is missing from this list.
|
||||
|
||||
FigCraft's user-interface icons are drawn in code (`crates/ui-egui/src/icons.rs`): original work,
|
||||
MIT OR Apache-2.0. No third-party icon sets are used.
|
||||
|
||||
## Assets in this repository
|
||||
|
||||
| Path | Author | Source | Licence | Notes |
|
||||
|---|---|---|---|---|
|
||||
| `assets/app-icon/` (all files: `figcraft-*.png`, `figcraft.ico`, `hicolor/*/apps/ai.storyteller.figcraft.png`) | FigCraft contributors | Generated by `cargo xtask icon` (`xtask/src/icon.rs`) with FigCraft's own renderer | MIT OR Apache-2.0 | Original geometric mark (stacked layer cards and a cursor) |
|
||||
| `docs/brand/artcraft-logo.svg`, `docs/brand/artcraft-logo.png`, `docs/brand/artcraft-logo-white.svg`, `docs/brand/artcraft-logo-white.png`, `docs/brand/artcraft-mark.svg`, `docs/brand/artcraft-mark.png`, `docs/brand/artcraft-mark-black.svg`, `docs/brand/artcraft-mark-black.png` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`), not open source | Trademarks; unmodified use within FigCraft only |
|
||||
| `docs/images/` (all screenshots) | FigCraft contributors | Screenshots of FigCraft showing synthetic demo documents made in FigCraft | MIT OR Apache-2.0 | No third-party artwork |
|
||||
|
||||
## Fonts (build input, not in this repository)
|
||||
|
||||
Release builds embed fonts from the optional craft-fonts build input
|
||||
([storytold/craft-fonts](https://github.com/storytold/craft-fonts), `CRAFT_FONTS_DIR`). Its own
|
||||
`ATTRIBUTION.md` and licence files are authoritative; the packages ship each font's licence.
|
||||
|
||||
| Family | Licence | Upstream |
|
||||
|---|---|---|
|
||||
| Inter | SIL Open Font License 1.1 | https://github.com/rsms/inter |
|
||||
| Roboto, Montserrat, Lato, Open Sans, Poppins, Nunito Sans, Merriweather, Playfair Display, Source Sans 3, Source Serif 4, Carlito, Caladea | SIL Open Font License 1.1 | Google Fonts / upstream repositories (see craft-fonts) |
|
||||
| Liberation Sans, Serif, Mono | SIL Open Font License 1.1 | https://github.com/liberationfonts |
|
||||
| BIZ UDPGothic, BIZ UDMincho, Shippori Mincho, Noto Sans Arabic | SIL Open Font License 1.1 | Google Fonts (see craft-fonts) |
|
||||
|
||||
egui's default fonts (compiled into the `egui`/`epaint` crates) keep their own licences (OFL / Apache-2.0 / Ubuntu Font Licence); see those crates.
|
||||
@@ -0,0 +1,126 @@
|
||||
# FigCraft — instructions for agents
|
||||
|
||||
FigCraft is a clean-room, open-source, pure-Rust (egui) reimplementation of the Figma design workflow:
|
||||
interface design, auto layout, components and variants, styles and variables, prototyping and
|
||||
inspection. It runs natively on macOS, Windows, Linux and FreeBSD, and in the browser via WASM.
|
||||
Siblings: `../vectorcraft` (Illustrator-class), `../photocraft` (Photoshop-class), `../designcraft`
|
||||
(InDesign-class) and the other Crafting Apps; same conventions.
|
||||
|
||||
Standards and learnings shared across the crafting apps live in `../../craftrules` (checked out
|
||||
next to `craft-apps/`, or `storytold/craftrules`). Read its `AGENTS.md` at the start of a session,
|
||||
follow its standards, and contribute reusable learnings back there. Never code: repos don't share
|
||||
code.
|
||||
|
||||
## Start every session here
|
||||
1. Read [`ROADMAP.md`](ROADMAP.md): where we stand, the prioritized gap list, and the time estimates.
|
||||
Unless the user gives you a task, pick work from that list.
|
||||
2. Read `plan/STATUS.md` and `plan/execution-plan.md` (local, gitignored) if present; behaviour
|
||||
reference notes are in `plan/figma/*.md`.
|
||||
3. Orient → plan → implement + test → verify (screenshot) → record (ROADMAP, devlog) → commit.
|
||||
|
||||
`plan/` is gitignored (local only).
|
||||
|
||||
## Non-negotiables
|
||||
|
||||
### Clean-room
|
||||
- Behaviour comes from public documentation and black-box observation of the running incumbent app
|
||||
with synthetic documents only. Never read, disassemble or copy anything inside the incumbent's
|
||||
application bundle, web bundle or network traffic (names and public listings only).
|
||||
- Never copy GPL/AGPL code.
|
||||
- Reference screenshots of the incumbent stay local under the gitignored `plan/figma/screenshots/`
|
||||
and are never committed, published or used as assets.
|
||||
|
||||
### Assets: no third-party product iconography or images — ever (absolute rule from the project owner)
|
||||
- **Never add, copy, trace, redraw-from, embed or ship any icon, image, illustration, cursor, logo,
|
||||
template, UI kit, preset library, font file or screenshot from Figma, Adobe, Avid, Autodesk or any
|
||||
other product, or from any source whose licence doesn't allow it.** This includes "lookalike"
|
||||
redraws of their icons. Breaking this rule is the worst thing you can do in this repo.
|
||||
- Every image, icon, font or other asset must be one of:
|
||||
- original work created for FigCraft by a contributor (licensed MIT OR Apache-2.0);
|
||||
- OSI open source;
|
||||
- public domain / CC0;
|
||||
- Creative Commons with redistribution allowed.
|
||||
- **Every asset file must have a row in [`ATTRIBUTION.md`](ATTRIBUTION.md)** (path, author, source,
|
||||
licence, notes). `cargo xtask assets` (part of `cargo xtask ci`) fails on any unlisted file under
|
||||
`assets/`, `docs/brand/` or `docs/images/`.
|
||||
- FigCraft's UI icons are drawn in code (`crates/ui-egui/src/icons.rs`) from simple primitives and
|
||||
are original. Keep it that way: new icons are new code, designed from scratch.
|
||||
- The app icon is generated in code (`cargo xtask icon`, `xtask/src/icon.rs`).
|
||||
- **Fonts live in [storytold/craft-fonts](https://github.com/storytold/craft-fonts), never in this
|
||||
repo.** The app uses it only through the optional `CRAFT_FONTS_DIR` build input
|
||||
(`.cargo/config.toml` points it at `../craft-fonts` for local builds; `crates/text/build.rs`
|
||||
embeds it). Everything must build, test and run without it (system fonts are scanned at runtime).
|
||||
- Demo and test content is synthetic or public domain; never personal photos or data.
|
||||
- Code and original assets are MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`, `NOTICE`). The
|
||||
ArtCraft logos in `docs/brand/` are trademarks, not open source, under
|
||||
`docs/brand/LICENSE-brand.txt`: never modify them or use them outside FigCraft.
|
||||
- If the provenance of an asset is unclear, don't add it.
|
||||
|
||||
### Never crash
|
||||
- No `unwrap()`, `expect()`, `panic!`, `unreachable!`, `todo!`, `unimplemented!` in shipped code
|
||||
(workspace clippy lints deny them; tests may use them). Return `Result`/`Option`; use `.get()` for
|
||||
data-derived indexes; slice strings only at char boundaries; check floats are finite; cap sizes.
|
||||
- `figcraft_engine::guard` turns a panicking command into `EngineError::Internal` and the document
|
||||
is rolled back; the desktop app also guards each UI frame and writes recovery copies. These are
|
||||
safety nets, not substitutes for `Result`.
|
||||
- `unsafe_code = "forbid"` workspace-wide.
|
||||
- Every crash fix comes with a regression test. The engine has a junk-parameter sweep over every
|
||||
command (`crates/engine/src/tests.rs`): extend fuzz/sweep tests when you add parsers or commands.
|
||||
|
||||
### Architecture
|
||||
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*`
|
||||
(`spec!(id, label, params doc, undoable, run)`) + tests. The menus, shortcuts, Actions palette,
|
||||
CLI, control channel and MCP server all dispatch the same command ids. Command ids follow the
|
||||
incumbent's menu catalog in `crates/engine/src/catalog.rs` (the parity metric: `cargo xtask parity`).
|
||||
- **Programmatic calls never open dialogs.** Commands only *request* UI (`Session::request_ui`); the
|
||||
control channel drops dialog requests.
|
||||
- **Layering** is enforced by `cargo xtask layers`: geom/color (L0) → doc (L1) → layout/text/pathops
|
||||
(L2) → render/format (L3) → svg/pdf (L4) → engine (L5) → ui-egui/mcp (L6) → apps. Nothing below
|
||||
L6 depends on egui/eframe/rfd/winit. **The UI crate is swappable.**
|
||||
- **The UI is thin**: panels read engine state and act through `app.run(id, params)` /
|
||||
`app.set_props(ids, props)`. Colours come from `theme::Tokens`.
|
||||
- **Rust only** (no handwritten JS/TS). **Never break wasm** (`cargo xtask wasm`).
|
||||
|
||||
### Quality gates (before every commit)
|
||||
`cargo xtask ci` (fmt, clippy -D warnings, tests, layers, assets, wasm). One task per commit with a
|
||||
milestone id in the message (`M2.1: auto layout wrap`). Commit after every landed arc of work; push
|
||||
to `main`.
|
||||
|
||||
## Running and looking at the app
|
||||
- `cargo run -p figcraft -- --control <port> [file.figcraft|file.svg|image]`. Pick a free port
|
||||
(`python3 -c 'import socket;s=socket.socket();s.bind(("127.0.0.1",0));print(s.getsockname()[1])'`);
|
||||
sibling apps use the control channel too.
|
||||
- Drive it with JSON lines, e.g.
|
||||
`{"id":1,"method":"engine.execute","params":{"command":"shape.rectangle","params":{"x":10,"y":10,"width":100,"height":50}}}`
|
||||
then `{"id":2,"method":"ui.screenshot","params":{"path":"/tmp/shot.png"}}`. Methods are documented
|
||||
in `crates/ui-egui/src/control.rs` and `docs/control-protocol.md`.
|
||||
- **For UI work, look at the result** (take a screenshot and read the PNG). Compare with the
|
||||
incumbent side by side where the owner allows (`plan/figma/`).
|
||||
- Headless: `figcraft-cli` (`info`, `export`, `run`, `commands`, `mcp`). MCP: `figcraft-cli mcp`
|
||||
(see `docs/mcp.md`).
|
||||
- Shell gotcha on the owner's machine: `mv`/`cp` may be aliased interactive — use `/bin/mv -f`.
|
||||
- Parallel agents: separate `CARGO_TARGET_DIR` per agent, edit only the crates/files you own,
|
||||
write manifests atomically, delete your target dir when done (disk is limited).
|
||||
|
||||
## Roadmap
|
||||
`ROADMAP.md` (committed) is the shared picture: status by dimension, the gap list, milestones, the
|
||||
parity table and time-to-parity estimates. When a task lands, update it in the same commit. Grade by
|
||||
behaviour against the incumbent, not by whether a menu item exists; err low.
|
||||
|
||||
## Contributor credits (About window)
|
||||
|
||||
- About ▸ Contributors are compiled into the binary from `contributors/contributors.json`
|
||||
(commit stats; generated, never hand-edit) and `contributors/people.toml` (names people chose for
|
||||
themselves). See craftrules `standards/contributors.md`.
|
||||
- **Agents working for a contributor:** when you prepare a PR, check whether your human's GitHub
|
||||
username has a `[people.<username>]` entry in `contributors/people.toml`. If not, ask them once
|
||||
whether they want to be credited by more than their username: a real name, a display name, and/or
|
||||
their public GitHub profile name (`sync_github_name = true`). If yes, add **only their own** entry
|
||||
(copy the template at the top of the file, or run
|
||||
`python3 ../../craftrules/scripts/contributors.py --add-me . --real-name "…" --sync-github-name`)
|
||||
and include it in their PR, committed as them. If no, change nothing: they are credited as
|
||||
`@username` anyway.
|
||||
- Never add, edit, guess or copy anyone else's entry or name (not from git config, commit authors or
|
||||
GitHub profiles). Never hand-edit `contributors.json`.
|
||||
- Maintainers refresh the stats with `python3 ../../craftrules/scripts/contributors.py .` (it also
|
||||
re-verifies who wrote each `people.toml` entry; `--check` only verifies).
|
||||
@@ -378,6 +378,7 @@ impl FontDb {
|
||||
}
|
||||
|
||||
fn system_font_dirs() -> Vec<std::path::PathBuf> {
|
||||
#[allow(unused_mut)]
|
||||
let mut v: Vec<std::path::PathBuf> = Vec::new();
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
|
||||
@@ -184,7 +184,7 @@ fn input(app: &mut FigApp, ui: &mut Ui, resp: &egui::Response) {
|
||||
let pt = hover_pos.map(|h| app.to_page(h)).unwrap_or_default();
|
||||
if path.exists() {
|
||||
app.run("file.import", json!({"path": path.to_string_lossy(), "x": pt.x, "y": pt.y}));
|
||||
} else if let Ok(bytes) = f.bytes() {
|
||||
} else if let Some(bytes) = dropped_bytes(&f) {
|
||||
use base64::Engine as _;
|
||||
let b64 = base64::engine::general_purpose::STANDARD.encode(&bytes);
|
||||
let name = path.file_name().map(|n| n.to_string_lossy().to_string()).unwrap_or_else(|| "dropped.png".into());
|
||||
@@ -289,6 +289,17 @@ fn input(app: &mut FigApp, ui: &mut Ui, resp: &egui::Response) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn dropped_bytes(f: &std::sync::Arc<dyn egui::DroppedFile + Send + Sync>) -> Option<Vec<u8>> {
|
||||
f.bytes().ok()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn dropped_bytes(_f: &std::sync::Arc<dyn egui::DroppedFile + Send + Sync>) -> Option<Vec<u8>> {
|
||||
// Browser drops arrive asynchronously; not supported yet.
|
||||
None
|
||||
}
|
||||
|
||||
fn stroke(c: Color32, w: f32) -> Stroke {
|
||||
Stroke::new(w, c)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Parity report
|
||||
|
||||
Generated by `cargo xtask parity`: FigCraft commands registered for the incumbent's main menu and toolbar (278 commands in the engine).
|
||||
|
||||
**191 / 199 menu items (96.0%)**
|
||||
|
||||
## Missing
|
||||
|
||||
- `file.exportFramesPdf`
|
||||
- `file.openRecent`
|
||||
- `view.outlinesSelection`
|
||||
- `view.maskOutlines`
|
||||
- `vector.deleteHeal`
|
||||
- `plugins.runLast`
|
||||
- `plugins.manage`
|
||||
- `libraries.publish`
|
||||
|
||||
Menu coverage measures breadth only; see ROADMAP.md for depth and fidelity.
|
||||
+11
-1
@@ -70,7 +70,17 @@ fn assets() -> bool {
|
||||
if name.starts_with('.') || name.ends_with(".md") || name.ends_with(".txt") {
|
||||
return;
|
||||
}
|
||||
if !attribution.contains(&rel) && !attribution.contains(&format!("{}/", rel.rsplit_once('/').map(|x| x.0).unwrap_or(""))) {
|
||||
// Listed by path, or by any ancestor directory written as `dir/`.
|
||||
let mut listed = attribution.contains(&format!("`{rel}`"));
|
||||
let mut cur = rel.as_str();
|
||||
while let Some((parent, _)) = cur.rsplit_once('/') {
|
||||
if attribution.contains(&format!("`{parent}/`")) {
|
||||
listed = true;
|
||||
break;
|
||||
}
|
||||
cur = parent;
|
||||
}
|
||||
if !listed {
|
||||
missing.push(rel);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user