This commit is contained in:
aiongg
2026-10-25 02:21:44 +00:00
21 changed files with 65 additions and 29 deletions
+1 -1
View File
@@ -304,7 +304,6 @@ status = "draft — needs native review"
"Constraints" = "সীমাবদ্ধতা (Constraints)"
"Content" = "কন্টেন্ট"
"Contents hidden" = "কন্টেন্ট লুকানো আছে"
"Contents only" = "শুধু কন্টেন্ট"
"Contextual alternates" = "প্রসঙ্গভিত্তিক বিকল্প"
"Contrast" = "কনট্রাস্ট (Contrast)"
"Contributors" = "অবদানকারীগণ"
@@ -628,6 +627,7 @@ status = "draft — needs native review"
"If" = "যদি (If)"
"If {condition}" = "যদি {condition}"
"Ignore auto layout (absolute position)" = "অটো লেআউট উপেক্ষা করুন (অ্যাবসোলিউট পজিশন)"
"Ignore overlapping layers" = "ওভারল্যাপ করা লেয়ার উপেক্ষা করুন"
"Image" = "ছবি"
"Images" = "ছবিসমূহ"
"Import" = "ইম্পোর্ট"
+1 -1
View File
@@ -295,7 +295,6 @@ status = "draft — needs native review"
"Constraints" = "Omezení"
"Content" = "Obsah"
"Contents hidden" = "Obsah skryt"
"Contents only" = "Pouze obsah"
"Contextual alternates" = "Kontextové alternativy"
"Contrast" = "Kontrast"
"Contributors" = "Přispěvatelé"
@@ -613,6 +612,7 @@ status = "draft — needs native review"
"If" = "Pokud"
"If {condition}" = "Pokud {condition}"
"Ignore auto layout (absolute position)" = "Ignorovat automatické rozvržení (absolutní poloha)"
"Ignore overlapping layers" = "Ignorovat překrývající se vrstvy"
"Image" = "Obrázek"
"Images" = "Obrázky"
"Import" = "Import"
+1 -1
View File
@@ -291,7 +291,6 @@ status = "draft — needs native review"
"Constraints" = "Constraints"
"Content" = "Inhalt"
"Contents hidden" = "Inhalt ausgeblendet"
"Contents only" = "Nur Inhalt"
"Contextual alternates" = "Kontextbedingte Varianten"
"Contrast" = "Kontrast"
"Contributors" = "Mitwirkende"
@@ -600,6 +599,7 @@ status = "draft — needs native review"
"If" = "Wenn"
"If {condition}" = "Wenn {condition}"
"Ignore auto layout (absolute position)" = "Auto-Layout ignorieren (absolute Position)"
"Ignore overlapping layers" = "Überlappende Ebenen ignorieren"
"Image" = "Bild"
"Images" = "Bilder"
"Import" = "Importieren"
+1 -1
View File
@@ -305,7 +305,6 @@ name = "English"
"Constraints" = "Constraints"
"Content" = "Content"
"Contents hidden" = "Contents hidden"
"Contents only" = "Contents only"
"Contextual alternates" = "Contextual alternates"
"Contrast" = "Contrast"
"Contributors" = "Contributors"
@@ -632,6 +631,7 @@ name = "English"
"If" = "If"
"If {condition}" = "If {condition}"
"Ignore auto layout (absolute position)" = "Ignore auto layout (absolute position)"
"Ignore overlapping layers" = "Ignore overlapping layers"
"Image" = "Image"
"Images" = "Images"
"Import" = "Import"
+1 -1
View File
@@ -305,7 +305,6 @@ status = "draft — needs native review"
"Constraints" = "Restricciones"
"Content" = "Contenido"
"Contents hidden" = "Contenido oculto"
"Contents only" = "Solo el contenido"
"Contextual alternates" = "Alternativas contextuales"
"Contrast" = "Contraste"
"Contributors" = "Colaboradores"
@@ -632,6 +631,7 @@ status = "draft — needs native review"
"If" = "Si"
"If {condition}" = "Si {condition}"
"Ignore auto layout (absolute position)" = "Ignorar diseño automático (posición absoluta)"
"Ignore overlapping layers" = "Ignorar capas superpuestas"
"Image" = "Imagen"
"Images" = "Imágenes"
"Import" = "Importar"
+1 -1
View File
@@ -303,7 +303,6 @@ status = "draft — needs native review"
"Constraints" = "Rajoitteet"
"Content" = "Sisältö"
"Contents hidden" = "Sisältö kätketty"
"Contents only" = "Vain sisältö"
"Contextual alternates" = "Kontekstuaaliset vaihtoehdot"
"Contrast" = "Kontrasti"
"Contributors" = "Tekijät"
@@ -630,6 +629,7 @@ status = "draft — needs native review"
"If it keeps happening, please report it at {link} with this message." = "Jos ongelma jatkuu, ilmoita siitä osoitteessa {link} ja liitä tämä viesti mukaan."
"If {condition}" = "Jos {condition}"
"Ignore auto layout (absolute position)" = "Ohita automaattinen asettelu (absoluuttinen sijainti)"
"Ignore overlapping layers" = "Ohita päällekkäiset tasot"
"Image" = "Kuva"
"Images" = "Kuvat"
"Import" = "Tuo"
+1 -1
View File
@@ -301,7 +301,6 @@ status = "draft — needs native review"
"Constraints" = "Contraintes"
"Content" = "Contenu"
"Contents hidden" = "Contenu masqué"
"Contents only" = "Contenu uniquement"
"Contextual alternates" = "Variantes contextuelles"
"Contrast" = "Contraste"
"Contributors" = "Contributeurs"
@@ -629,6 +628,7 @@ status = "draft — needs native review"
"If" = "Si"
"If {condition}" = "Si {condition}"
"Ignore auto layout (absolute position)" = "Ignorer la mise en page auto (position absolue)"
"Ignore overlapping layers" = "Ignorer les calques superposés"
"Image" = "Image"
"Images" = "Images"
"Import" = "Importer"
+1 -1
View File
@@ -299,7 +299,6 @@ status = "draft — needs native review"
"Constraints" = "Batasan"
"Content" = "Konten"
"Contents hidden" = "Konten disembunyikan"
"Contents only" = "Hanya konten"
"Contextual alternates" = "Alternatif kontekstual"
"Contrast" = "Kontras"
"Contributors" = "Kontributor"
@@ -617,6 +616,7 @@ status = "draft — needs native review"
"If" = "Jika"
"If {condition}" = "Jika {condition}"
"Ignore auto layout (absolute position)" = "Abaikan auto layout (posisi absolut)"
"Ignore overlapping layers" = "Abaikan layer yang tumpang tindih"
"Image" = "Gambar"
"Images" = "Gambar"
"Import" = "Impor"
+1 -1
View File
@@ -302,7 +302,6 @@ status = "draft — needs native review"
"Constraints" = "制約"
"Content" = "コンテンツ"
"Contents hidden" = "コンテンツ非表示"
"Contents only" = "コンテンツのみ"
"Contextual alternates" = "前後関係に依存する字形"
"Contrast" = "コントラスト"
"Contributors" = "貢献者"
@@ -624,6 +623,7 @@ status = "draft — needs native review"
"If" = "条件"
"If {condition}" = "条件:{condition}"
"Ignore auto layout (absolute position)" = "オートレイアウトを無視(絶対位置)"
"Ignore overlapping layers" = "重なっているレイヤーを無視"
"Image" = "画像"
"Images" = "画像"
"Import" = "インポート"
+1 -1
View File
@@ -306,7 +306,6 @@ status = "draft — reviewed by a native speaker, awaiting a maintainer's approv
"Constraints" = "შეზღუდვები"
"Content" = "შიგთავსი"
"Contents hidden" = "შიგთავსი დამალულია"
"Contents only" = "მხოლოდ შიგთავსი"
"Contextual alternates" = "კონტექსტური ალტერნატივები"
"Contrast" = "კონტრასტი"
"Contributors" = "მონაწილეები"
@@ -630,6 +629,7 @@ status = "draft — reviewed by a native speaker, awaiting a maintainer's approv
"If" = "თუ"
"If {condition}" = "თუ {condition}"
"Ignore auto layout (absolute position)" = "ავტოგანლაგების იგნორირება (აბსოლუტური პოზიცია)"
"Ignore overlapping layers" = "გადაფარული შრეების იგნორირება"
"Image" = "გამოსახულება"
"Images" = "გამოსახულებები"
"Import" = "იმპორტი"
+1 -1
View File
@@ -291,7 +291,6 @@ status = "draft — needs native review"
"Constraints" = "제약"
"Content" = "콘텐츠"
"Contents hidden" = "콘텐츠 숨김"
"Contents only" = "콘텐츠만"
"Contextual alternates" = "문맥 대체 글자"
"Contrast" = "대비"
"Contributors" = "기여자"
@@ -596,6 +595,7 @@ status = "draft — needs native review"
"If" = "조건"
"If {condition}" = "조건: {condition}"
"Ignore auto layout (absolute position)" = "자동 레이아웃 무시(절대 위치)"
"Ignore overlapping layers" = "겹치는 레이어 무시"
"Image" = "이미지"
"Images" = "이미지"
"Import" = "가져오기"
+1 -1
View File
@@ -303,7 +303,6 @@ status = "draft — needs native review"
"Constraints" = "Constraints"
"Content" = "Inhoud"
"Contents hidden" = "Inhoud verborgen"
"Contents only" = "Alleen de inhoud"
"Contextual alternates" = "Contextuele alternatieven"
"Contrast" = "Contrast"
"Contributors" = "Bijdragers"
@@ -630,6 +629,7 @@ status = "draft — needs native review"
"If it keeps happening, please report it at {link} with this message." = "Als dit blijft gebeuren, meld het dan op {link} met dit bericht."
"If {condition}" = "Als {condition}"
"Ignore auto layout (absolute position)" = "Auto layout negeren (absolute positie)"
"Ignore overlapping layers" = "Overlappende lagen negeren"
"Image" = "Afbeelding"
"Images" = "Afbeeldingen"
"Import" = "Importeren"
+1 -1
View File
@@ -302,7 +302,6 @@ status = "draft — needs native review"
"Constraints" = "Więzy"
"Content" = "Zawartość"
"Contents hidden" = "Zawartość ukryta"
"Contents only" = "Tylko zawartość"
"Contextual alternates" = "Alternatywy kontekstowe"
"Contrast" = "Kontrast"
"Contributors" = "Współtwórcy"
@@ -627,6 +626,7 @@ status = "draft — needs native review"
"If" = "Jeżeli"
"If {condition}" = "Jeżeli {condition}"
"Ignore auto layout (absolute position)" = "Ignoruj automatyczny układ (pozycja bezwzględna)"
"Ignore overlapping layers" = "Ignoruj nakładające się warstwy"
"Image" = "Obraz"
"Images" = "Obrazy"
"Import" = "Importuj"
+1 -1
View File
@@ -289,7 +289,6 @@ status = "draft — needs native review"
"Constraints" = "Restrições"
"Content" = "Conteúdo"
"Contents hidden" = "Conteúdo oculto"
"Contents only" = "Somente o conteúdo"
"Contextual alternates" = "Alternativas contextuais"
"Contrast" = "Contraste"
"Contributors" = "Colaboradores"
@@ -595,6 +594,7 @@ status = "draft — needs native review"
"If" = "Se"
"If {condition}" = "Se {condition}"
"Ignore auto layout (absolute position)" = "Ignorar layout automático (posição absoluta)"
"Ignore overlapping layers" = "Ignorar camadas sobrepostas"
"Image" = "Imagem"
"Images" = "Imagens"
"Import" = "Importar"
+1 -1
View File
@@ -302,7 +302,6 @@ name = "Русский"
"Constraints" = "Ограничения"
"Content" = "Содержимое"
"Contents hidden" = "Содержимое скрыто"
"Contents only" = "Только содержимое"
"Contextual alternates" = "Контекстные альтернативы"
"Contrast" = "Контраст"
"Contributors" = "Участники"
@@ -629,6 +628,7 @@ name = "Русский"
"If it keeps happening, please report it at {link} with this message." = "Если это повторяется, сообщите об этом по адресу {link}, приложив это сообщение."
"If {condition}" = "Если {condition}"
"Ignore auto layout (absolute position)" = "Игнорировать автолейаут (абсолютная позиция)"
"Ignore overlapping layers" = "Игнорировать перекрывающиеся слои"
"Image" = "Изображение"
"Images" = "Изображения"
"Import" = "Импорт"
+1 -1
View File
@@ -299,7 +299,6 @@ name = "Svenska"
"Constraints" = "Begränsningar"
"Content" = "Innehåll"
"Contents hidden" = "Innehållet är dolt"
"Contents only" = "Endast innehåll"
"Contextual alternates" = "Kontextuella alternativ"
"Contrast" = "Kontrast"
"Contributors" = "Bidragsgivare"
@@ -624,6 +623,7 @@ name = "Svenska"
"If" = "Om"
"If {condition}" = "Om {condition}"
"Ignore auto layout (absolute position)" = "Ignorera automatisk layout (absolut position)"
"Ignore overlapping layers" = "Ignorera överlappande lager"
"Image" = "Bild"
"Images" = "Bilder"
"Import" = "Importera"
+1 -1
View File
@@ -299,7 +299,6 @@ name = "Türkçe"
"Constraints" = "Kısıtlamalar"
"Content" = "İçerik"
"Contents hidden" = "İçerik gizli"
"Contents only" = "Yalnızca içerik"
"Contextual alternates" = "Bağlamsal alternatifler"
"Contrast" = "Kontrast"
"Contributors" = "Katkıda bulunanlar"
@@ -617,6 +616,7 @@ name = "Türkçe"
"If" = "Eğer"
"If {condition}" = "Eğer {condition}"
"Ignore auto layout (absolute position)" = "Otomatik yerleşimi yok say (mutlak konum)"
"Ignore overlapping layers" = "Çakışan katmanları yok say"
"Image" = "Görüntü"
"Images" = "Görüntüler"
"Import" = "İçe aktar"
+1 -1
View File
@@ -292,7 +292,6 @@ status = "draft — needs native review"
"Constraints" = "约束"
"Content" = "内容"
"Contents hidden" = "内容已隐藏"
"Contents only" = "仅内容"
"Contextual alternates" = "上下文替代字"
"Contrast" = "对比度"
"Contributors" = "贡献者"
@@ -597,6 +596,7 @@ status = "draft — needs native review"
"If" = "如果"
"If {condition}" = "如果 {condition}"
"Ignore auto layout (absolute position)" = "忽略自动布局(绝对定位)"
"Ignore overlapping layers" = "忽略重叠图层"
"Image" = "图片"
"Images" = "图片"
"Import" = "导入"
+15 -9
View File
@@ -40,8 +40,9 @@ pub fn section(app: &mut FigApp, ui: &mut Ui, doc: &Document, sel: &[NodeId]) {
if mixed {
widgets::note(ui, tr("Click + to replace mixed content"), t.text_secondary);
}
let text = sel.iter().all(|i| matches!(doc.node(*i).map(|n| &n.kind), Some(NodeKind::Text(_))));
for (i, e) in list.iter().enumerate() {
setting_row(app, ui, &ids, i, e);
setting_row(app, ui, &ids, i, e, text);
}
let jobs = export_jobs(doc, sel);
if jobs.is_empty() {
@@ -61,8 +62,9 @@ pub fn section(app: &mut FigApp, ui: &mut Ui, doc: &Document, sel: &[NodeId]) {
}
/// One export setting: size (typed or picked; images only, SVG and PDF are vector), suffix,
/// format, advanced options and remove; a PDF's print settings under it.
fn setting_row(app: &mut FigApp, ui: &mut Ui, ids: &[NodeId], i: usize, e: &ExportSetting) {
/// format, advanced options and remove; a PDF's print settings under it. `text`: every layer in
/// `ids` is a text layer.
fn setting_row(app: &mut FigApp, ui: &mut Ui, ids: &[NodeId], i: usize, e: &ExportSetting, text: bool) {
row(ui, 32.0, |ui| {
// Tighter spacing so the advanced options and remove buttons fit beside the fields.
ui.spacing_mut().item_spacing.x = 4.0;
@@ -98,7 +100,7 @@ fn setting_row(app: &mut FigApp, ui: &mut Ui, ids: &[NodeId], i: usize, e: &Expo
.width(216.0)
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
.show(|ui| {
if let Some(mut params) = advanced_options(ui, e) {
if let Some(mut params) = advanced_options(ui, e, text) {
params["ids"] = json!(ids);
params["index"] = json!(i);
app.run("export.update", params);
@@ -113,17 +115,21 @@ fn setting_row(app: &mut FigApp, ui: &mut Ui, ids: &[NodeId], i: usize, e: &Expo
}
}
/// A setting's advanced options: contents only and include bounding box, and for SVG outline
/// text, the id attribute and simplified strokes. Returns the changed option as command params.
fn advanced_options(ui: &mut Ui, e: &ExportSetting) -> Option<Value> {
/// A setting's advanced options: ignore overlapping layers (`contentsOnly`), include bounding box
/// for text layers (and for any setting that has it on, so it can be turned off), and for SVG
/// outline text, the id attribute and simplified strokes. Returns the changed option as command
/// params.
fn advanced_options(ui: &mut Ui, e: &ExportSetting, text: bool) -> Option<Value> {
let mut out = None;
let mut option = |ui: &mut Ui, key: &str, on: bool, label: &str| {
if widgets::checkbox(ui, on, label) {
out = Some(json!({ key: !on }));
}
};
option(ui, "contentsOnly", e.contents_only, tr("Contents only"));
option(ui, "includeBoundingBox", e.include_bounding_box, tr("Include bounding box"));
option(ui, "contentsOnly", e.contents_only, tr("Ignore overlapping layers"));
if text || e.include_bounding_box {
option(ui, "includeBoundingBox", e.include_bounding_box, tr("Include bounding box"));
}
if e.format == ExportFormat::Svg {
option(ui, "svgOutlineText", e.svg_outline_text, tr("Outline text"));
option(ui, "svgIdAttribute", e.svg_id_attribute, tr("Include id attribute"));
+31 -1
View File
@@ -1,7 +1,7 @@
//! The Export section's Preview row: a slice paints nothing itself, so its preview must show the
//! page content under it — the same thing exporting the slice writes — and not a blank
//! transparency checkerboard next to a correct export. And its setting rows: a size only for
//! images.
//! images, and advanced options named as the reference app names them.
use figcraft_doc::{Document, NodeId};
use figcraft_engine::Session;
@@ -93,3 +93,33 @@ fn export_rows_offer_a_size_for_images_only() {
assert!(size_menu(&u), "{format} has sizes again");
}
}
/// The advanced options: Ignore overlapping layers (the `contentsOnly` setting), and Include
/// bounding box for text layers only. A setting that already has the bounding box on keeps it, and
/// the option stays so it can be turned off.
#[test]
fn advanced_options_offer_the_bounding_box_for_text_layers() {
let mut s = Session::new();
let r = crate::present_tests::id(&s.execute("shape.rectangle", &json!({"x": 0, "y": 0, "width": 100, "height": 80})).unwrap());
let t = crate::present_tests::id(&s.execute("text.create", &json!({"text": "Hi", "x": 200, "y": 0})).unwrap());
s.execute("export.add", &json!({"ids": [r]})).unwrap();
s.execute("export.add", &json!({"ids": [t]})).unwrap();
let mut u = crate::layers_drag_tests::Ui::new(s);
let options = |u: &mut crate::layers_drag_tests::Ui, id: NodeId| {
u.app.run("select.set", json!({"ids": [id]}));
u.frame(vec![]);
egui::Popup::open_id(&u.ctx, egui::Id::new(("export_more", 0)));
u.frame(vec![]);
crate::import_report_tests::shown_texts(u.frame_output(vec![]).shapes)
};
let shown = options(&mut u, r);
assert!(shown.iter().any(|s| s == "Ignore overlapping layers"), "the reference app's name: {shown:?}");
assert!(!shown.iter().any(|s| s == "Contents only"));
assert!(!shown.iter().any(|s| s == "Include bounding box"), "a rectangle has no bounding box option");
let shown = options(&mut u, t);
assert!(shown.iter().any(|s| s == "Include bounding box"), "a text layer has it: {shown:?}");
u.app.run("export.update", json!({"ids": [r], "index": 0, "includeBoundingBox": true}));
let shown = options(&mut u, r);
assert!(shown.iter().any(|s| s == "Include bounding box"), "a rectangle that has it on shows it: {shown:?}");
assert!(u.app.session.doc().unwrap().node(r).unwrap().exports[0].include_bounding_box, "the setting is kept");
}
+1 -1
View File
@@ -423,7 +423,7 @@ Hours in this narrative are the builders' estimates; the tables above supersede
presenter) and variables (the local variables JSON passed along, next to the file or embedded:
collections, modes, aliases, scopes, layer bindings and explicit modes).
Export panel: a row per export setting (typed or preset sizes like `2x` / `512w` / `512h`, PNG,
JPG, WebP, SVG and PDF, suffix, advanced options: contents only, include bounding box, and for
JPG, WebP, SVG and PDF, suffix, advanced options: ignore overlapping layers, include bounding box for text layers, and for
SVG outline text, id attributes and simplified strokes), a preview, and "Export N layers" (`file.exportLayers`) in the
panel and the Export dialog. Paste from other apps: images, SVG and text (the newest clipboard
content wins over our own copy; pasted SVG lands centred in the view), and layers copied from