mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-01 21:57:12 -06:00
Merge pull request #5022 from mockydevs/feat/export-all-open-4920
Fix #4920: Document Tools exports every open document
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
//! Document Tools (`addon.document.*`), a built-in add-on: Save a Timestamped Copy writes a copy of
|
||||
//! the document named with the date and time through File › Save a Copy's save; New Symbols from
|
||||
//! Layers makes a symbol of each layer's art as New Symbol does. Its submenu (Object › Plug-ins ›
|
||||
//! Layers makes a symbol of each layer's art as New Symbol does; Export All Open Documents writes a
|
||||
//! copy of every open document to one folder as Save a Copy does (#4920). Its submenu (Object › Plug-ins ›
|
||||
//! Document Tools) is the UI's.
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -30,6 +31,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_clock,
|
||||
save_timestamped_copy
|
||||
),
|
||||
cmd!(
|
||||
"addon.document.exportAllOpen",
|
||||
"Export All Open Documents",
|
||||
["Object", "Plug-ins", "Document Tools"],
|
||||
None,
|
||||
"{folder, format?: vectorcraft|pdf|svg|svgz|ai|eps (default: pdf)} write a copy of every open document, in tab order, to `folder` as File › Save a Copy writes it, each named after its document (<name>.<ext>; -2, -3… added when that name is taken, so no file is replaced): every document keeps its path, title and modified state, and no undo step is made. A document that can't be written is listed in `failed` and the others are still written; the active document stays active → {files: [{title, path, warnings}], failed: [{title, error}], format}",
|
||||
has_doc,
|
||||
export_all_open
|
||||
),
|
||||
cmd!(
|
||||
"addon.document.symbolsFromLayers",
|
||||
"New Symbols from Layers",
|
||||
@@ -88,6 +98,37 @@ fn save_timestamped_copy(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
fileio::save_document(s, SaveMode::Copy, &json!({ "path": path, "format": format.id }))
|
||||
}
|
||||
|
||||
fn export_all_open(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "addon.document.exportAllOpen";
|
||||
let format = fileio::save_format(Some(str_param(p, "format").unwrap_or("pdf")), None).map_err(|e| bad(C, e))?;
|
||||
let folder = str_param(p, "folder").map(str::trim).filter(|f| !f.is_empty()).ok_or_else(|| bad(C, "give `folder`"))?.to_string();
|
||||
let ext = format.extensions.first().copied().ok_or_else(|| bad(C, "the format has no file extension"))?;
|
||||
let (mut files, mut failed, mut written) = (vec![], vec![], Vec::<String>::new());
|
||||
let active = s.active;
|
||||
for i in 0..s.docs.len() {
|
||||
// Each document in turn is the one Save a Copy writes; switching tabs this way leaves every
|
||||
// document's tool and interaction alone, and the active one comes back below.
|
||||
s.active = Some(i);
|
||||
let Ok(st) = s.doc() else { continue };
|
||||
let title = st.doc.title.clone();
|
||||
let stem = fileio::file_stem(st.path.as_deref().unwrap_or(&title));
|
||||
// Names the copies already took count as taken, as do files on disk.
|
||||
let Some(path) = free_name(&folder, &stem, ext, |p| written.iter().any(|w| w == p) || std::path::Path::new(p).exists()) else {
|
||||
failed.push(json!({ "title": title, "error": "every numbered name for the copy is taken" }));
|
||||
continue;
|
||||
};
|
||||
match fileio::save_document(s, SaveMode::Copy, &json!({ "path": path, "format": format.id })) {
|
||||
Ok(r) => {
|
||||
written.push(path.clone());
|
||||
files.push(json!({ "title": title, "path": r.get("path").cloned().unwrap_or(json!(path)), "warnings": r.get("warnings").cloned().unwrap_or(json!([])) }));
|
||||
}
|
||||
Err(e) => failed.push(json!({ "title": title, "error": e.to_string() })),
|
||||
}
|
||||
}
|
||||
s.active = active;
|
||||
Ok(json!({ "files": files, "failed": failed, "format": format.id }))
|
||||
}
|
||||
|
||||
/// `n` with each layer in it, and itself, made a group of the same art and clipping (a symbol holds
|
||||
/// no layers).
|
||||
fn without_layers(n: &Node) -> Node {
|
||||
|
||||
@@ -194,3 +194,26 @@ fn the_layers_highlighted_in_the_layers_panel_are_the_default() {
|
||||
let r = s.execute("addon.document.symbolsFromLayers", &json!({})).unwrap();
|
||||
assert_eq!((r["symbols"].clone(), r["skipped"].as_array().unwrap().len()), (json!(["Icons"]), 1));
|
||||
}
|
||||
|
||||
/// #4920: Export All Open Documents writes an SVG of each open document; a folder that can't be
|
||||
/// written lists every document in `failed`, and either way the active document stays active.
|
||||
#[test]
|
||||
fn export_all_open_documents_writes_each_and_reports_failures() {
|
||||
let dir = std::env::temp_dir().join(format!("vc-export-all-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"width": 100, "height": 100, "name": "one"})).unwrap();
|
||||
s.execute("file.new", &json!({"width": 100, "height": 100, "name": "two"})).unwrap();
|
||||
s.execute("document.activate", &json!({"index": 0})).unwrap();
|
||||
let r = s.execute("addon.document.exportAllOpen", &json!({"folder": dir, "format": "svg"})).unwrap();
|
||||
assert_eq!(r["files"].as_array().unwrap().len(), 2, "{r}");
|
||||
assert!(dir.join("one.svg").exists() && dir.join("two.svg").exists());
|
||||
assert_eq!(s.active_index(), Some(0));
|
||||
assert!(s.documents().iter().all(|d| d.path.is_none()), "the documents stay unsaved");
|
||||
let missing = dir.join("missing").join("deeper");
|
||||
let r = s.execute("addon.document.exportAllOpen", &json!({"folder": missing, "format": "svg"})).unwrap();
|
||||
assert_eq!((r["files"].as_array().unwrap().len(), r["failed"].as_array().unwrap().len()), (0, 2), "{r}");
|
||||
assert_eq!(s.active_index(), Some(0));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//! Document Tools in the interface: its submenu (Object › Plug-ins › Document Tools), which runs
|
||||
//! Save a Timestamped Copy, New Symbols from Layers and Convert Layers to Symbols (the same, with
|
||||
//! each layer's art replaced by an instance). Save a Timestamped Copy of a document never saved
|
||||
//! asks for the folder to put it in ([`save_copy`]).
|
||||
//! asks for the folder to put it in ([`save_copy`]). Export All Open Documents as PDF or SVG asks
|
||||
//! for the folder the copies go in ([`export_all`], #4920).
|
||||
|
||||
use serde_json::{Value, json};
|
||||
|
||||
@@ -10,6 +11,8 @@ use crate::menus::Item;
|
||||
|
||||
/// Save a Timestamped Copy.
|
||||
pub const SAVE_COPY: &str = "addon.document.saveTimestampedCopy";
|
||||
/// Export All Open Documents.
|
||||
pub const EXPORT_ALL: &str = "addon.document.exportAllOpen";
|
||||
/// New Symbols from Layers (Convert Layers to Symbols: with their art replaced by instances).
|
||||
const SYMBOLS: &str = "addon.document.symbolsFromLayers";
|
||||
|
||||
@@ -17,6 +20,8 @@ const SYMBOLS: &str = "addon.document.symbolsFromLayers";
|
||||
pub fn menu() -> Vec<Item> {
|
||||
vec![
|
||||
Item::Cmd("Save a Timestamped Copy", SAVE_COPY, json!({})),
|
||||
Item::Cmd("Export All Open Documents as PDF", EXPORT_ALL, json!({ "format": "pdf" })),
|
||||
Item::Cmd("Export All Open Documents as SVG", EXPORT_ALL, json!({ "format": "svg" })),
|
||||
Item::Sep,
|
||||
Item::Cmd("New Symbols from Layers", SYMBOLS, json!({})),
|
||||
Item::Cmd("Convert Layers to Symbols", SYMBOLS, json!({ "replace": true })),
|
||||
@@ -35,5 +40,27 @@ pub(crate) fn save_copy(app: &mut VectorcraftApp, p: &Value) -> Result<Value, St
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
/// Export All Open Documents with params `p`: without a `folder`, the copies go in the folder
|
||||
/// picked. The status bar says how many were written and names the first that failed.
|
||||
pub(crate) fn export_all(app: &mut VectorcraftApp, p: &Value) -> Result<Value, String> {
|
||||
let mut p = if p.is_object() { p.clone() } else { json!({}) };
|
||||
if p.get("folder").is_none() {
|
||||
p["folder"] = json!(crate::picks::folder(app).ok_or("cancelled")?);
|
||||
}
|
||||
let r = app.session.execute(EXPORT_ALL, &p).map_err(|e| e.to_string())?;
|
||||
let written = r["files"].as_array().map_or(0, Vec::len);
|
||||
let failed = r["failed"].as_array().cloned().unwrap_or_default();
|
||||
let status = match failed.first() {
|
||||
Some(f) => {
|
||||
let args = [("title", f["title"].as_str().unwrap_or_default()), ("error", f["error"].as_str().unwrap_or_default())];
|
||||
let (one, other) = ("Exported {n} document; {title} wasn't written: {error}", "Exported {n} documents; {title} wasn't written: {error}");
|
||||
crate::i18n::msg_n(written as u64, one, other, &args)
|
||||
}
|
||||
None => crate::i18n::msg_n(written as u64, "Exported {n} document", "Exported {n} documents", &[]),
|
||||
};
|
||||
app.status(status);
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@@ -82,3 +82,44 @@ fn new_symbols_from_layers_and_convert_layers_to_symbols() {
|
||||
.all(|l| matches!(l.children().unwrap()[..], [ref one] if matches!(one.kind, vectorcraft_doc::NodeKind::SymbolInstance { .. })))
|
||||
);
|
||||
}
|
||||
|
||||
/// #4920: Export All Open Documents as PDF asks for a folder and writes one PDF per open document,
|
||||
/// named after each, without replacing a file there, and leaves every document as it was.
|
||||
#[test]
|
||||
fn export_all_open_documents_writes_each_to_the_folder_picked() {
|
||||
let dir = folder("export-all");
|
||||
let mut app = app();
|
||||
app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 50, "height": 40})).unwrap();
|
||||
app.run("document.save", json!({"path": dir.join("card.vectorcraft")})).unwrap();
|
||||
app.run("file.new", json!({"width": 200, "height": 100, "name": "card"})).unwrap();
|
||||
app.run("file.new", json!({"width": 200, "height": 100})).unwrap();
|
||||
let untitled = app.session.doc().unwrap().doc.title.clone();
|
||||
let out = dir.join("out");
|
||||
std::fs::create_dir_all(&out).unwrap();
|
||||
std::fs::write(out.join(format!("{untitled}.pdf")), b"keep").unwrap();
|
||||
let picked = out.to_string_lossy().into_owned();
|
||||
app.services.pick_folder = Some(Box::new(move || Some(picked.clone())));
|
||||
let active = app.session.active_index();
|
||||
click(&mut app, "Export All Open Documents as PDF");
|
||||
let mut names = files(&out);
|
||||
names.sort();
|
||||
let mut want = vec!["card.pdf".to_string(), "card-2.pdf".into(), format!("{untitled}.pdf"), format!("{untitled}-2.pdf")];
|
||||
want.sort();
|
||||
assert_eq!(names, want, "one per document, the taken names numbered");
|
||||
assert_eq!(std::fs::read(out.join(format!("{untitled}.pdf"))).unwrap(), b"keep", "no file is replaced");
|
||||
assert!(std::fs::read(out.join("card.pdf")).unwrap().starts_with(b"%PDF"));
|
||||
assert_eq!(app.session.active_index(), active, "the active document stays active");
|
||||
assert!(
|
||||
app.session.documents().iter().all(|d| d.path.as_ref().is_none_or(|p| p.ends_with("card.vectorcraft"))),
|
||||
"no document takes a copy's path"
|
||||
);
|
||||
assert!(app.ui.status.starts_with("Exported 3 documents"), "{}", app.ui.status);
|
||||
// Cancelled: nothing written.
|
||||
app.services.pick_folder = Some(Box::new(|| None));
|
||||
assert_eq!(app.run(super::EXPORT_ALL, json!({})).unwrap_err(), "cancelled");
|
||||
assert_eq!(files(&out).len(), 4);
|
||||
// The engine command refuses a missing folder and an unknown format.
|
||||
assert!(app.session.execute(super::EXPORT_ALL, &json!({})).is_err());
|
||||
assert!(app.session.execute(super::EXPORT_ALL, &json!({"folder": out, "format": "doc"})).is_err());
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
@@ -5993,6 +5993,11 @@ breakText Glyphs Глифи
|
||||
Odia Ория
|
||||
Urdu Урду
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} и по-нови (версия {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Експортиране на всички отворени документи като PDF
|
||||
Export All Open Documents as SVG Експортиране на всички отворени документи като SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Експортиран е {n} документ|Експортирани са {n} документа
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Експортиран е {n} документ; {title} не беше записан: {error}|Експортирани са {n} документа; {title} не беше записан: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Тип на символа:
|
||||
Dynamic Symbol Динамичен символ
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6025,6 +6025,11 @@ shape Open Otvoren
|
||||
Odia Odija
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} i novije (verzija {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Izvezi sve otvorene dokumente kao PDF
|
||||
Export All Open Documents as SVG Izvezi sve otvorene dokumente kao SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Izvezen je {n} dokument|Izvezena su {n} dokumenta|Izvezeno je {n} dokumenata
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Izvezen je {n} dokument; {title} nije zapisan: {error}|Izvezena su {n} dokumenta; {title} nije zapisan: {error}|Izvezeno je {n} dokumenata; {title} nije zapisan: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Vrsta simbola:
|
||||
Dynamic Symbol Dinamički simbol
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6099,6 +6099,11 @@ breakText Glyphs Glifs
|
||||
Odia Oriya
|
||||
Urdu Urdú
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} i posteriors (versió {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Exporta tots els documents oberts com a PDF
|
||||
Export All Open Documents as SVG Exporta tots els documents oberts com a SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents S’ha exportat {n} document|S’han exportat {n} documents
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} S’ha exportat {n} document; no s’ha escrit {title}: {error}|S’han exportat {n} documents; no s’ha escrit {title}: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Tipus de símbol:
|
||||
Dynamic Symbol Símbol dinàmic
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6109,6 +6109,11 @@ breakText Glyphs Glyfy
|
||||
Odia Urijština
|
||||
Urdu Urdština
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} a novější (verze {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Exportovat všechny otevřené dokumenty jako PDF
|
||||
Export All Open Documents as SVG Exportovat všechny otevřené dokumenty jako SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Exportován {n} dokument|Exportovány {n} dokumenty|Exportováno {n} dokumentů
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Exportován {n} dokument; {title} nebyl zapsán: {error}|Exportovány {n} dokumenty; {title} nebyl zapsán: {error}|Exportováno {n} dokumentů; {title} nebyl zapsán: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Typ symbolu:
|
||||
Dynamic Symbol Dynamický symbol
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6008,6 +6008,11 @@ breakText Glyphs Glyffer
|
||||
Odia Oriya
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} og nyere (version {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Eksportér alle åbne dokumenter som PDF
|
||||
Export All Open Documents as SVG Eksportér alle åbne dokumenter som SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Eksporterede {n} dokument|Eksporterede {n} dokumenter
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Eksporterede {n} dokument; {title} blev ikke skrevet: {error}|Eksporterede {n} dokumenter; {title} blev ikke skrevet: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Symboltype:
|
||||
Dynamic Symbol Dynamisk symbol
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5694,6 +5694,11 @@ breakText Glyphs Glyphen
|
||||
Odia Oriya
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} und neuer (Version {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Alle geöffneten Dokumente als PDF exportieren
|
||||
Export All Open Documents as SVG Alle geöffneten Dokumente als SVG exportieren
|
||||
@msgplural Exported {n} document|Exported {n} documents {n} Dokument exportiert|{n} Dokumente exportiert
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} {n} Dokument exportiert; {title} wurde nicht geschrieben: {error}|{n} Dokumente exportiert; {title} wurde nicht geschrieben: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Symboltyp:
|
||||
Dynamic Symbol Dynamisches Symbol
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6061,6 +6061,11 @@ breakText Glyphs Γλύφοι
|
||||
Odia Όντια
|
||||
Urdu Ούρντου
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} και νεότερες (έκδοση {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Εξαγωγή όλων των ανοιχτών εγγράφων ως PDF
|
||||
Export All Open Documents as SVG Εξαγωγή όλων των ανοιχτών εγγράφων ως SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Εξήχθη {n} έγγραφο|Εξήχθησαν {n} έγγραφα
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Εξήχθη {n} έγγραφο; το {title} δεν γράφτηκε: {error}|Εξήχθησαν {n} έγγραφα; το {title} δεν γράφτηκε: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Τύπος συμβόλου:
|
||||
Dynamic Symbol Δυναμικό σύμβολο
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 164 and column 5.
|
@@ -6051,6 +6051,11 @@ breakText Glyphs Glifos
|
||||
Odia Oriya
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} y posteriores (versión {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Exportar todos los documentos abiertos como PDF
|
||||
Export All Open Documents as SVG Exportar todos los documentos abiertos como SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Se exportó {n} documento|Se exportaron {n} documentos
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Se exportó {n} documento; no se escribió {title}: {error}|Se exportaron {n} documentos; no se escribió {title}: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Tipo de símbolo:
|
||||
Dynamic Symbol Símbolo dinámico
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6139,6 +6139,11 @@ breakText Glyphs Merkit
|
||||
Odia Orija
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} ja uudemmat (versio {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Vie kaikki avoimet asiakirjat PDF-muodossa
|
||||
Export All Open Documents as SVG Vie kaikki avoimet asiakirjat SVG-muodossa
|
||||
@msgplural Exported {n} document|Exported {n} documents Vietiin {n} asiakirja|Vietiin {n} asiakirjaa
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Vietiin {n} asiakirja; {title} jäi kirjoittamatta: {error}|Vietiin {n} asiakirjaa; {title} jäi kirjoittamatta: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Symbolin tyyppi:
|
||||
Dynamic Symbol Dynaaminen symboli
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6106,6 +6106,11 @@ breakText Glyphs Glyphes
|
||||
Odia Odia
|
||||
Urdu Ourdou
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} et ultérieures (version {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Exporter tous les documents ouverts en PDF
|
||||
Export All Open Documents as SVG Exporter tous les documents ouverts en SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents {n} document exporté|{n} documents exportés
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} {n} document exporté; {title} n’a pas été écrit : {error}|{n} documents exportés; {title} n’a pas été écrit : {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Type de symbole :
|
||||
Dynamic Symbol Symbole dynamique
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6095,6 +6095,11 @@ breakText Glyphs Glifák
|
||||
Odia Odia
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} és újabb (verzió: {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Az összes megnyitott dokumentum exportálása PDF-ként
|
||||
Export All Open Documents as SVG Az összes megnyitott dokumentum exportálása SVG-ként
|
||||
@msgplural Exported {n} document|Exported {n} documents Exportált dokumentumok: {n}
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Exportált dokumentumok: {n}; {title} nem lett kiírva: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Szimbólum típusa:
|
||||
Dynamic Symbol Dinamikus szimbólum
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6008,6 +6008,11 @@ breakText Glyphs Glif
|
||||
Odia Oriya
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} dan yang lebih baru (versi {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Ekspor Semua Dokumen Terbuka sebagai PDF
|
||||
Export All Open Documents as SVG Ekspor Semua Dokumen Terbuka sebagai SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Berhasil mengekspor {n} dokumen
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Berhasil mengekspor {n} dokumen; {title} tidak ditulis: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Jenis simbol:
|
||||
Dynamic Symbol Simbol dinamis
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2190 and column 5.
|
@@ -5728,6 +5728,11 @@ breakText Glyphs Glifi
|
||||
Odia Odia
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} e successive (versione {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Esporta tutti i documenti aperti come PDF
|
||||
Export All Open Documents as SVG Esporta tutti i documenti aperti come SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Esportato {n} documento|Esportati {n} documenti
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Esportato {n} documento; {title} non è stato scritto: {error}|Esportati {n} documenti; {title} non è stato scritto: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Tipo di simbolo:
|
||||
Dynamic Symbol Simbolo dinamico
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5795,6 +5795,11 @@ breakText Glyphs 字形
|
||||
Odia オディア語
|
||||
Urdu ウルドゥー語
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} 以降 (バージョン {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF 開いているすべてのドキュメントを PDF として書き出し
|
||||
Export All Open Documents as SVG 開いているすべてのドキュメントを SVG として書き出し
|
||||
@msgplural Exported {n} document|Exported {n} documents {n} 個のドキュメントを書き出しました
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} {n} 個のドキュメントを書き出しました; {title} は書き出されませんでした: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: シンボルの種類:
|
||||
Dynamic Symbol ダイナミックシンボル
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6098,6 +6098,11 @@ breakText Glyphs გლიფები
|
||||
Odia ორია
|
||||
Urdu ურდუ
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} და უფრო ახალი (ვერსია {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF ყველა ღია დოკუმენტის ექსპორტი PDF-ად
|
||||
Export All Open Documents as SVG ყველა ღია დოკუმენტის ექსპორტი SVG-ად
|
||||
@msgplural Exported {n} document|Exported {n} documents ექსპორტირებულია დოკუმენტი ({n})
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} ექსპორტირებულია დოკუმენტი ({n}); {title} არ ჩაიწერა: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: სიმბოლოს ტიპი:
|
||||
Dynamic Symbol დინამიკური სიმბოლო
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -5691,6 +5691,11 @@ breakText Glyphs 글리프
|
||||
Odia 오리야어
|
||||
Urdu 우르두어
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} 이상 (버전 {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF 열린 모든 문서를 PDF로 내보내기
|
||||
Export All Open Documents as SVG 열린 모든 문서를 SVG로 내보내기
|
||||
@msgplural Exported {n} document|Exported {n} documents 문서 {n}개를 내보냈습니다
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} 문서 {n}개를 내보냈습니다; {title}을(를) 쓰지 못했습니다: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: 심볼 유형:
|
||||
Dynamic Symbol 동적 심볼
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6052,6 +6052,11 @@ breakText Glyphs Glyphs
|
||||
Odia Odia
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} en nieuwer (versie {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Alle geopende documenten exporteren als PDF
|
||||
Export All Open Documents as SVG Alle geopende documenten exporteren als SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents {n} document geëxporteerd|{n} documenten geëxporteerd
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} {n} document geëxporteerd; {title} is niet geschreven: {error}|{n} documenten geëxporteerd; {title} is niet geschreven: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Symbooltype:
|
||||
Dynamic Symbol Dynamisch symbool
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5964,6 +5964,11 @@ breakText Glyphs Glify
|
||||
Odia Orija
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} i nowsze (wersja {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Eksportuj wszystkie otwarte dokumenty jako PDF
|
||||
Export All Open Documents as SVG Eksportuj wszystkie otwarte dokumenty jako SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Wyeksportowano {n} dokument|Wyeksportowano {n} dokumenty|Wyeksportowano {n} dokumentów
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Wyeksportowano {n} dokument; nie zapisano {title}: {error}|Wyeksportowano {n} dokumenty; nie zapisano {title}: {error}|Wyeksportowano {n} dokumentów; nie zapisano {title}: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Typ symbolu:
|
||||
Dynamic Symbol Symbol dynamiczny
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6028,6 +6028,11 @@ breakText Glyphs Glifos
|
||||
Odia Oriá
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} e posteriores (versão {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Exportar todos os documentos abertos como PDF
|
||||
Export All Open Documents as SVG Exportar todos os documentos abertos como SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents {n} documento exportado|{n} documentos exportados
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} {n} documento exportado; {title} não foi gravado: {error}|{n} documentos exportados; {title} não foi gravado: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Tipo de símbolo:
|
||||
Dynamic Symbol Símbolo dinâmico
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -6086,6 +6086,11 @@ breakText Glyphs Глифы
|
||||
Odia Ория
|
||||
Urdu Урду
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} и новее (версия {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Экспортировать все открытые документы в PDF
|
||||
Export All Open Documents as SVG Экспортировать все открытые документы в SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Экспортирован {n} документ|Экспортировано {n} документа|Экспортировано {n} документов
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Экспортирован {n} документ; {title} не записан: {error}|Экспортировано {n} документа; {title} не записан: {error}|Экспортировано {n} документов; {title} не записан: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Тип символа:
|
||||
Dynamic Symbol Динамический символ
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6161,6 +6161,11 @@ breakText Glyphs Glyfer
|
||||
Odia Oriya
|
||||
Urdu Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} och senare (version {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Exportera alla öppna dokument som PDF
|
||||
Export All Open Documents as SVG Exportera alla öppna dokument som SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Exporterade {n} dokument|Exporterade {n} dokument
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Exporterade {n} dokument; {title} skrevs inte: {error}|Exporterade {n} dokument; {title} skrevs inte: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Symboltyp:
|
||||
Dynamic Symbol Dynamisk symbol
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -6066,6 +6066,11 @@ breakText Glyphs Glifler
|
||||
Odia Oriya dili
|
||||
Urdu Urduca
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} ve sonrası (sürüm {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Tüm Açık Belgeleri PDF Olarak Dışa Aktar
|
||||
Export All Open Documents as SVG Tüm Açık Belgeleri SVG Olarak Dışa Aktar
|
||||
@msgplural Exported {n} document|Exported {n} documents {n} belge dışa aktarıldı
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} {n} belge dışa aktarıldı; {title} yazılamadı: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Sembol Türü:
|
||||
Dynamic Symbol Dinamik Sembol
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -5708,6 +5708,11 @@ breakText Glyphs Гліфи
|
||||
Odia Одія
|
||||
Urdu Урду
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} і новіші (версія {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Експортувати всі відкриті документи як PDF
|
||||
Export All Open Documents as SVG Експортувати всі відкриті документи як SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Експортовано {n} документ|Експортовано {n} документи|Експортовано {n} документів
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Експортовано {n} документ; {title} не записано: {error}|Експортовано {n} документи; {title} не записано: {error}|Експортовано {n} документів; {title} не записано: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Тип символу:
|
||||
Dynamic Symbol Динамічний символ
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 178 and column 5.
|
@@ -5711,6 +5711,11 @@ breakText Glyphs Glyph
|
||||
Odia Tiếng Odia
|
||||
Urdu Tiếng Urdu
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} trở lên (phiên bản {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF Xuất tất cả tài liệu đang mở dưới dạng PDF
|
||||
Export All Open Documents as SVG Xuất tất cả tài liệu đang mở dưới dạng SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents Đã xuất {n} tài liệu
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} Đã xuất {n} tài liệu; không ghi được {title}: {error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: Kiểu ký hiệu:
|
||||
Dynamic Symbol Ký hiệu động
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 200 and column 5.
|
@@ -5951,6 +5951,11 @@ breakText Glyphs 字形
|
||||
Odia 奥里亚语
|
||||
Urdu 乌尔都语
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} 及更高版本 (版本 {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF 将所有打开的文档导出为 PDF
|
||||
Export All Open Documents as SVG 将所有打开的文档导出为 SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents 已导出 {n} 个文档
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} 已导出 {n} 个文档; 未写入 {title}:{error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: 符号类型:
|
||||
Dynamic Symbol 动态符号
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5748,6 +5748,11 @@ breakText Glyphs 字符
|
||||
Odia 歐利亞文
|
||||
Urdu 烏都文
|
||||
VectorCraft {release} and later (version {n}) VectorCraft {release} 及更新版本 (版本 {n})
|
||||
# Document Tools add-on: Export All Open Documents (#4920).
|
||||
Export All Open Documents as PDF 將所有開啟的文件匯出為 PDF
|
||||
Export All Open Documents as SVG 將所有開啟的文件匯出為 SVG
|
||||
@msgplural Exported {n} document|Exported {n} documents 已匯出 {n} 份文件
|
||||
@msgplural Exported {n} document; {title} wasn't written: {error}|Exported {n} documents; {title} wasn't written: {error} 已匯出 {n} 份文件; 未寫入 {title}:{error}
|
||||
# Symbol Options › Symbol Type (dynamic symbols)
|
||||
Symbol Type: 符號類型:
|
||||
Dynamic Symbol 動態符號
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -531,6 +531,7 @@ fn run_ui_part6(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<Result<
|
||||
crate::addons::pathtools::shared_edge::COMMAND => crate::addons::pathtools::shared_edge::open(app),
|
||||
crate::addons::arrange::ZOOM => crate::addons::arrange::zoom(app),
|
||||
crate::addons::document::SAVE_COPY => crate::addons::document::save_copy(app, p),
|
||||
crate::addons::document::EXPORT_ALL => crate::addons::document::export_all(app, p),
|
||||
"tool.setOption" => app.session.set_tool_option_cmd(p),
|
||||
"effect.dialog" => crate::dialogs::open_effect_dialog(app, p),
|
||||
"ui.recolorDialog" => crate::dialogs::recolor::open(app, p),
|
||||
|
||||
+12
@@ -6401,6 +6401,18 @@ command is off where there is no clock (the web). → `{path, format, bytes, war
|
||||
{"name":"run_command","arguments":{"command":"addon.document.saveTimestampedCopy","params":{"folder":"/Users/me/Versions","format":"pdf"}}}
|
||||
```
|
||||
|
||||
`addon.document.exportAllOpen {folder, format?}` writes a copy of every open document, in tab order, to `folder`,
|
||||
each named after its document (`<name>.<ext>`, with `-2`, `-3`… added when that name is taken there or by another
|
||||
copy, so no file is replaced). `format` is a save format (`pdf` by default; `svg`, `svgz`, `vectorcraft`, `ai`,
|
||||
`eps`). Each copy is written as `file.saveCopy` writes it, inside the automation roots in force: every document keeps
|
||||
its path, title and modified state, no undo step is made, and the active document stays active. A document that
|
||||
can't be written is listed in `failed` and the others are still written (#4920). The desktop app's Export All Open
|
||||
Documents as PDF and as SVG ask for the folder. → `{files: [{title, path, warnings}], failed: [{title, error}], format}`
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"addon.document.exportAllOpen","params":{"folder":"/Users/me/Out","format":"svg"}}}
|
||||
```
|
||||
|
||||
`addon.document.symbolsFromLayers {layers?, replace?}` makes one symbol of each top-level layer's art, as `symbol.new`
|
||||
makes one (registration in the centre), named after the layer with a number added when a symbol has that name, as
|
||||
one undo step. `layers` lists layer ids (top-level layers only; anything else is refused); by default it takes the
|
||||
|
||||
@@ -1448,10 +1448,15 @@ A VectorCraft addition, not a feature of the reference app, so no area score mov
|
||||
|
||||
Symbols area (#4938), from the public symbol documentation ([create and place symbols](https://helpx.adobe.com/illustrator/desktop/manage-objects/traces-mockups-symbols/create-and-place-symbols.html), [edit symbols](https://helpx.adobe.com/illustrator/desktop/manage-objects/traces-mockups-symbols/edit-symbols.html)). Symbol Options has Symbol Type (Dynamic Symbol / Static Symbol; the dialog's default is Dynamic, `symbol.new`'s `type` defaults to static so scripts behave as before). An instance of a dynamic symbol keeps its own fill, stroke, opacity and blend for any object of the symbol's art, named by a child-index path (`symbol.instance.setAppearance`), and stays an instance: the canvas, SVG, PDF, EPS, legacy `.ai`, EMF/WMF and DXF writers, effects and Expand draw the art with those changes. Redefining the symbol reshapes every instance and keeps each change whose object the new art still has; Break Link bakes the changes into the art; Edit Symbol expands the symbol's own art; Reset (`symbol.instance.reset`: the Properties panel's Quick Actions and the Symbols panel menu) and making the symbol static drop them. The type is stored on the symbol and the changes on the instance in the native format, both left out when unset, so documents without them save byte for byte as before. Remaining: Direct Selection of an object inside a dynamic instance on the canvas (with the Fill/Stroke controls then setting its change), and reading and writing the type and changes in `.ai` files. Evidence: `crates/engine/src/tests/dynamic_symbols.rs`, `crates/doc/src/symbol_overrides.rs` tests. Score unchanged at 87% (estimated); hours 5–9 → 4–8.
|
||||
|
||||
## Document Tools add-on: Export All Open Documents (2026-11-01)
|
||||
|
||||
A VectorCraft addition, not a feature of the reference app, so no area score moves. Object › Plug-ins › Document Tools › Export All Open Documents as PDF (or as SVG) asks for a folder and writes a copy of every open document there, each named after its document with `-2`, `-3`… added when a name is taken, so no file is replaced (`addon.document.exportAllOpen {folder, format?}`, #4920). Each copy is written as Save a Copy writes it: the documents keep their paths, titles and modified state, and the active one stays active. A document that can't be written is named in the status bar and the others are still written. Tests: `addons::document::tests::export_all_open_documents_writes_each_to_the_folder_picked` (ui-egui), `cmd::addons::document::tests::export_all_open_documents_writes_each_and_reports_failures` (engine).
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-01 | minor | Document Tools add-on (a VectorCraft addition): Export All Open Documents as PDF or SVG (#4920); evidence added; scores unchanged. |
|
||||
| 2026-11-01 | minor | Path Precision Tools add-on (a VectorCraft addition): Expand Dashes into Paths (#4922); evidence added; scores unchanged. |
|
||||
| 2026-11-01 | minor | Type core: the Glyphs panel highlights the character selected with the Type tool and scrolls it into view (#4908); evidence added; scores unchanged. |
|
||||
| 2026-11-01 | minor | Arrange Tools add-on (a VectorCraft addition): Randomize Opacity (#4925); evidence added; scores unchanged. |
|
||||
|
||||
@@ -337,6 +337,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
|
||||
| Arrange Tools add-on (VectorCraft addition): Object › Plug-ins › Arrange Tools › Randomize Opacity… gives each selected object its own opacity at random between Minimum and Maximum (%), with a Seed that repeats it and Preview, one undo step | done | #4925; `addon.arrange.randomizeOpacity`, `crates/engine/src/cmd/addons/arrange.rs`, `crates/ui-egui/src/addons/arrange.rs` and their tests; not a feature of the reference app, so it is not scored |
|
||||
| Arrange Tools add-on (VectorCraft addition): Object › Plug-ins › Arrange Tools › Sort Objects… sorts the selected objects by Sort By (width, height, area, X or Y position, opacity, stacking order) in an Order (Small to Large, Large to Small, Random) and gives them Apply To in that order, trading the values or with Distribute Evenly; Scale Strokes & Effects; Preview; one undo step | done | #4917; `addon.arrange.sort`, `crates/engine/src/cmd/addons/arrange.rs`, `crates/ui-egui/src/addons/arrange.rs` and their tests; not a feature of the reference app, so it is not scored |
|
||||
| Document Tools add-on (VectorCraft addition): Object › Plug-ins › Document Tools › Save a Timestamped Copy writes `<name>_YYYY-MM-DD_HH-MM.<ext>` next to the document (a folder picked for one never saved), which keeps its path, title and modified state; off on the web | done | #4926; `addon.document.saveTimestampedCopy`, `crates/engine/src/cmd/addons/document.rs`, `crates/ui-egui/src/addons/document.rs` and their tests; not a feature of the reference app, so it is not scored |
|
||||
| Document Tools add-on (VectorCraft addition): Export All Open Documents as PDF / as SVG (#4920) | done | asks for a folder, writes a copy of every open document named after it (taken names numbered, nothing replaced), documents and active tab unchanged; failures named in the status bar |
|
||||
| Document Tools add-on (VectorCraft addition): Object › Plug-ins › Document Tools › New Symbols from Layers makes a symbol of each layer's art named after the layer (the highlighted layers when two or more are, else all); Convert Layers to Symbols also replaces each layer's art with an instance in place; empty layers skipped, one undo step | done | #4927; `addon.document.symbolsFromLayers`, `crates/engine/src/cmd/addons/document.rs`, `crates/ui-egui/src/addons/document.rs` and their tests; not a feature of the reference app, so it is not scored |
|
||||
| Smart Pen add-on (VectorCraft addition): Object › Plug-ins › Smart Pen selects the Smart Pen Tool, which the All Tools drawer lists under its own heading but neither toolbar shows as shipped (no shortcut), and opens the Smart Pen panel (next segment straight or curved; Remove Points Keep Shape, Make Smooth, Make Corner, Retract Handles, Close or Join). The tool draws (click: straight or curved segment, a curve after a straight one tangent; drag: smooth anchor, Alt breaks the handle, Shift 45°, Space moves it; Tab switches a segment; rubber band; close, join, continue) and edits without switching tools (click selects a point, drag moves it, Alt-click removes it keeping the shape, Shift+Alt-click deletes it, double-click toggles smooth/corner; handle drags with Shift and Alt; segment drags reshape, Alt-click adds a point) | done | `addon.pen.*`, `crates/tools/src/addons/smart_pen.rs`, `crates/ui-egui/src/addons/pen.rs` and their tests; not a feature of the reference app, so it is not scored |
|
||||
| Path Precision Tools add-on (VectorCraft addition): Object › Plug-ins › Path Precision Tools selects its seven tools (Anchor Eraser Brush, Extend Path, Measure & Inspect, Parametric Shape, Corner Tool, Slide Anchor Along Path, Shared Edge Merge Tool), which the All Tools drawer lists under their own heading but neither toolbar shows as shipped, opens the Anchor Inspector panel (the selected anchor's X/Y and handle lengths and angles as fields; Make Smooth, Make Corner, Equalize Handles, Remove Points Keep Shape, Add Points, the three ways to close) and the Parametric Shape panel (kind, count, W/H, rotation, the kind's own values and corner radius of the selected parametric shape, or of the tool's next one), and runs Add Points at / Split at Crossings and Convert to Parametric Shape; the Parametric Shape Tool draws ten re-editable kinds from the centre (↑/↓ and ←/→ change their numbers while dragging) and edits a selected one with handles; the Corner Tool cuts editable corners on any path (hover shows the anchor, a click uses its radius and kind, a drag sizes the corner, Shift whole values; a corner's marker selects it and loads its values, drags to resize, to 0 or double-clicked removes it; never past what fits; Alt-marquee cuts every anchor inside) with a Corners section in the Anchor Inspector (radius, kind, selected count, Apply to Selected Anchors); Slide Anchor Along Path drags an anchor along its curve with the segments beside it refitted, Shift snapping where the tangent is a multiple of 45°; the Shared Edge Merge Tool shows, over two paths touching at two coincident anchors, the two stretches and the edge merging them, a click merges them (half way; Shift the upper path, Alt the lower), and near anchors meet or an anchor one path lacks is added to match (Shift+Alt asks for this inside a stretch), with a Shared Edges section in the Anchor Inspector (brush diameter, coincidence 0 to 3 pt, Keep Shared Points Together, which takes coincident anchors along with the add-on's own anchor moves); a double-click on the brush or Extend Path tool opens its options | done | `addon.pathtools.*`, `crates/tools/src/addons/`, `crates/ui-egui/src/addons/pathtools.rs`, `crates/ui-egui/src/addons/pathtools/` and their tests; not a feature of the reference app, so it is not scored |
|
||||
@@ -392,6 +393,7 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-01 | minor | Document Tools add-on (a VectorCraft addition): Export All Open Documents as PDF or SVG (#4920); scores and estimates unchanged |
|
||||
| 2026-11-01 | minor | Path Precision Tools add-on (a VectorCraft addition): Expand Dashes into Paths (#4922); scores and estimates unchanged |
|
||||
| 2026-11-01 | minor | Arrange Tools add-on (a VectorCraft addition): Randomize Opacity (#4925); scores and estimates unchanged |
|
||||
| 2026-11-01 | minor | Arrange Tools add-on (a VectorCraft addition): Sort Objects (#4917); scores and estimates unchanged |
|
||||
|
||||
Reference in New Issue
Block a user