* fix(engine): Quick Export writes the format its path names (#8519)
Quick Export as PNG renamed to photo.jpeg in the save dialog wrote PNG
bytes under a JPEG name, which upload checks refuse and file managers
don't preview. The path's extension (.jpg/.jpeg/.png/.gif/.webp) now picks
the format; any other extension is refused with a pointer to Export As;
no extension keeps Export Preferences' format.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* contributors: add benandez's real name
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
docs/scorecard.md conflicted with main (a generated file). Regenerated it
with cargo xtask scorecard on the merged tree: settings that do nothing
24 -> 23 of 171, plug_ins.generator_enabled leaves the Unread list.
Co-authored-by: reynold-hu <88558425+reynold-hu@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-ups:
- Windows also reserves COM¹–COM³ and LPT¹–LPT³ (the ISO 8859-1
superscript digits), with any extension. `is_windows_device_name`
takes them too; `sanitize` keeps those characters, so `COM¹` became a
device file name before.
- Save for Web's `portable_generated_stem` added `_` at the end, so
`path: nul.v2.png` gave `nul.v2_.html`, still the NUL device, and the
export failed as an unsafe component. Both it and `sanitize` now share
`portable_device_name`, which puts `_` before the first dot.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`slices::resolve()` only clipped each stored slice to the canvas, so a slice under a later
one was numbered and exported in full and Save for Web wrote the overlap twice (the HTML
path cut pieces itself, named `<name>_01`, `_02`). As Photoshop does, resolve() now cuts a
covered slice into its visible pieces: the first piece in reading order keeps the name,
every further piece is `<name>-NN` with its own slice number, and auto slices count the
pieces in their numbering (measured in Photoshop: sliceA, <doc>_02, sliceA-03, sliceB,
<doc>_05).
- Save for Web exports resolve()'s pieces as they are, with or without HTML; a no-image
cell's text goes into its first piece only.
- Slice Options and slice.list show the slice's own name for every piece; slice.set accepts
a slice that ends up wholly under later ones (number null) instead of calling it off the
canvas.
- Slice Select drags the whole slice, not the piece that was hit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* file.saveACopy refuses the document's own file without "overwrite" (#7437)
Save a Copy through the engine (control channel, MCP, serve, headless
action playback) silently replaced the open document's own file when
given its path, so a lossy re-encode could not be undone. It now returns
BadParams when `path` is the active document's file (same text, ./ or ..
spelling, hard link, case on Windows via same_file) unless the params
pass "overwrite": true, and nothing is written. The desktop dialog writes
through the shell after the OS confirms a replace, so it is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* same_file: compare file identity on Windows, so a hard link is the same file
On Windows `same_file` compared canonical path strings, so a hard link to
the input (another name for the same file) passed the new convert guard
without --in-place. It now compares the volume serial number and file index
(the `same-file` crate, already in the dependency tree; std's file_index is
unstable), as unix compares dev and inode, falling back to the
case-insensitive canonical path when a file won't open. The engine's
same_file test now checks hard links on every platform. (Review on #7454.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* saveACopy own-file test: hard link on every platform, doc state unchanged after a refusal
Each refused copy (same path, ./ spelling, hard link) now also checks the
document keeps its path, revision and unsaved state. The hard link is no
longer unix-only: same_file compares file identity on Windows too. (Review
on #7456.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Image Assets: two layers naming the same file no longer overwrite each other (#6614) [WIP]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Image Assets: two layers naming the same file no longer overwrite each other (#6614)
generate_assets wrote every requested asset, so two layers (or two
default variants) naming one file silently replaced each other and the
result listed the file twice. Each file is now written once per run:
layers go top first, as the Layers panel lists them, the first writer
keeps the name, and later ones are reported in errors. Names are
compared ignoring case, since Logo.png and logo.png are one file on
Windows and macOS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
With Export Preferences › Location = Same Folder, Quick Export wrote
<name>.<format> beside the document's file with no check, so a document
opened from photo.png was exported over photo.png itself. The app now
opens the save dialog for that case, and file.export.quickExport refuses
it without a `path`. Overwriting an earlier export beside a PSD is kept.
Adds file_cmds::same_file (text, dev+inode on Unix, case-insensitive
canonical path on Windows).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* engine: remember the last Save for Web settings in the preferences
* engine: test that a complete export remembers its settings for the next launch
* ui: seed the Save for Web dialog from the remembered preferences
* ui: Export As opens with the settings it was used with last
* scorecard: FILE-215-18 done, the export dialogs remember their settings
* docs: scorecard, File compatibility 7 done of 27
* Regenerate the scorecard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat: resize Save for Web previews and added palette editing for Gif/PNG8
* Save for Web: add Turkish and Hungarian rows for the preview navigation hint
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Save for Web gets a platform-writer entry point (web_cmds::save_for_web_with_writer) so the browser build downloads every image, spacer and HTML file side by side; the export is authorized before any picker opens, a failed write stops it, and only a complete export remembers its settings. Each document now opens the dialog at its own size instead of the last export's width, height and percent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Output file names are made unique (case-insensitively; spacer.gif reserved when
writing HTML). In the HTML table a slice shows only where no later slice covers
it; that visible part is cut into rectangles, each its own cell and image, so a
later overlapping slice's link, text and image are no longer dropped.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
CI's `cargo fmt --all -- --check` has failed on every run because the
repo had no rustfmt config and was never formatted. Use the same settings
as EffectCraft/FilmCraft (max_width 160, use_small_heuristics Max), which
also keeps the churn small. Formatting only; no code changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gradients/Patterns/Styles/Shapes/Tool Presets/Clone Source panels with
headless preset commands and a Custom Shape tool; Color card tabs match
Essentials. Character and Paragraph Styles (doc model, .pcraft, PSD style
sheets), Glyphs panel + type.insertText, Check Spelling (SCOWL-50 list).
Checkpoint also includes compiling in-progress work of the remaining agents.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>