From a325232a09e42e68ca97930bc0a0b56b134b02e5 Mon Sep 17 00:00:00 2001 From: Amruth Pillai Date: Tue, 29 Sep 2026 15:25:44 +0200 Subject: [PATCH] refactor(pdf): render every resume with semantic css and drop the legacy styler Now that the API hands out every resume with its legacy style rules converted, the renderer runs one styling system: the stylesheet mode, the per-slot legacy rule hooks in the template primitives and the section style provider are gone, and the Custom Styles editor loses its legacy draft banner and Activate step. The converter stays (the API uses it), with its fixtures now checked by rendering the converted stylesheets. --- apps/web/locales/af-ZA.po | 12 -- apps/web/locales/am-ET.po | 12 -- apps/web/locales/ar-SA.po | 12 -- apps/web/locales/az-AZ.po | 12 -- apps/web/locales/bg-BG.po | 12 -- apps/web/locales/bn-BD.po | 12 -- apps/web/locales/ca-ES.po | 12 -- apps/web/locales/cs-CZ.po | 12 -- apps/web/locales/da-DK.po | 12 -- apps/web/locales/de-DE.po | 12 -- apps/web/locales/el-GR.po | 12 -- apps/web/locales/en-GB.po | 12 -- apps/web/locales/en-US.po | 12 -- apps/web/locales/es-ES.po | 12 -- apps/web/locales/fa-IR.po | 12 -- apps/web/locales/fi-FI.po | 12 -- apps/web/locales/fr-FR.po | 12 -- apps/web/locales/he-IL.po | 12 -- apps/web/locales/hi-IN.po | 12 -- apps/web/locales/hu-HU.po | 12 -- apps/web/locales/id-ID.po | 12 -- apps/web/locales/it-IT.po | 12 -- apps/web/locales/ja-JP.po | 12 -- apps/web/locales/km-KH.po | 12 -- apps/web/locales/kn-IN.po | 12 -- apps/web/locales/ko-KR.po | 12 -- apps/web/locales/lt-LT.po | 12 -- apps/web/locales/lv-LV.po | 12 -- apps/web/locales/ml-IN.po | 12 -- apps/web/locales/mr-IN.po | 12 -- apps/web/locales/ms-MY.po | 12 -- apps/web/locales/ne-NP.po | 12 -- apps/web/locales/nl-NL.po | 12 -- apps/web/locales/no-NO.po | 12 -- apps/web/locales/or-IN.po | 12 -- apps/web/locales/pl-PL.po | 12 -- apps/web/locales/pt-BR.po | 12 -- apps/web/locales/pt-PT.po | 12 -- apps/web/locales/ro-RO.po | 12 -- apps/web/locales/ru-RU.po | 12 -- apps/web/locales/sk-SK.po | 12 -- apps/web/locales/sl-SI.po | 12 -- apps/web/locales/sq-AL.po | 12 -- apps/web/locales/sr-SP.po | 12 -- apps/web/locales/sv-SE.po | 12 -- apps/web/locales/ta-IN.po | 12 -- apps/web/locales/te-IN.po | 12 -- apps/web/locales/th-TH.po | 12 -- apps/web/locales/tr-TR.po | 12 -- apps/web/locales/uk-UA.po | 12 -- apps/web/locales/uz-UZ.po | 12 -- apps/web/locales/vi-VN.po | 12 -- apps/web/locales/zh-CN.po | 12 -- apps/web/locales/zh-TW.po | 12 -- apps/web/locales/zu-ZA.po | 12 -- .../resume/stylesheet/editor.test.tsx | 41 +---- .../src/features/resume/stylesheet/editor.tsx | 19 +-- .../resume/stylesheet/legacy-banner.tsx | 29 ---- .../-sidebar/right/sections/design.tsx | 5 - packages/pdf/src/document.tsx | 9 +- .../all-templates-presentation.test.ts | 2 - .../semantic/combined-field-bindings.test.tsx | 49 ++---- packages/pdf/src/semantic/context.tsx | 20 +-- packages/pdf/src/semantic/index.ts | 1 - .../pdf/src/semantic/issue-fixtures.test.tsx | 24 +-- .../src/semantic/item-header-binding.test.tsx | 1 - .../pdf/src/semantic/item-header-row.test.tsx | 2 +- ...st.tsx => legacy-adoption-render.test.tsx} | 108 +++++-------- .../pdf/src/semantic/link-fidelity.test.tsx | 4 +- packages/pdf/src/semantic/no-wrapper.test.tsx | 18 +-- .../semantic/pagination-cancellation.test.tsx | 2 +- packages/pdf/src/semantic/public.test.ts | 6 +- packages/pdf/src/semantic/resolve.ts | 11 +- .../rich-text-table.integration.test.tsx | 142 +++++++++--------- .../pdf/src/semantic/runtime-paths.test.tsx | 8 +- .../src/semantic/sibling-ordering.test.tsx | 2 +- .../src/templates/ditgar/DitgarPage.test.tsx | 38 +++-- .../templates/gengar/gengar-skills.test.tsx | 27 ++-- packages/pdf/src/templates/shared/context.tsx | 25 --- .../src/templates/shared/date-layout.test.tsx | 2 +- .../src/templates/shared/level-display.tsx | 8 +- .../src/templates/shared/level-gap.test.tsx | 9 +- .../templates/shared/list-pagination.test.tsx | 2 +- .../templates/shared/ordered-marker.test.tsx | 2 +- .../templates/shared/page-margins.test.tsx | 17 +-- .../templates/shared/picture-border.test.tsx | 52 +++---- .../pdf/src/templates/shared/primitives.tsx | 34 +---- .../pdf/src/templates/shared/rich-text.tsx | 24 +-- .../shared/section-header-alignment.test.tsx | 15 +- .../pdf/src/templates/shared/sections.test.ts | 10 +- .../pdf/src/templates/shared/sections.tsx | 20 +-- .../skill-keyword-presentation.test.tsx | 2 +- .../shared/skill-level-alignment.test.tsx | 34 ++--- .../src/templates/shared/style-rules.test.ts | 3 +- .../pdf/src/templates/shared/style-rules.ts | 6 +- .../schema/src/resume/style-rules.test.ts | 45 ------ packages/schema/src/resume/style-rules.ts | 12 -- tests/e2e/fixtures/db.ts | 17 +-- 98 files changed, 257 insertions(+), 1310 deletions(-) delete mode 100644 apps/web/src/features/resume/stylesheet/legacy-banner.tsx rename packages/pdf/src/semantic/{legacy-render-parity.test.tsx => legacy-adoption-render.test.tsx} (62%) delete mode 100644 packages/schema/src/resume/style-rules.test.ts diff --git a/apps/web/locales/af-ZA.po b/apps/web/locales/af-ZA.po index 97f3eb900..aea07e5f6 100644 --- a/apps/web/locales/af-ZA.po +++ b/apps/web/locales/af-ZA.po @@ -738,10 +738,6 @@ msgstr "Rekening" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktiveer Semantiese CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Omgeskakelde stylbladkonsep" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Jou ou style bly aktief totdat jy hierdie Semantic CSS-konsep aktiveer." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Jou lyne is baie styf gepak." diff --git a/apps/web/locales/am-ET.po b/apps/web/locales/am-ET.po index b6021e283..d9504f41c 100644 --- a/apps/web/locales/am-ET.po +++ b/apps/web/locales/am-ET.po @@ -738,10 +738,6 @@ msgstr "መለያ" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "የሴማንቲክ CSS ን ያግብሩ" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "የተቀየረ የቅጥ ሉህ ረቂቅ" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "የቀድሞ ቅጦችዎ ይህን የ Semantic CSS ረቂቅ እስኪያነቁ ድረስ በሥራ ላይ ይቆያሉ።" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "መስመሮችዎ በጣም በጥብቅ የታሸጉ ናቸው።" diff --git a/apps/web/locales/ar-SA.po b/apps/web/locales/ar-SA.po index d632ebe21..ef4e69246 100644 --- a/apps/web/locales/ar-SA.po +++ b/apps/web/locales/ar-SA.po @@ -738,10 +738,6 @@ msgstr "الحساب" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "تفعيل CSS الدلالي" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "مسودة ورقة الأنماط المحولة" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "تبقى أنماطك القديمة فعّالة حتى تفعّل مسودة Semantic CSS هذه." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "خطوطك معبأة بإحكام شديد." diff --git a/apps/web/locales/az-AZ.po b/apps/web/locales/az-AZ.po index 7c2d8410c..0ec0698c4 100644 --- a/apps/web/locales/az-AZ.po +++ b/apps/web/locales/az-AZ.po @@ -738,10 +738,6 @@ msgstr "Hesab" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Semantik CSS-i aktivləşdirin" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Çevirilmiş stil cədvəli qaralaması" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Köhnə üslublarınız siz bu Semantic CSS qaralamasını aktivləşdirənə qədər qüvvədə qalır." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Sətirləriniz çox sıx yığılıb." diff --git a/apps/web/locales/bg-BG.po b/apps/web/locales/bg-BG.po index 6ce23809e..935e51891 100644 --- a/apps/web/locales/bg-BG.po +++ b/apps/web/locales/bg-BG.po @@ -738,10 +738,6 @@ msgstr "Акаунт" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Активиране на семантичен CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Конвертирана чернова на стилов лист" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Старите ви стилове остават активни, докато не активирате тази чернова със Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Вашите линии са опаковани много плътно." diff --git a/apps/web/locales/bn-BD.po b/apps/web/locales/bn-BD.po index 16d160717..90b755575 100644 --- a/apps/web/locales/bn-BD.po +++ b/apps/web/locales/bn-BD.po @@ -738,10 +738,6 @@ msgstr "অ্যাকাউন্ট" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "সিমান্টিক CSS সক্রিয় করুন" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "রূপান্তরিত স্টাইলশীট খসড়া" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "আপনি এই Semantic CSS খসড়া সক্রিয় না করা পর্যন্ত আপনার পুরোনো স্টাইলগুলোই চালু থাকবে।" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "আপনার লাইন খুব শক্তভাবে প্যাক করা হয়." diff --git a/apps/web/locales/ca-ES.po b/apps/web/locales/ca-ES.po index b984b5564..4bb304a4d 100644 --- a/apps/web/locales/ca-ES.po +++ b/apps/web/locales/ca-ES.po @@ -738,10 +738,6 @@ msgstr "Compte" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Activa el CSS semàntic" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Esborrany de full d'estil convertit" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Els teus estils antics continuen actius fins que activis aquest esborrany de CSS semàntic." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Les teves línies estan molt atapeïdes." diff --git a/apps/web/locales/cs-CZ.po b/apps/web/locales/cs-CZ.po index 8d27b36a4..64968b9fc 100644 --- a/apps/web/locales/cs-CZ.po +++ b/apps/web/locales/cs-CZ.po @@ -738,10 +738,6 @@ msgstr "Účet" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktivace sémantického CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Konverze konceptu stylů" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Vaše původní styly zůstávají aktivní, dokud neaktivujete tento koncept Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Vaše linky jsou nabité velmi pevně." diff --git a/apps/web/locales/da-DK.po b/apps/web/locales/da-DK.po index 486b79639..c8f64ef8b 100644 --- a/apps/web/locales/da-DK.po +++ b/apps/web/locales/da-DK.po @@ -738,10 +738,6 @@ msgstr "Konto" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktivér semantisk CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Konverteret stylesheet-kladde" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Dine hidtidige typografier forbliver aktive, indtil du aktiverer dette Semantic CSS-udkast." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Dine linjer er pakket meget tæt." diff --git a/apps/web/locales/de-DE.po b/apps/web/locales/de-DE.po index bca684b35..19f6c1280 100644 --- a/apps/web/locales/de-DE.po +++ b/apps/web/locales/de-DE.po @@ -738,10 +738,6 @@ msgstr "Konto" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Semantisches CSS aktivieren" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Konvertierter Stylesheet-Entwurf" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Ihre bisherigen Stile bleiben aktiv, bis Sie diesen Semantic-CSS-Entwurf aktivieren." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Deine Zeilen sind sehr dicht gepackt." diff --git a/apps/web/locales/el-GR.po b/apps/web/locales/el-GR.po index 042fb1911..cd2c7d2e7 100644 --- a/apps/web/locales/el-GR.po +++ b/apps/web/locales/el-GR.po @@ -738,10 +738,6 @@ msgstr "Λογαριασμός" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Ενεργοποίηση Σημασιολογικού CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Μετατρεπόμενο προσχέδιο φύλλου στυλ" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Τα παλαιά σας στυλ παραμένουν ενεργά μέχρι να ενεργοποιήσετε αυτό το πρόχειρο Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Οι γραμμές σας είναι γεμάτες πολύ σφιχτά." diff --git a/apps/web/locales/en-GB.po b/apps/web/locales/en-GB.po index f5682f2aa..b6e7a4890 100644 --- a/apps/web/locales/en-GB.po +++ b/apps/web/locales/en-GB.po @@ -738,10 +738,6 @@ msgstr "Account" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Activate Semantic CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Converted stylesheet draft" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Your legacy styles stay active until you activate this Semantic CSS draft." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Your lines are packed very tightly." diff --git a/apps/web/locales/en-US.po b/apps/web/locales/en-US.po index 184c91924..818d5e249 100644 --- a/apps/web/locales/en-US.po +++ b/apps/web/locales/en-US.po @@ -733,10 +733,6 @@ msgstr "Account" msgid "Actions" msgstr "Actions" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Activate Semantic CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "Activity" @@ -1990,10 +1986,6 @@ msgstr "Conversation" msgid "Conversations" msgstr "Conversations" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Converted stylesheet draft" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9044,10 +9036,6 @@ msgstr "Your headline changed on the resume. The letter updated too." msgid "Your keys, stored encrypted" msgstr "Your keys, stored encrypted" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Your legacy styles stay active until you activate this Semantic CSS draft." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Your lines are packed very tightly." diff --git a/apps/web/locales/es-ES.po b/apps/web/locales/es-ES.po index 1a4e95c6d..4ab863f47 100644 --- a/apps/web/locales/es-ES.po +++ b/apps/web/locales/es-ES.po @@ -738,10 +738,6 @@ msgstr "Cuenta" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Activar CSS semántico" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Borrador de hoja de estilo convertido" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Tus estilos antiguos siguen activos hasta que actives este borrador de CSS semántico." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Tus líneas están muy apretadas." diff --git a/apps/web/locales/fa-IR.po b/apps/web/locales/fa-IR.po index c8ac8cdcb..261ef22b0 100644 --- a/apps/web/locales/fa-IR.po +++ b/apps/web/locales/fa-IR.po @@ -738,10 +738,6 @@ msgstr "حساب کاربری" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "فعال کردن CSS معنایی" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "پیش‌نویس شیوه‌نامه تبدیل‌شده" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "سبک‌های قدیمی شما تا زمانی که این پیش‌نویس Semantic CSS را فعال کنید، فعال می‌مانند." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "خطوط شما بیش از حد فشرده‌اند." diff --git a/apps/web/locales/fi-FI.po b/apps/web/locales/fi-FI.po index 1c04b02a7..c5ad690b4 100644 --- a/apps/web/locales/fi-FI.po +++ b/apps/web/locales/fi-FI.po @@ -738,10 +738,6 @@ msgstr "Tili" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktivoi semanttinen CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Muunnettu tyylitiedoston luonnos" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Vanhat tyylisi pysyvät voimassa, kunnes otat tämän Semantic CSS -luonnoksen käyttöön." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Sinun rivisi on pakattu erittäin tiukasti." diff --git a/apps/web/locales/fr-FR.po b/apps/web/locales/fr-FR.po index 1d9f1fd87..7f2cc2f89 100644 --- a/apps/web/locales/fr-FR.po +++ b/apps/web/locales/fr-FR.po @@ -738,10 +738,6 @@ msgstr "Compte" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Activer le CSS sémantique" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Brouillon de feuille de style converti" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Vos anciens styles restent actifs tant que vous n'activez pas ce brouillon de CSS sémantique." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Vos lignes sont très serrées." diff --git a/apps/web/locales/he-IL.po b/apps/web/locales/he-IL.po index c3e51ab96..60a5776b5 100644 --- a/apps/web/locales/he-IL.po +++ b/apps/web/locales/he-IL.po @@ -738,10 +738,6 @@ msgstr "חשבון" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "הפעלת CSS סמנטי" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "טיוטת גיליון סגנונות שהומרה" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "הסגנונות הישנים שלך נשארים פעילים עד שתפעיל את טיוטת ה-Semantic CSS הזו." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "השורות שלך צפופות מאוד." diff --git a/apps/web/locales/hi-IN.po b/apps/web/locales/hi-IN.po index 46d69e198..b7708c391 100644 --- a/apps/web/locales/hi-IN.po +++ b/apps/web/locales/hi-IN.po @@ -738,10 +738,6 @@ msgstr "खाता" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "सिमेंटिक सीएसएस को सक्रिय करें" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "रूपांतरित स्टाइलशीट ड्राफ्ट" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "जब तक आप यह Semantic CSS ड्राफ़्ट सक्रिय नहीं करते, तब तक आपकी पुरानी स्टाइल ही लागू रहेंगी।" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "आपकी पंक्तियाँ बहुत कसकर भरी हुई हैं।" diff --git a/apps/web/locales/hu-HU.po b/apps/web/locales/hu-HU.po index 4851160c2..1cae123c4 100644 --- a/apps/web/locales/hu-HU.po +++ b/apps/web/locales/hu-HU.po @@ -738,10 +738,6 @@ msgstr "Fiók" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Szemantikus CSS aktiválása" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Stíluslap-tervezet konvertálása" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "A korábbi stílusai aktívak maradnak, amíg nem aktiválja ezt a Semantic CSS piszkozatot." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "A soraid nagyon szorosan vannak csomagolva." diff --git a/apps/web/locales/id-ID.po b/apps/web/locales/id-ID.po index 29170583d..f110dcd94 100644 --- a/apps/web/locales/id-ID.po +++ b/apps/web/locales/id-ID.po @@ -738,10 +738,6 @@ msgstr "Akun" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktifkan CSS Semantik" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Draf stylesheet yang telah dikonversi" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Gaya lama Anda tetap aktif sampai Anda mengaktifkan draf Semantic CSS ini." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Garis Anda dikemas sangat rapat." diff --git a/apps/web/locales/it-IT.po b/apps/web/locales/it-IT.po index 749b6c8cd..aa34cf32e 100644 --- a/apps/web/locales/it-IT.po +++ b/apps/web/locales/it-IT.po @@ -738,10 +738,6 @@ msgstr "Account" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Attiva il CSS semantico" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Bozza del foglio di stile convertito" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "I tuoi stili precedenti restano attivi finché non attivi questa bozza di CSS semantico." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Le tue battute sono molto fitte." diff --git a/apps/web/locales/ja-JP.po b/apps/web/locales/ja-JP.po index b3c91331b..65ae2b2b6 100644 --- a/apps/web/locales/ja-JP.po +++ b/apps/web/locales/ja-JP.po @@ -738,10 +738,6 @@ msgstr "アカウント" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "セマンティックCSSを有効にする" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "変換されたスタイルシートのドラフト" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "このセマンティック CSS の下書きを有効にするまで、これまでのスタイルがそのまま適用されます。" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "あなたのラインは非常に密集しています。" diff --git a/apps/web/locales/km-KH.po b/apps/web/locales/km-KH.po index 005e4304c..638ecc06c 100644 --- a/apps/web/locales/km-KH.po +++ b/apps/web/locales/km-KH.po @@ -738,10 +738,6 @@ msgstr "គណនី" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "ធ្វើឱ្យ CSS ន័យវិទ្យាសកម្ម" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "សេចក្តីព្រាងសន្លឹករចនាប័ទ្មដែលបានបម្លែង" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "រចនាប័ទ្មចាស់របស់អ្នកនៅតែដំណើរការ រហូតដល់អ្នកបើកដំណើរការសេចក្ដីព្រាង Semantic CSS នេះ។" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "បន្ទាត់របស់អ្នកត្រូវបានខ្ចប់យ៉ាងតឹងរ៉ឹង។" diff --git a/apps/web/locales/kn-IN.po b/apps/web/locales/kn-IN.po index c62c07433..9d3bdc40d 100644 --- a/apps/web/locales/kn-IN.po +++ b/apps/web/locales/kn-IN.po @@ -738,10 +738,6 @@ msgstr "ಖಾತೆ" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "ಲಾಕ್ಷಣಿಕ CSS ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "ಪರಿವರ್ತಿಸಲಾದ ಸ್ಟೈಲ್‌ಶೀಟ್ ಡ್ರಾಫ್ಟ್" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "ಈ Semantic CSS ಕರಡನ್ನು ನೀವು ಸಕ್ರಿಯಗೊಳಿಸುವವರೆಗೆ ನಿಮ್ಮ ಹಳೆಯ ಶೈಲಿಗಳು ಸಕ್ರಿಯವಾಗಿಯೇ ಇರುತ್ತವೆ." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "ನಿಮ್ಮ ಸಾಲುಗಳನ್ನು ತುಂಬಾ ಬಿಗಿಯಾಗಿ ಪ್ಯಾಕ್ ಮಾಡಲಾಗಿದೆ." diff --git a/apps/web/locales/ko-KR.po b/apps/web/locales/ko-KR.po index 539079fb1..0ab085838 100644 --- a/apps/web/locales/ko-KR.po +++ b/apps/web/locales/ko-KR.po @@ -738,10 +738,6 @@ msgstr "계정" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "시맨틱 CSS 활성화" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "변환된 스타일시트 초안" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "이 시맨틱 CSS 초안을 활성화하기 전까지는 기존 스타일이 그대로 적용됩니다." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "귀하의 라인은 매우 촘촘하게 포장되어 있습니다." diff --git a/apps/web/locales/lt-LT.po b/apps/web/locales/lt-LT.po index 8707952b5..6deaa6317 100644 --- a/apps/web/locales/lt-LT.po +++ b/apps/web/locales/lt-LT.po @@ -738,10 +738,6 @@ msgstr "Paskyra" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Semantinio CSS aktyvavimas" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Konvertuotas stilių lapo juodraštis" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Seni jūsų stiliai lieka aktyvūs, kol neaktyvuosite šio Semantic CSS juodraščio." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Jūsų eilutės supakuotos labai sandariai." diff --git a/apps/web/locales/lv-LV.po b/apps/web/locales/lv-LV.po index e67667420..fe811d8df 100644 --- a/apps/web/locales/lv-LV.po +++ b/apps/web/locales/lv-LV.po @@ -738,10 +738,6 @@ msgstr "Konts" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktivizēt semantisko CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Konvertēts stila lapas melnraksts" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Jūsu vecie stili paliek aktīvi, līdz aktivizēsiet šo Semantic CSS melnrakstu." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Jūsu rindas ir ļoti cieši iesaiņotas." diff --git a/apps/web/locales/ml-IN.po b/apps/web/locales/ml-IN.po index 37135d4de..fd5cfc87f 100644 --- a/apps/web/locales/ml-IN.po +++ b/apps/web/locales/ml-IN.po @@ -738,10 +738,6 @@ msgstr "അക്കൗണ്ട്" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "സെമാന്റിക് CSS സജീവമാക്കുക" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "പരിവർത്തനം ചെയ്ത സ്റ്റൈൽഷീറ്റ് ഡ്രാഫ്റ്റ്" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "ഈ Semantic CSS ഡ്രാഫ്റ്റ് നിങ്ങൾ സജീവമാക്കുന്നതുവരെ പഴയ സ്റ്റൈലുകൾ സജീവമായി തുടരും." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "നിങ്ങളുടെ വരികൾ വളരെ കർശനമായി പായ്ക്ക് ചെയ്തിട്ടുണ്ട്." diff --git a/apps/web/locales/mr-IN.po b/apps/web/locales/mr-IN.po index 186e2d18f..3118ec0e1 100644 --- a/apps/web/locales/mr-IN.po +++ b/apps/web/locales/mr-IN.po @@ -738,10 +738,6 @@ msgstr "खाते" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "सिमँटिक CSS सक्रिय करा" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "रूपांतरित स्टाईलशीटचा मसुदा" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "तुम्ही हा Semantic CSS मसुदा सक्रिय करेपर्यंत तुमच्या जुन्या स्टाइल्स लागू राहतील." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "तुमच्या ओळी खूप घट्ट बांधल्या आहेत." diff --git a/apps/web/locales/ms-MY.po b/apps/web/locales/ms-MY.po index f9d4b0631..b2812b448 100644 --- a/apps/web/locales/ms-MY.po +++ b/apps/web/locales/ms-MY.po @@ -738,10 +738,6 @@ msgstr "Akaun" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktifkan CSS Semantik" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Draf helaian gaya yang ditukar" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Gaya lama anda kekal aktif sehingga anda mengaktifkan draf Semantic CSS ini." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Talian anda padat dengan sangat ketat." diff --git a/apps/web/locales/ne-NP.po b/apps/web/locales/ne-NP.po index 6401a6306..70ea77070 100644 --- a/apps/web/locales/ne-NP.po +++ b/apps/web/locales/ne-NP.po @@ -738,10 +738,6 @@ msgstr "खाता" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "सिमेन्टिक CSS सक्रिय गर्नुहोस्" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "रूपान्तरित स्टाइलसिट ड्राफ्ट" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "तपाईंले यो Semantic CSS मस्यौदा सक्रिय नगरेसम्म तपाईंका पुराना शैलीहरू नै लागू रहनेछन्।" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "तपाईंको लाइनहरू धेरै कडा प्याक गरिएका छन्।" diff --git a/apps/web/locales/nl-NL.po b/apps/web/locales/nl-NL.po index c9e577803..bd380260a 100644 --- a/apps/web/locales/nl-NL.po +++ b/apps/web/locales/nl-NL.po @@ -738,10 +738,6 @@ msgstr "Rekening" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Activeer semantische CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Omgezette stylesheet-concept" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Je bestaande stijlen blijven actief totdat je dit Semantic CSS-concept activeert." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Je paginamarges zijn erg smal." diff --git a/apps/web/locales/no-NO.po b/apps/web/locales/no-NO.po index 34daa5e16..030dbe62c 100644 --- a/apps/web/locales/no-NO.po +++ b/apps/web/locales/no-NO.po @@ -738,10 +738,6 @@ msgstr "Konto" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktiver semantisk CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Konvertert stilarkutkast" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "De gamle stilene dine forblir aktive til du aktiverer dette Semantic CSS-utkastet." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Linjeavstanden din er svært tett." diff --git a/apps/web/locales/or-IN.po b/apps/web/locales/or-IN.po index 0856f2cc8..7d0e78c83 100644 --- a/apps/web/locales/or-IN.po +++ b/apps/web/locales/or-IN.po @@ -738,10 +738,6 @@ msgstr "ଆକାଉଣ୍ଟ" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "ସିମାଣ୍ଟିକ୍ CSS ସକ୍ରିୟ କରନ୍ତୁ" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "ରୂପାନ୍ତରିତ ଷ୍ଟାଇଲସିଟ୍ ଡ୍ରାଫ୍ଟ" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "ଆପଣ ଏହି Semantic CSS ଡ୍ରାଫ୍ଟକୁ ସକ୍ରିୟ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଆପଣଙ୍କ ପୁରୁଣା ଶୈଳୀଗୁଡିକ ସକ୍ରିୟ ରହିଥାଏ।" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "ଆପଣଙ୍କ ଲାଇନ୍‌ଗୁଡ଼ିକ ଅତ୍ୟଧିକ ଘନ।" diff --git a/apps/web/locales/pl-PL.po b/apps/web/locales/pl-PL.po index eb820a22e..3ce9a7760 100644 --- a/apps/web/locales/pl-PL.po +++ b/apps/web/locales/pl-PL.po @@ -738,10 +738,6 @@ msgstr "Konto" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktywuj semantyczny CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Przekonwertowany projekt arkusza stylów" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Twoje dotychczasowe style pozostają aktywne, dopóki nie aktywujesz tej wersji roboczej Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Wiersze są bardzo ciasno ułożone." diff --git a/apps/web/locales/pt-BR.po b/apps/web/locales/pt-BR.po index 0c2ca4d65..705d13bd1 100644 --- a/apps/web/locales/pt-BR.po +++ b/apps/web/locales/pt-BR.po @@ -738,10 +738,6 @@ msgstr "Conta" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Ativar CSS Semântico" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Rascunho da folha de estilo convertida" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Seus estilos antigos continuam ativos até você ativar este rascunho de CSS semântico." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Suas linhas estão muito compactadas." diff --git a/apps/web/locales/pt-PT.po b/apps/web/locales/pt-PT.po index 550bedf79..1a44f8d30 100644 --- a/apps/web/locales/pt-PT.po +++ b/apps/web/locales/pt-PT.po @@ -738,10 +738,6 @@ msgstr "Conta" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Ativar CSS Semântico" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Rascunho da folha de estilo convertida" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Os seus estilos antigos continuam ativos até ativar este rascunho de CSS semântico." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Suas falas estão muito compactadas." diff --git a/apps/web/locales/ro-RO.po b/apps/web/locales/ro-RO.po index f9da210d1..3b8c8e2ba 100644 --- a/apps/web/locales/ro-RO.po +++ b/apps/web/locales/ro-RO.po @@ -738,10 +738,6 @@ msgstr "Cont" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Activează CSS-ul semantic" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Schiță de foaie de stil convertită" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Stilurile vechi rămân active până când activați această ciornă Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Liniile tale sunt foarte strâns." diff --git a/apps/web/locales/ru-RU.po b/apps/web/locales/ru-RU.po index 0bd8570c0..5415084af 100644 --- a/apps/web/locales/ru-RU.po +++ b/apps/web/locales/ru-RU.po @@ -738,10 +738,6 @@ msgstr "Аккаунт" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Активировать семантический CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Преобразованный черновик таблицы стилей" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Ваши прежние стили остаются активными, пока вы не активируете этот черновик Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Ваши строки упакованы очень плотно." diff --git a/apps/web/locales/sk-SK.po b/apps/web/locales/sk-SK.po index ef05f9a30..4a6d5b0db 100644 --- a/apps/web/locales/sk-SK.po +++ b/apps/web/locales/sk-SK.po @@ -738,10 +738,6 @@ msgstr "Účet" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktivovať sémantický CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Konvertovaný koncept štýlového hárka" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Vaše pôvodné štýly zostávajú aktívne, kým neaktivujete tento koncept Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Vaše linky sú nahustené." diff --git a/apps/web/locales/sl-SI.po b/apps/web/locales/sl-SI.po index 172d662ae..7791d2546 100644 --- a/apps/web/locales/sl-SI.po +++ b/apps/web/locales/sl-SI.po @@ -738,10 +738,6 @@ msgstr "Račun" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktiviraj semantični CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Pretvorjen osnutek slogovne predloge" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Vaši stari slogi ostanejo aktivni, dokler ne aktivirate tega osnutka Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Vaše vrstice so zelo natrpane." diff --git a/apps/web/locales/sq-AL.po b/apps/web/locales/sq-AL.po index 5da34fe4c..0417ac4b0 100644 --- a/apps/web/locales/sq-AL.po +++ b/apps/web/locales/sq-AL.po @@ -738,10 +738,6 @@ msgstr "Llogaria" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktivizo CSS-në Semantike" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Drafti i konvertuar i fletës së stilit" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Stilet tuaja të vjetra mbeten aktive derisa ta aktivizoni këtë draft Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Linjat tuaja janë të mbushura shumë fort." diff --git a/apps/web/locales/sr-SP.po b/apps/web/locales/sr-SP.po index 9526be269..7ea193f7c 100644 --- a/apps/web/locales/sr-SP.po +++ b/apps/web/locales/sr-SP.po @@ -738,10 +738,6 @@ msgstr "Налог" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Активирајте семантички CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Конвертована нацртна верзија стилског листа" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Ваши стари стилови остају активни док не активирате овај Semantic CSS нацрт." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Ваше линије су веома збијене." diff --git a/apps/web/locales/sv-SE.po b/apps/web/locales/sv-SE.po index 60166a9cc..fa8f39b9b 100644 --- a/apps/web/locales/sv-SE.po +++ b/apps/web/locales/sv-SE.po @@ -738,10 +738,6 @@ msgstr "Konto" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Aktivera semantisk CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Konverterat utkast till stilark" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Dina tidigare stilar förblir aktiva tills du aktiverar det här Semantic CSS-utkastet." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Dina linjer är mycket tätt packade." diff --git a/apps/web/locales/ta-IN.po b/apps/web/locales/ta-IN.po index ec6d01630..26748cfe1 100644 --- a/apps/web/locales/ta-IN.po +++ b/apps/web/locales/ta-IN.po @@ -738,10 +738,6 @@ msgstr "கணக்கு" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "செமாண்டிக் CSS-ஐ செயல்படுத்துக" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "மாற்றப்பட்ட ஸ்டைல்ஷீட் வரைவு" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "இந்த Semantic CSS வரைவை நீங்கள் செயல்படுத்தும் வரை உங்கள் பழைய பாணிகள் செயலில் இருக்கும்." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "உங்கள் வரிகள் மிகவும் இறுக்கமாக நிரம்பியுள்ளன." diff --git a/apps/web/locales/te-IN.po b/apps/web/locales/te-IN.po index b214697b9..2babb54fa 100644 --- a/apps/web/locales/te-IN.po +++ b/apps/web/locales/te-IN.po @@ -738,10 +738,6 @@ msgstr "ఖాతా" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "సెమాంటిక్ CSSని యాక్టివేట్ చేయండి" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "మార్చబడిన స్టైల్‌షీట్ డ్రాఫ్ట్" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "ఈ Semantic CSS ముసాయిదాను మీరు సక్రియం చేసే వరకు మీ పాత శైలులు అమల్లోనే ఉంటాయి." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "మీ లైన్లు చాలా గట్టిగా ప్యాక్ చేయబడ్డాయి." diff --git a/apps/web/locales/th-TH.po b/apps/web/locales/th-TH.po index a741b84a7..c9a0b2df1 100644 --- a/apps/web/locales/th-TH.po +++ b/apps/web/locales/th-TH.po @@ -738,10 +738,6 @@ msgstr "บัญชี" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "เปิดใช้งาน Semantic CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "แปลงร่างสไตล์ชีตแล้ว" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "สไตล์เดิมของคุณจะยังใช้งานอยู่จนกว่าคุณจะเปิดใช้งานฉบับร่าง Semantic CSS นี้" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "เส้นของคุณแน่นมาก" diff --git a/apps/web/locales/tr-TR.po b/apps/web/locales/tr-TR.po index a7935600f..d7bb82d5a 100644 --- a/apps/web/locales/tr-TR.po +++ b/apps/web/locales/tr-TR.po @@ -738,10 +738,6 @@ msgstr "Hesap" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Semantik CSS'i Etkinleştir" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Dönüştürülmüş stil sayfası taslağı" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Bu Semantic CSS taslağını etkinleştirene kadar eski stilleriniz etkin kalır." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Hatlarınız çok sıkı paketlenmiş." diff --git a/apps/web/locales/uk-UA.po b/apps/web/locales/uk-UA.po index 250240ce0..be4e3cbb3 100644 --- a/apps/web/locales/uk-UA.po +++ b/apps/web/locales/uk-UA.po @@ -738,10 +738,6 @@ msgstr "Обліковий запис" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Активуйте семантичний CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Конвертований чернетка таблиці стилів" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Ваші попередні стилі залишаються активними, доки ви не активуєте цю чернетку Semantic CSS." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Ваші рядки зібрані дуже щільно." diff --git a/apps/web/locales/uz-UZ.po b/apps/web/locales/uz-UZ.po index d932b445d..89ba17a99 100644 --- a/apps/web/locales/uz-UZ.po +++ b/apps/web/locales/uz-UZ.po @@ -738,10 +738,6 @@ msgstr "Hisob" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Semantik CSS-ni faollashtirish" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "O'zgartirilgan uslublar jadvali qoralamasi" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Eski uslublaringiz siz ushbu Semantic CSS qoralamasini faollashtirmaguningizcha amalda qoladi." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Sizning chiziqlaringiz juda qattiq o'ralgan." diff --git a/apps/web/locales/vi-VN.po b/apps/web/locales/vi-VN.po index 80439fee0..888507bd7 100644 --- a/apps/web/locales/vi-VN.po +++ b/apps/web/locales/vi-VN.po @@ -738,10 +738,6 @@ msgstr "Tài khoản" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "Kích hoạt CSS ngữ nghĩa" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "Bản nháp bảng định kiểu đã chuyển đổi" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "Các kiểu cũ của bạn vẫn còn hiệu lực cho đến khi bạn kích hoạt bản nháp Semantic CSS này." - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "Đường dây của bạn được đóng gói rất chặt chẽ." diff --git a/apps/web/locales/zh-CN.po b/apps/web/locales/zh-CN.po index ebb9afc41..a35c37dc9 100644 --- a/apps/web/locales/zh-CN.po +++ b/apps/web/locales/zh-CN.po @@ -738,10 +738,6 @@ msgstr "账户" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "启用语义化 CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "已转换的样式表草稿" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "在你启用这份语义化 CSS 草稿之前,原有的样式会继续生效。" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "你的线路排得很紧。" diff --git a/apps/web/locales/zh-TW.po b/apps/web/locales/zh-TW.po index c48dbae7d..b388768b4 100644 --- a/apps/web/locales/zh-TW.po +++ b/apps/web/locales/zh-TW.po @@ -738,10 +738,6 @@ msgstr "帳戶" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "啟用語意化 CSS" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1995,10 +1991,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "已轉換的樣式表草稿" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9049,10 +9041,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "在您啟用這份語意化 CSS 草稿之前,原有的樣式會繼續生效。" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "你的線路排得很緊。" diff --git a/apps/web/locales/zu-ZA.po b/apps/web/locales/zu-ZA.po index a48f256ab..6cd8b5c4c 100644 --- a/apps/web/locales/zu-ZA.po +++ b/apps/web/locales/zu-ZA.po @@ -733,10 +733,6 @@ msgstr "" msgid "Actions" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Activate Semantic CSS" -msgstr "" - #: src/features/applications/components/detail/activity.tsx msgid "Activity" msgstr "" @@ -1990,10 +1986,6 @@ msgstr "" msgid "Conversations" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Converted stylesheet draft" -msgstr "" - #: src/features/resume/public/public-resume.tsx #: src/features/resume/share/link-tab.tsx #: src/features/settings/ai/api-keys.tsx @@ -9044,10 +9036,6 @@ msgstr "" msgid "Your keys, stored encrypted" msgstr "" -#: src/features/resume/stylesheet/legacy-banner.tsx -msgid "Your legacy styles stay active until you activate this Semantic CSS draft." -msgstr "" - #: src/features/ats-checker/messages.ts msgid "Your lines are packed very tightly." msgstr "" diff --git a/apps/web/src/features/resume/stylesheet/editor.test.tsx b/apps/web/src/features/resume/stylesheet/editor.test.tsx index 1a9875ddc..982b70994 100644 --- a/apps/web/src/features/resume/stylesheet/editor.test.tsx +++ b/apps/web/src/features/resume/stylesheet/editor.test.tsx @@ -58,16 +58,6 @@ vi.mock("./worker-client", () => ({ }), })); -const fatalError: SemanticCssDiagnostic = { - code: "VERSION_MISMATCH", - severity: "error", - message: "Version mismatch", - range: { - start: { line: 2, column: 3, offset: 17 }, - end: { line: 2, column: 9, offset: 23 }, - }, -}; - const guideName = /read the applying custom styles guide.*opens in new tab/i; const expectGuideLink = (root: HTMLElement) => { @@ -294,7 +284,6 @@ describe("StylesheetEditorShell", () => { , ); - expect(screen.queryByRole("button", { name: /activate semantic css/i })).not.toBeInTheDocument(); expect(screen.queryByRole("button", { name: /save|apply/i })).not.toBeInTheDocument(); }); @@ -321,7 +310,7 @@ describe("StylesheetEditorShell", () => { expect(builder.data.metadata.stylesheet.source.text).toBe("name { color: blue; }\n"); }); - it("switches a converted legacy draft through the ordinary resume update", async () => { + it("writes a first edit to a resume without a stylesheet as Semantic CSS", () => { render( @@ -329,35 +318,17 @@ describe("StylesheetEditorShell", () => { , ); + const view = EditorView.findFromDOM(screen.getByRole("textbox", { name: "Semantic CSS stylesheet" })); + if (!view) throw new Error("Missing editor view"); - const activate = await screen.findByRole("button", { name: "Activate Semantic CSS" }); - await waitFor(() => expect(activate).toBeEnabled()); - fireEvent.click(activate); + act(() => view.dispatch({ changes: { from: 0, insert: "name { color: blue; }\n" } })); expect(builder.data?.metadata.stylesheet).toEqual({ mode: "semantic", - source: { languageVersion: 1, text: "" }, + source: { languageVersion: 1, text: "name { color: blue; }\n" }, }); }); - it("does not block legacy activation on compiler errors", async () => { - compileWorker.diagnostics = [fatalError]; - - render( - - - - - , - ); - - const activate = await screen.findByRole("button", { name: "Activate Semantic CSS" }); - expect(activate).toBeEnabled(); - fireEvent.click(activate); - - expect(builder.data?.metadata.stylesheet?.mode).toBe("semantic"); - }); - it("makes editor mutation controls read-only while the resume is locked", () => { builder.isLocked = true; builder.canUndo = true; @@ -375,7 +346,6 @@ describe("StylesheetEditorShell", () => { "contenteditable", "false", ); - expect(screen.getByRole("button", { name: "Activate Semantic CSS" })).toBeDisabled(); expect(screen.getByRole("button", { name: "Undo stylesheet edit" })).toBeDisabled(); expect(screen.getByRole("button", { name: "Redo stylesheet edit" })).toBeDisabled(); expect(screen.getByRole("button", { name: "Format stylesheet" })).toBeDisabled(); @@ -397,7 +367,6 @@ describe("StylesheetEditorShell", () => { const sheet = await screen.findByRole("dialog"); expect(within(sheet).getByRole("heading", { name: "Semantic CSS stylesheet" })).toBeInTheDocument(); - expect(within(sheet).getByRole("button", { name: "Activate Semantic CSS" })).toBeInTheDocument(); expect(within(sheet).getByRole("toolbar", { name: "Stylesheet editor" })).toBeInTheDocument(); expectGuideLink(sheet); expect(document.querySelectorAll(".cm-editor")).toHaveLength(1); diff --git a/apps/web/src/features/resume/stylesheet/editor.tsx b/apps/web/src/features/resume/stylesheet/editor.tsx index 4f4a709d9..ce8dfbe4f 100644 --- a/apps/web/src/features/resume/stylesheet/editor.tsx +++ b/apps/web/src/features/resume/stylesheet/editor.tsx @@ -20,7 +20,6 @@ import { tags } from "@lezer/highlight"; import { t } from "@lingui/core/macro"; import { Trans } from "@lingui/react/macro"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { convertLegacyStyleRules } from "@reactive-resume/pdf/semantic-legacy"; import { buildSemanticTree, getTemplateSemanticManifest, @@ -43,7 +42,6 @@ import { } from "./editor-extensions"; import { formatEditorDocument } from "./formatter"; import { matchedNodeKeys } from "./highlight"; -import { LegacyStylesheetBanner } from "./legacy-banner"; import { listStyleTargets, styleTargetFor } from "./targets"; import { StylesheetToolbar } from "./toolbar"; import { createCompileWorkerClient } from "./worker-client"; @@ -430,10 +428,10 @@ function StylesheetEditorShell({ readOnly = false }: StylesheetEditorShellProps) return () => client.destroy(); }, []); const stylesheet = data?.metadata.stylesheet; - const mode = stylesheet?.mode ?? "legacy"; const source = useMemo( - () => stylesheet?.source ?? (data ? convertLegacyStyleRules(data).source : { languageVersion: 1, text: "" }), - [data, stylesheet], + // Resumes reach the builder with legacy rules already converted (the API does it), so there is one stylesheet. + () => stylesheet?.source ?? { languageVersion: 1, text: "" }, + [stylesheet], ); const metadata = useMemo(() => (data ? createEditorMetadata(data) : emptyMetadata), [data]); const disabled = readOnly || isLocked; @@ -503,14 +501,7 @@ function StylesheetEditorShell({ readOnly = false }: StylesheetEditorShellProps) const setSourceText = (next: string) => { if (disabled || next === text) return; updateResumeData((draft) => { - draft.metadata.stylesheet = { mode, source: { ...source, text: next } }; - }); - }; - - const activate = () => { - if (disabled || mode === "semantic") return; - updateResumeData((draft) => { - draft.metadata.stylesheet = { mode: "semantic", source }; + draft.metadata.stylesheet = { mode: "semantic", source: { ...source, text: next } }; }); }; @@ -536,8 +527,6 @@ function StylesheetEditorShell({ readOnly = false }: StylesheetEditorShellProps) ); const editorChrome = (
- {mode === "legacy" && } - - - - Converted stylesheet draft - - -

- Your legacy styles stay active until you activate this Semantic CSS draft. -

- -
- - ); -} diff --git a/apps/web/src/routes/builder/$resumeId/-sidebar/right/sections/design.tsx b/apps/web/src/routes/builder/$resumeId/-sidebar/right/sections/design.tsx index 1c7c7270e..9b4425bbc 100644 --- a/apps/web/src/routes/builder/$resumeId/-sidebar/right/sections/design.tsx +++ b/apps/web/src/routes/builder/$resumeId/-sidebar/right/sections/design.tsx @@ -6,7 +6,6 @@ import { useStore } from "@tanstack/react-form"; import { AnimatePresence, m } from "motion/react"; import { colorDesignSchema, levelDesignSchema } from "@reactive-resume/schema/resume/data"; import { resolveLevelDisplaySizes } from "@reactive-resume/schema/resume/level-display-sizes"; -import { resolveStyleRuleFontSize } from "@reactive-resume/schema/resume/style-rules"; import { FormControl, FormItem, FormLabel, FormMessage } from "@reactive-resume/ui/components/form"; import { Input } from "@reactive-resume/ui/components/input"; import { Separator } from "@reactive-resume/ui/components/separator"; @@ -235,12 +234,8 @@ function LevelSectionForm() { const previewType = useStore(form.store, (s) => s.values.type); const previewIcon = useStore(form.store, (s) => s.values.icon); - const iconFontSize = resolveStyleRuleFontSize(resume.data, { slot: "icon" }); - const levelFontSize = resolveStyleRuleFontSize(resume.data, { slot: "level" }); const { decorationSize, levelIconExplicitSize } = resolveLevelDisplaySizes({ bodyFontSize: resume.data.metadata.typography.body.fontSize, - iconFontSize, - levelFontSize, }); return ( diff --git a/packages/pdf/src/document.tsx b/packages/pdf/src/document.tsx index d1add08ca..ab823fc28 100644 --- a/packages/pdf/src/document.tsx +++ b/packages/pdf/src/document.tsx @@ -10,7 +10,7 @@ import { Document } from "#react-pdf-renderer"; import { RenderProvider } from "./context"; import { resolvePdfFonts, resumeContentContainsCJK, resumeContentScripts } from "./hooks/use-register-fonts"; import { SemanticRenderProvider } from "./semantic/context"; -import { resolveResumeRuntime, resolveStylesheetMode } from "./semantic/resolve"; +import { resolveResumeRuntime } from "./semantic/resolve"; import { getTemplatePage } from "./templates"; import { shouldShowResumeHeader } from "./templates/shared/cover-letter"; import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "./templates/shared/page-size"; @@ -63,17 +63,14 @@ export const ResumeDocument = ({ () => (renderOptions ? { ...resumeData, renderOptions } : resumeData), [resumeData, renderOptions], ); - const stylesheetMode = resolveStylesheetMode(resumeData); // The tree is built with the render options, so a letter printed with its header keeps it. const runtime = useMemo( - () => semanticRuntime ?? resolveResumeRuntime({ data: headerResumeData, template, mode: stylesheetMode }), - [headerResumeData, semanticRuntime, stylesheetMode, template], + () => semanticRuntime ?? resolveResumeRuntime({ data: headerResumeData, template }), + [headerResumeData, semanticRuntime, template], ); - const semanticMode = semanticRuntime ? "semantic" : stylesheetMode; return ( diff --git a/packages/pdf/src/semantic/all-templates-presentation.test.ts b/packages/pdf/src/semantic/all-templates-presentation.test.ts index 9efef2cbf..3b0102b56 100644 --- a/packages/pdf/src/semantic/all-templates-presentation.test.ts +++ b/packages/pdf/src/semantic/all-templates-presentation.test.ts @@ -16,7 +16,6 @@ describe("Semantic CSS all-template presentation", () => { data, template, source: comprehensiveStylesheet, - mode: "semantic", }); expect(runtime.diagnostics.filter(({ severity }) => severity === "error")).toEqual([]); @@ -35,7 +34,6 @@ describe("Semantic CSS all-template presentation", () => { data, template, source: comprehensiveStylesheet, - mode: "semantic", }); const templateParts = new Set(); diff --git a/packages/pdf/src/semantic/combined-field-bindings.test.tsx b/packages/pdf/src/semantic/combined-field-bindings.test.tsx index a1894e274..621a4501c 100644 --- a/packages/pdf/src/semantic/combined-field-bindings.test.tsx +++ b/packages/pdf/src/semantic/combined-field-bindings.test.tsx @@ -36,7 +36,7 @@ const findTexts = (node: HostNode, text: string): HostNode[] => [ ...(node.children ?? []).flatMap((child) => findTexts(child, text)), ]; -const fixture = (mode: "legacy" | "semantic", section: "experience" | "education", rule = ""): ResumeData => { +const fixture = (section: "experience" | "education", rule = ""): ResumeData => { const data = structuredClone(defaultResumeData); data.picture.hidden = true; data.basics.name = "Ada Lovelace"; @@ -69,10 +69,7 @@ const fixture = (mode: "legacy" | "semantic", section: "experience" | "education }, ]; data.metadata.layout.pages = [{ fullWidth: true, main: [section], sidebar: [] }]; - if (mode === "semantic") { - const stylesheet = { languageVersion: 1, text: `@version 1; ${rule}` }; - data.metadata.stylesheet = { mode, source: stylesheet }; - } + data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: `@version 1; ${rule}` } }; return data; }; @@ -83,14 +80,6 @@ const renderHost = async (template: Template, data: ResumeData): Promise => { - const renderer = await vi.importActual("../forme/testing"); - const element = createElement(ResumeDocument, { data, template }) as unknown as Parameters< - typeof renderer.renderToBuffer - >[0]; - return new Uint8Array(await renderer.renderToBuffer(element)); -}; - const rasterizeFirstPage = async (bytes: Uint8Array): Promise => { const document = await getDocument({ data: bytes }).promise; const page = await document.getPage(1); @@ -197,8 +186,8 @@ describe("combined PDF field bindings", () => { combined-text { color: #334455; font-size: 14pt; opacity: 0.6; margin-left: 3pt; } field[name="degree"] { opacity: 0.4; } `; - const onyxData = fixture("semantic", "education", semanticRule); - const meowthData = fixture("semantic", "education", semanticRule); + const onyxData = fixture("education", semanticRule); + const meowthData = fixture("education", semanticRule); const onyxTree = buildSemanticTree({ data: onyxData, template: "onyx", @@ -274,9 +263,9 @@ describe("combined PDF field bindings", () => { field[name="grade"] { color: #550000; } field[name="period"] { color: #660000; } `; - const experience = await renderHost("meowth", fixture("semantic", "experience", colors)); - const inlineEducation = await renderHost("meowth", fixture("semantic", "education", colors)); - const splitEducation = await renderHost("onyx", fixture("semantic", "education", colors)); + const experience = await renderHost("meowth", fixture("experience", colors)); + const inlineEducation = await renderHost("meowth", fixture("education", colors)); + const splitEducation = await renderHost("onyx", fixture("education", colors)); expect(nodeText(experience)).toContain("Engineer (London)"); expectColor(experience, "Engineer", "#110000"); @@ -299,7 +288,6 @@ describe("combined PDF field bindings", () => { it("uses the promoted single field's real semantic key", async () => { const experienceData = fixture( - "semantic", "experience", 'field[name="period"] { color: #660000; } field[name="location"] { color: #220000; }', ); @@ -308,7 +296,6 @@ describe("combined PDF field bindings", () => { experience.location = ""; const educationData = fixture( - "semantic", "education", 'field[name="period"] { color: #660000; } field[name="degree"] { color: #440000; }', ); @@ -325,11 +312,7 @@ describe("combined PDF field bindings", () => { it("keeps non-inheritable split-field styles on their final field hosts", async () => { const document = await renderHost( "meowth", - fixture( - "semantic", - "experience", - 'field[name="position"] { opacity: 0.6; } field[name="location"] { margin-left: 3pt; }', - ), + fixture("experience", 'field[name="position"] { opacity: 0.6; } field[name="location"] { margin-left: 3pt; }'), ); const combined = findTexts(document, "Engineer (London)"); const position = findTexts(document, "Engineer"); @@ -342,7 +325,7 @@ describe("combined PDF field bindings", () => { }); it("publishes one existing Text binding for every split field key", () => { - const data = fixture("semantic", "education"); + const data = fixture("education"); const tree = buildSemanticTree({ data, template: "meowth", @@ -361,20 +344,6 @@ describe("combined PDF field bindings", () => { ); }); - it.each([ - ["meowth", "experience"], - ["meowth", "education"], - ["onyx", "education"], - ] as const)( - "keeps the real %s %s section raster-identical between legacy and empty semantic mode", - async (template, section) => { - const legacy = await rasterizeFirstPage(await renderPdf(template, fixture("legacy", section))); - const semantic = await rasterizeFirstPage(await renderPdf(template, fixture("semantic", section))); - - expect(semantic.equals(legacy)).toBe(true); - }, - ); - it.each([ { name: "Meowth experience position and location", diff --git a/packages/pdf/src/semantic/context.tsx b/packages/pdf/src/semantic/context.tsx index d79c5eaae..4b1d617db 100644 --- a/packages/pdf/src/semantic/context.tsx +++ b/packages/pdf/src/semantic/context.tsx @@ -1,5 +1,4 @@ import type { SemanticNode } from "@reactive-resume/resume/stylesheet"; -import type { StylesheetMode } from "@reactive-resume/schema/resume/stylesheet"; import type { ReactNode } from "react"; import type { ResolvedPdfNodePresentation } from "./adapter"; import { createContext, use, useMemo } from "react"; @@ -9,7 +8,6 @@ export type ResolvedResumePresentation = Readonly; sourceNodeKeys: ReadonlySet; renderedChildKeys: ReadonlyMap; @@ -61,7 +58,6 @@ const indexRenderTree = (root: SemanticNode) => { export function SemanticRenderProvider({ presentation, - mode, sourceTree, renderTree, children, @@ -80,8 +76,8 @@ export function SemanticRenderProvider({ [sourceNodes], ); const value = useMemo( - () => ({ presentation, mode, sourceNodeKeys, sourceChildKeys, sourceNodes, ...treeIndex }), - [mode, presentation, sourceChildKeys, sourceNodeKeys, sourceNodes, treeIndex], + () => ({ presentation, sourceNodeKeys, sourceChildKeys, sourceNodes, ...treeIndex }), + [presentation, sourceChildKeys, sourceNodeKeys, sourceNodes, treeIndex], ); return {children}; } @@ -92,11 +88,9 @@ export function useResolvedNode(nodeKey: string | undefined): ResolvedPdfNodePre return context.presentation[nodeKey] ?? EMPTY_NODE; } -export const useSemanticRenderMode = (): StylesheetMode => use(SemanticRenderContext)?.mode ?? "legacy"; - export const useSemanticNodeVisible = (nodeKey: string | undefined): boolean => { const context = use(SemanticRenderContext); - if (context?.mode !== "semantic" || !nodeKey) return true; + if (!context || !nodeKey) return true; return context.renderedNodeKeys.has(nodeKey); }; @@ -107,7 +101,7 @@ export const useSemanticNodeExists = (nodeKey: string | undefined): boolean => { export const useRenderedChildKeys = (nodeKey: string | undefined): readonly string[] | undefined => { const context = use(SemanticRenderContext); - if (context?.mode !== "semantic" || !nodeKey) return undefined; + if (!context || !nodeKey) return undefined; const rendered = context.renderedChildKeys.get(nodeKey) ?? []; const source = context.sourceChildKeys.get(nodeKey) ?? []; return rendered.length === source.length && rendered.every((key, index) => key === source[index]) @@ -142,7 +136,7 @@ export const useSemanticSectionNodeKey = (pageNodeKey: string, sectionId: string export const useRenderedSectionIds = (pageNodeKey: string, authoredIds: readonly string[]): string[] => { const context = use(SemanticRenderContext); - if (context?.mode !== "semantic") return [...authoredIds]; + if (!context) return [...authoredIds]; const authored = new Set(authoredIds); return context.sourceNodes @@ -171,11 +165,11 @@ export const useSemanticNodeBindings = () => { return context.presentation[nodeKey] ?? EMPTY_NODE; }, isNodeVisible: (nodeKey: string | undefined): boolean => { - if (context?.mode !== "semantic" || !nodeKey) return true; + if (!context || !nodeKey) return true; return context.renderedNodeKeys.has(nodeKey); }, renderedChildKeysFor: (nodeKey: string | undefined): readonly string[] | undefined => { - if (context?.mode !== "semantic" || !nodeKey) return undefined; + if (!context || !nodeKey) return undefined; const rendered = context.renderedChildKeys.get(nodeKey) ?? []; const source = context.sourceChildKeys.get(nodeKey) ?? []; return rendered.length === source.length && rendered.every((key, index) => key === source[index]) diff --git a/packages/pdf/src/semantic/index.ts b/packages/pdf/src/semantic/index.ts index 2e65dc41f..1b71895a9 100644 --- a/packages/pdf/src/semantic/index.ts +++ b/packages/pdf/src/semantic/index.ts @@ -6,6 +6,5 @@ export * from "./legacy-converter"; export { resolveResumePresentation, resolveResumeRuntime, - resolveStylesheetMode, } from "./resolve"; export * from "./tree"; diff --git a/packages/pdf/src/semantic/issue-fixtures.test.tsx b/packages/pdf/src/semantic/issue-fixtures.test.tsx index 836caf0a6..6d129fa09 100644 --- a/packages/pdf/src/semantic/issue-fixtures.test.tsx +++ b/packages/pdf/src/semantic/issue-fixtures.test.tsx @@ -6,7 +6,7 @@ import { defaultResumeData } from "@reactive-resume/schema/resume/default"; import { ResumeDocument } from "../document"; import { pdf } from "../forme/testing"; import { semanticNodeKeys } from "./node-keys"; -import { resolveResumePresentation, resolveStylesheetMode } from "./resolve"; +import { resolveResumePresentation } from "./resolve"; const source = (text: string) => ({ languageVersion: 1, text }); @@ -100,7 +100,6 @@ const resolveIssueFixture = (text: string) => { data, template: "onyx", source: source(text), - mode: "semantic", }); }; @@ -148,7 +147,6 @@ describe("semantic issue fixtures", () => { data, template: "onyx", source: source(`@version 1;${text}`), - mode: "semantic", }); expect(resolve("contact-item { color: red; } link { color: blue; }")[contact]?.style?.color).toBe("blue"); @@ -185,26 +183,6 @@ describe("semantic issue fixtures", () => { expect(presentation[company]?.style?.fontWeight).not.toBe("400"); }); - it("never applies legacy and semantic custom styles together", () => { - const semanticData = buildIssueFixture(); - semanticData.metadata.stylesheet = { - mode: "semantic", - source: source("@version 1;"), - }; - const legacyData = buildIssueFixture(); - - expect(resolveStylesheetMode(semanticData)).toBe("semantic"); - expect(resolveStylesheetMode(legacyData)).toBe("legacy"); - expect( - resolveResumePresentation({ - data: legacyData, - template: "onyx", - source: source("@version 1; name { color: red; }"), - mode: "legacy", - }), - ).toEqual({}); - }); - it("applies issue-regression styles to the final existing PDF primitives", async () => { const data = buildIssueFixture(); const stylesheet = source(` diff --git a/packages/pdf/src/semantic/item-header-binding.test.tsx b/packages/pdf/src/semantic/item-header-binding.test.tsx index e20a9f81c..02b28ddf7 100644 --- a/packages/pdf/src/semantic/item-header-binding.test.tsx +++ b/packages/pdf/src/semantic/item-header-binding.test.tsx @@ -58,7 +58,6 @@ const renderHeaderBoxes = async (template: Template): Promise => { const semanticRuntime = resolveResumeRuntime({ data, template, - mode: "semantic", source: { languageVersion: 1, text: STYLESHEET }, }); const element = createElement(ResumeDocument, { data, template, semanticRuntime }) as unknown as Parameters< diff --git a/packages/pdf/src/semantic/item-header-row.test.tsx b/packages/pdf/src/semantic/item-header-row.test.tsx index 737d9971f..df75590f3 100644 --- a/packages/pdf/src/semantic/item-header-row.test.tsx +++ b/packages/pdf/src/semantic/item-header-row.test.tsx @@ -65,7 +65,7 @@ const buildFixture = (): ResumeData => { const renderTitleRowStyles = async (template: Template, stylesheet?: string) => { const data = buildFixture(); const semanticRuntime = stylesheet - ? resolveResumeRuntime({ data, template, mode: "semantic", source: { languageVersion: 1, text: stylesheet } }) + ? resolveResumeRuntime({ data, template, source: { languageVersion: 1, text: stylesheet } }) : undefined; const element = createElement(ResumeDocument, { data, template, semanticRuntime }) as unknown as Parameters< typeof pdf diff --git a/packages/pdf/src/semantic/legacy-render-parity.test.tsx b/packages/pdf/src/semantic/legacy-adoption-render.test.tsx similarity index 62% rename from packages/pdf/src/semantic/legacy-render-parity.test.tsx rename to packages/pdf/src/semantic/legacy-adoption-render.test.tsx index c4c15767d..273051ff2 100644 --- a/packages/pdf/src/semantic/legacy-render-parity.test.tsx +++ b/packages/pdf/src/semantic/legacy-adoption-render.test.tsx @@ -159,94 +159,60 @@ const render = async (data: ResumeData, template: Template): Promise return new Uint8Array(await renderToBuffer(document)); }; -const semanticData = (data: ResumeData): ResumeData => { +// What the API stores on read/write: the legacy rules converted into the resume's Semantic CSS stylesheet. +const adopt = (data: ResumeData): ResumeData => { const conversion = convertLegacyStyleRules(data); - const semantic = structuredClone(data); - semantic.metadata.styleRules = [...conversion.sanitizedRules]; - semantic.metadata.stylesheet = { mode: "semantic", source: conversion.source }; - return semantic; + const adopted = structuredClone(data); + adopted.metadata.styleRules = [...conversion.sanitizedRules]; + adopted.metadata.stylesheet = { mode: "semantic", source: conversion.source }; + return adopted; }; -type RasterComparison = { - pixelDiffRatio: number; - mismatches: readonly string[]; -}; - -const comparePdfRasters = async (legacy: Uint8Array, semantic: Uint8Array): Promise => { - const legacyPages = await rasterizePdf(legacy); - const semanticPages = await rasterizePdf(semantic); +const comparePdfRasters = async (before: Uint8Array, after: Uint8Array): Promise => { + const beforePages = await rasterizePdf(before); + const afterPages = await rasterizePdf(after); const mismatches: string[] = []; - if (legacyPages.length !== semanticPages.length) { - mismatches.push(`page count: legacy=${legacyPages.length} semantic=${semanticPages.length}`); + if (beforePages.length !== afterPages.length) { + mismatches.push(`page count: ${beforePages.length} -> ${afterPages.length}`); } - - let changed = 0; - let pixels = 0; - for (const [index, legacyPage] of legacyPages.entries()) { - const semanticPage = semanticPages[index]; - if (!semanticPage) continue; - if (semanticPage.width !== legacyPage.width || semanticPage.height !== legacyPage.height) { - mismatches.push( - `page ${index + 1} dimensions: legacy=${legacyPage.width}x${legacyPage.height} semantic=${semanticPage.width}x${semanticPage.height}`, - ); + for (const [index, beforePage] of beforePages.entries()) { + const afterPage = afterPages[index]; + if (!afterPage) continue; + if (afterPage.width !== beforePage.width || afterPage.height !== beforePage.height) { + mismatches.push(`page ${index + 1} dimensions changed`); continue; } - const changedOnPage = pixelmatch( - legacyPage.data, - semanticPage.data, - undefined, - legacyPage.width, - legacyPage.height, - { threshold: 0 }, - ); - if (changedOnPage > 0) { - mismatches.push(`page ${index + 1} pixels: changed=${changedOnPage}/${legacyPage.width * legacyPage.height}`); - } - changed += changedOnPage; - pixels += legacyPage.width * legacyPage.height; + const changed = pixelmatch(beforePage.data, afterPage.data, undefined, beforePage.width, beforePage.height, { + threshold: 0, + }); + if (changed > 0) mismatches.push(`page ${index + 1} pixels: changed=${changed}`); } - return { pixelDiffRatio: pixels === 0 ? (mismatches.length > 0 ? 1 : 0) : changed / pixels, mismatches }; + return mismatches; }; -describe("legacy activation raster parity", () => { - it.each(fixtureNames)( - "has zero real-PDF pixel drift for %s", - async (fixture) => { - const legacy = buildFixture(readRules(fixture)); - const semantic = semanticData(legacy); +// Rules with no visible effect on this fixture: disabled, or restating the award title's existing weight. +const noOpFixtures = new Set(["award-unbold", "disabled-rules"]); - expect(await comparePdfRasters(await render(legacy, "onyx"), await render(semantic, "onyx"))).toEqual({ - pixelDiffRatio: 0, - mismatches: [], - }); +// Unconverted rules no longer render, so the fixture itself is the unstyled baseline. +const drift = async (data: ResumeData, template: Template) => + comparePdfRasters(await render(data, template), await render(adopt(data), template)); + +describe("adopted legacy rules in the rendered PDF", () => { + it.each(fixtureNames)( + "renders the converted %s stylesheet", + async (fixture) => { + const mismatches = await drift(buildFixture(readRules(fixture)), "onyx"); + + if (noOpFixtures.has(fixture)) expect(mismatches).toEqual([]); + else expect(mismatches).not.toEqual([]); }, 30_000, ); it.each(templates)( - "smoke-renders %s without activation pixel drift", + "renders the converted smoke stylesheet on %s", async (template) => { - const legacy = buildFixture(readRules("all-templates-smoke")); - const semantic = semanticData(legacy); - - expect(await comparePdfRasters(await render(legacy, template), await render(semantic, template))).toEqual({ - pixelDiffRatio: 0, - mismatches: [], - }); - }, - 30_000, - ); - - it.each(["onyx", "meowth"] as const)( - "has zero combined-separator and box-style pixel drift on %s", - async (template) => { - const legacy = buildFixture(readRules("combined-text-host")); - const semantic = semanticData(legacy); - - expect(await comparePdfRasters(await render(legacy, template), await render(semantic, template))).toEqual({ - pixelDiffRatio: 0, - mismatches: [], - }); + expect(await drift(buildFixture(readRules("all-templates-smoke")), template)).not.toEqual([]); }, 30_000, ); diff --git a/packages/pdf/src/semantic/link-fidelity.test.tsx b/packages/pdf/src/semantic/link-fidelity.test.tsx index 4771d6fbd..536b1e293 100644 --- a/packages/pdf/src/semantic/link-fidelity.test.tsx +++ b/packages/pdf/src/semantic/link-fidelity.test.tsx @@ -15,7 +15,7 @@ type HostNode = { const emptyStylesheet = { languageVersion: 1, text: "@version 1;" }; const buildFixture = ( - mode: "missing" | "legacy" | "semantic", + mode: "missing" | "semantic", hideLinkUnderline: boolean, text = emptyStylesheet.text, ): ResumeData => { @@ -58,8 +58,6 @@ describe("PDF link decoration fidelity", () => { it.each([ ["missing", false, "underline"], ["missing", true, "none"], - ["legacy", false, "underline"], - ["legacy", true, "none"], ["semantic", false, "underline"], ["semantic", true, "none"], ] as const)("%s stylesheet with hideLinkUnderline=%s resolves to %s", async (mode, hidden, expected) => { diff --git a/packages/pdf/src/semantic/no-wrapper.test.tsx b/packages/pdf/src/semantic/no-wrapper.test.tsx index 61fd09f5c..5cd2ead6a 100644 --- a/packages/pdf/src/semantic/no-wrapper.test.tsx +++ b/packages/pdf/src/semantic/no-wrapper.test.tsx @@ -23,7 +23,7 @@ const semanticSource = (text = "@version 1;\n") => ({ text, }); -const buildFixture = (mode: "legacy" | "semantic"): ResumeData => { +const buildFixture = (withStylesheet: boolean): ResumeData => { const data = structuredClone(sampleResumeData); data.picture.hidden = true; data.basics.name = "Ada Lovelace"; @@ -49,9 +49,9 @@ const buildFixture = (mode: "legacy" | "semantic"): ResumeData => { sidebar: ["skills", "languages"], }, ]; - if (mode === "semantic") { + if (withStylesheet) { data.metadata.stylesheet = { - mode, + mode: "semantic", source: semanticSource(), }; } @@ -74,9 +74,9 @@ const textValues = (node: HostNode): string[] => [ ...(node.children ?? []).flatMap((child) => textValues(child)), ]; -describe("semantic PDF bindings do not add layout wrappers", () => { +describe("resumes without a stylesheet render like an empty stylesheet", () => { it("uses a split-page fixture with chrome, ordinary sections, rich lists, and levels", () => { - const data = buildFixture("legacy"); + const data = buildFixture(false); expect(data.metadata.layout.pages[0]).toMatchObject({ fullWidth: false, @@ -93,11 +93,11 @@ describe("semantic PDF bindings do not add layout wrappers", () => { it.each(templateSchema.options)( "%s preserves primitive type, count, and order for an empty stylesheet", async (template) => { - const legacy = await renderHostTree(buildFixture("legacy"), template); - const semantic = await renderHostTree(buildFixture("semantic"), template); + const missing = await renderHostTree(buildFixture(false), template); + const empty = await renderHostTree(buildFixture(true), template); - expect(textValues(semantic)).toEqual(textValues(legacy)); - expect(primitiveTypes(semantic)).toEqual(primitiveTypes(legacy)); + expect(textValues(empty)).toEqual(textValues(missing)); + expect(primitiveTypes(empty)).toEqual(primitiveTypes(missing)); }, ); }); diff --git a/packages/pdf/src/semantic/pagination-cancellation.test.tsx b/packages/pdf/src/semantic/pagination-cancellation.test.tsx index 111ecc2a0..9f8e0cb99 100644 --- a/packages/pdf/src/semantic/pagination-cancellation.test.tsx +++ b/packages/pdf/src/semantic/pagination-cancellation.test.tsx @@ -70,7 +70,7 @@ describe("semantic pagination cancellation", () => { ["revert", true, false], ] as const)("maps %s over builder pagination to explicit break=%s and wrap=%s", (value, breakBefore, wrap) => { const data = buildFixture(value); - const presentation = resolveResumePresentation({ data, template: "onyx", mode: "semantic" }); + const presentation = resolveResumePresentation({ data, template: "onyx" }); const sectionKey = semanticNodeKeys.section(semanticNodeKeys.region(semanticNodeKeys.page(1), "main"), "summary"); expect(presentation[sectionKey]).toMatchObject({ break: breakBefore, wrap }); diff --git a/packages/pdf/src/semantic/public.test.ts b/packages/pdf/src/semantic/public.test.ts index 19c4c7636..b997bf882 100644 --- a/packages/pdf/src/semantic/public.test.ts +++ b/packages/pdf/src/semantic/public.test.ts @@ -7,7 +7,7 @@ describe("@reactive-resume/pdf/semantic", () => { const data = structuredClone(sampleResumeData); data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 2, text: "@version 2;" } }; - const inspection = resolveResumeRuntime({ data, template: data.metadata.template, mode: "semantic" }); + const inspection = resolveResumeRuntime({ data, template: data.metadata.template }); expect(inspection.diagnostics).toContainEqual( expect.objectContaining({ code: "UNSUPPORTED_VERSION", severity: "error" }), @@ -23,7 +23,7 @@ describe("@reactive-resume/pdf/semantic", () => { source: { languageVersion: 1, text: `@version 1;\n${selectors} { color: red; }` }, }; - const inspection = resolveResumeRuntime({ data, template: data.metadata.template, mode: "semantic" }); + const inspection = resolveResumeRuntime({ data, template: data.metadata.template }); expect(inspection.diagnostics).toContainEqual( expect.objectContaining({ code: "RESOURCE_LIMIT", severity: "error" }), @@ -42,7 +42,7 @@ describe("@reactive-resume/pdf/semantic", () => { }, }; - const inspection = resolveResumeRuntime({ data, template: data.metadata.template, mode: "semantic" }); + const inspection = resolveResumeRuntime({ data, template: data.metadata.template }); expect(inspection.presentation["page-1/region-header/header/name"]?.style?.color).toBe("#123456"); expect(inspection.diagnostics).toContainEqual( diff --git a/packages/pdf/src/semantic/resolve.ts b/packages/pdf/src/semantic/resolve.ts index a88becb29..cae5394f1 100644 --- a/packages/pdf/src/semantic/resolve.ts +++ b/packages/pdf/src/semantic/resolve.ts @@ -1,6 +1,6 @@ import type { ResolveStylesheetResult, SemanticCssDiagnostic, SemanticNode } from "@reactive-resume/resume/stylesheet"; import type { ResumeData } from "@reactive-resume/schema/resume/data"; -import type { StylesheetMode, StylesheetSource } from "@reactive-resume/schema/resume/stylesheet"; +import type { StylesheetSource } from "@reactive-resume/schema/resume/stylesheet"; import type { Template } from "@reactive-resume/schema/templates"; import type { ResolvedResumePresentation } from "./context"; import { compileStylesheet, isFatalStylesheetDiagnostic, resolveStylesheet } from "@reactive-resume/resume/stylesheet"; @@ -18,7 +18,6 @@ export type ResolveResumePresentationInput = { data: ResumeData; template: Template; source?: StylesheetSource; - mode: StylesheetMode; }; export type ResolvedResumeRuntime = { @@ -78,20 +77,12 @@ const toPresentation = ( ) as ResolvedResumePresentation; }; -export function resolveStylesheetMode(data: ResumeData): StylesheetMode { - return data.metadata.stylesheet?.mode ?? "legacy"; -} - export function resolveResumeRuntime({ data, template, source, - mode, }: ResolveResumePresentationInput): ResolvedResumeRuntime { const sourceTree = mergeAuthoredPageTrees(data, template); - if (mode !== "semantic") { - return { presentation: EMPTY_PRESENTATION, sourceTree, renderTree: sourceTree, diagnostics: [] }; - } const stylesheetSource = source ?? data.metadata.stylesheet?.source ?? { diff --git a/packages/pdf/src/semantic/rich-text-table.integration.test.tsx b/packages/pdf/src/semantic/rich-text-table.integration.test.tsx index abc997c40..090b0ff62 100644 --- a/packages/pdf/src/semantic/rich-text-table.integration.test.tsx +++ b/packages/pdf/src/semantic/rich-text-table.integration.test.tsx @@ -19,7 +19,7 @@ const table = (paragraphs = false) => ) .join("")}`; -const fixture = (html: string, mode: "legacy" | "semantic", css = ""): ResumeData => { +const fixture = (html: string, css = ""): ResumeData => { const data = structuredClone(defaultResumeData); data.basics.name = "Table probe"; data.picture.hidden = true; @@ -27,7 +27,7 @@ const fixture = (html: string, mode: "legacy" | "semantic", css = ""): ResumeDat data.metadata.layout.pages = [{ fullWidth: true, main: ["summary"], sidebar: [] }]; data.metadata.typography.body.fontFamily = "Helvetica"; data.metadata.typography.heading.fontFamily = "Helvetica"; - data.metadata.stylesheet = { mode, source: { languageVersion: 1, text: `@version 1; ${css}` } }; + data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: `@version 1; ${css}` } }; return data; }; @@ -95,96 +95,90 @@ const tableCoordinates = (items: Awaited>["items"]) = describe("imported rich-text tables", () => { for (const template of ["ditgar", "onyx"] as const) { - for (const mode of ["legacy", "semantic"] as const) { - it(`${template} ${mode} preserves bare cell text and row/column positions`, async () => { - const { items } = await readPdf(fixture(table(), mode), template); - const cell = (text: string) => { - const cell = items.find((item) => item.text === text); - if (!cell) throw new Error(`Missing table cell ${text}`); - return cell; - }; - const alpha = cell("Alpha"); - const beta = cell("Beta"); - const gamma = cell("Gamma"); - const delta = cell("Delta"); - const epsilon = cell("Epsilon"); - const zeta = cell("Zeta"); - expect(alpha.y).toBe(beta.y); - expect(alpha.y).toBe(gamma.y); - expect(delta.y).toBe(epsilon.y); - expect(delta.y).toBe(zeta.y); - expect(alpha.y).toBeGreaterThan(delta.y); - expect(alpha.x).toBe(delta.x); - expect(beta.x).toBe(epsilon.x); - expect(gamma.x).toBe(zeta.x); - expect(beta.x).toBeGreaterThan(alpha.x); - expect(gamma.x).toBeGreaterThan(beta.x); - }); - } + it(`${template} preserves bare cell text and row/column positions`, async () => { + const { items } = await readPdf(fixture(table()), template); + const cell = (text: string) => { + const cell = items.find((item) => item.text === text); + if (!cell) throw new Error(`Missing table cell ${text}`); + return cell; + }; + const alpha = cell("Alpha"); + const beta = cell("Beta"); + const gamma = cell("Gamma"); + const delta = cell("Delta"); + const epsilon = cell("Epsilon"); + const zeta = cell("Zeta"); + expect(alpha.y).toBe(beta.y); + expect(alpha.y).toBe(gamma.y); + expect(delta.y).toBe(epsilon.y); + expect(delta.y).toBe(zeta.y); + expect(alpha.y).toBeGreaterThan(delta.y); + expect(alpha.x).toBe(delta.x); + expect(beta.x).toBe(epsilon.x); + expect(gamma.x).toBe(zeta.x); + expect(beta.x).toBeGreaterThan(alpha.x); + expect(gamma.x).toBeGreaterThan(beta.x); + }); } it("preserves table cells containing recognized paragraphs", async () => { - const { items } = await readPdf(fixture(table(true), "semantic"), "ditgar"); + const { items } = await readPdf(fixture(table(true)), "ditgar"); expect(items.map((item) => item.text)).toEqual(expect.arrayContaining(["Alpha", "Beta", "Gamma", "Delta"])); }); it("preserves raw text inside an unrecognized block wrapper", async () => { - const { items } = await readPdf(fixture("
Wrapper content
", "semantic"), "ditgar"); + const { items } = await readPdf(fixture("
Wrapper content
"), "ditgar"); expect(items.map((item) => item.text)).toContain("Wrapper content"); }); it("still honors explicit semantic rich-text hiding", async () => { - const { items } = await readPdf(fixture(table(), "semantic", "rich-text { display: none; }"), "ditgar"); + const { items } = await readPdf(fixture(table(), "rich-text { display: none; }"), "ditgar"); expect(items.map((item) => item.text)).toContain("Table probe"); expect(items.map((item) => item.text)).not.toContain("Alpha"); }); - it.each(["legacy", "semantic"] as const)( - "keeps six cell coordinates, border operators, and fixed-DPI pixels through %s persistence", - async (mode) => { - const bordered = table().replaceAll("black", "#cc00cc"); - const unrelated = fixture(bordered, mode); - unrelated.basics.name = "Border Probe unrelated edit"; - const stages = [ - { name: "original", data: fixture(bordered, mode), expectedBeta: "Beta" }, - { name: "unrelated edit", data: unrelated, expectedBeta: "Beta" }, - { name: "table edit", data: fixture(bordered.replace("Beta", "Beta!"), mode), expectedBeta: "Beta!" }, + it("keeps six cell coordinates, border operators, and fixed-DPI pixels through persistence", async () => { + const bordered = table().replaceAll("black", "#cc00cc"); + const unrelated = fixture(bordered); + unrelated.basics.name = "Border Probe unrelated edit"; + const stages = [ + { name: "original", data: fixture(bordered), expectedBeta: "Beta" }, + { name: "unrelated edit", data: unrelated, expectedBeta: "Beta" }, + { name: "table edit", data: fixture(bordered.replace("Beta", "Beta!")), expectedBeta: "Beta!" }, + ]; + // The first render sets the reference: three equal columns over two rows, with the borders drawn. Neither an + // unrelated edit nor an edit inside a cell may move a cell or change a border. + let reference: { cells: Record; colored: unknown } | undefined; + for (const stage of stages) { + const pdf = await readPdf(stage.data, "ditgar"); + const cells = tableCoordinates(pdf.items); + const { colored } = await inspectTableBorders(pdf); + const cell = (text: string) => { + const [x, y] = cells[text] ?? []; + if (x === undefined || y === undefined) throw new Error(`${stage.name}: missing cell ${text}`); + return { x, y }; + }; + const [alpha, beta, gamma, delta] = ["Alpha", stage.expectedBeta, "Gamma", "Delta"].map(cell) as [ + { x: number; y: number }, + { x: number; y: number }, + { x: number; y: number }, + { x: number; y: number }, ]; - // The first render sets the reference: three equal columns over two rows, with the borders drawn. Neither an - // unrelated edit nor an edit inside a cell may move a cell or change a border. - let reference: { cells: Record; colored: unknown } | undefined; - for (const stage of stages) { - const pdf = await readPdf(stage.data, "ditgar"); - const cells = tableCoordinates(pdf.items); - const { colored } = await inspectTableBorders(pdf); - const cell = (text: string) => { - const [x, y] = cells[text] ?? []; - if (x === undefined || y === undefined) throw new Error(`${stage.name}: missing cell ${text}`); - return { x, y }; - }; - const [alpha, beta, gamma, delta] = ["Alpha", stage.expectedBeta, "Gamma", "Delta"].map(cell) as [ - { x: number; y: number }, - { x: number; y: number }, - { x: number; y: number }, - { x: number; y: number }, - ]; - expect(beta.x - alpha.x, stage.name).toBeCloseTo(gamma.x - beta.x, 1); - expect(beta.y, stage.name).toBe(alpha.y); - expect(delta.x, stage.name).toBe(alpha.x); - expect(delta.y, stage.name).toBeLessThan(alpha.y); - expect((colored as { pixels: number }).pixels, stage.name).toBeGreaterThan(0); - const { [stage.expectedBeta]: _beta, ...rest } = cells; - const comparable = { cells: { ...rest, Beta: [beta.x, beta.y] }, colored }; - if (reference) expect(comparable, stage.name).toEqual(reference); - else reference = comparable; - } - }, - 30_000, - ); + expect(beta.x - alpha.x, stage.name).toBeCloseTo(gamma.x - beta.x, 1); + expect(beta.y, stage.name).toBe(alpha.y); + expect(delta.x, stage.name).toBe(alpha.x); + expect(delta.y, stage.name).toBeLessThan(alpha.y); + expect((colored as { pixels: number }).pixels, stage.name).toBeGreaterThan(0); + const { [stage.expectedBeta]: _beta, ...rest } = cells; + const comparable = { cells: { ...rest, Beta: [beta.x, beta.y] }, colored }; + if (reference) expect(comparable, stage.name).toEqual(reference); + else reference = comparable; + } + }, 30_000); - it.each(["legacy", "semantic"] as const)("keeps borderless tables borderless in %s mode", async (mode) => { + it("keeps borderless tables borderless", async () => { const borderless = table().replaceAll("border: 1pt solid black; ", ""); - const pdf = await readPdf(fixture(borderless, mode), "ditgar"); + const pdf = await readPdf(fixture(borderless), "ditgar"); expect((await inspectTableBorders(pdf)).geometry).toEqual({ horizontal: 0, vertical: 0 }); }); }); diff --git a/packages/pdf/src/semantic/runtime-paths.test.tsx b/packages/pdf/src/semantic/runtime-paths.test.tsx index 490ba0031..b73c8f4d3 100644 --- a/packages/pdf/src/semantic/runtime-paths.test.tsx +++ b/packages/pdf/src/semantic/runtime-paths.test.tsx @@ -57,11 +57,11 @@ const buildFixture = (): ResumeData => { return data; }; -const buildNodeBudgetFixture = (mode: "legacy" | "semantic"): ResumeData => { +const buildNodeBudgetFixture = (): ResumeData => { const data = structuredClone(defaultResumeData); const source = { languageVersion: 1, text: "@version 1;\n" }; data.metadata.layout.pages = [{ fullWidth: true, main: ["skills"], sidebar: [] }]; - data.metadata.stylesheet = { mode, source }; + data.metadata.stylesheet = { mode: "semantic", source }; data.sections.skills.items = Array.from({ length: 2_000 }, (_, index) => ({ id: `skill-${index}`, hidden: false, @@ -128,8 +128,8 @@ describe("browser/server semantic runtime identity", () => { expect(browserProps).toEqual(serverProps); }, 15_000); - it("keeps legacy PDF rendering unaffected by the semantic node budget", async () => { - const data = buildNodeBudgetFixture("legacy"); + it("still renders a resume beyond the semantic node budget", async () => { + const data = buildNodeBudgetFixture(); const blob = await createResumePdfBlob({ data, template: "onyx" }); const file = await createResumePdfFile({ data, filename: "resume.pdf", template: "onyx" }); diff --git a/packages/pdf/src/semantic/sibling-ordering.test.tsx b/packages/pdf/src/semantic/sibling-ordering.test.tsx index f52f4a494..302641345 100644 --- a/packages/pdf/src/semantic/sibling-ordering.test.tsx +++ b/packages/pdf/src/semantic/sibling-ordering.test.tsx @@ -237,7 +237,7 @@ describe("semantic sibling ordering reaches final PDF output", () => { data.metadata.page.locale = locale; data.summary.content = "
  • List content
"; data.metadata.layout.pages = [{ fullWidth: true, main: ["summary"], sidebar: [] }]; - const runtime = resolveResumeRuntime({ data, template: "onyx", mode: "semantic" }); + const runtime = resolveResumeRuntime({ data, template: "onyx" }); const renderedItem = findSemanticNode(runtime.renderTree, (node) => node.kind === "list-item"); expect(runtime.diagnostics.filter(({ severity }) => severity === "error")).toEqual([]); diff --git a/packages/pdf/src/templates/ditgar/DitgarPage.test.tsx b/packages/pdf/src/templates/ditgar/DitgarPage.test.tsx index 1b597415a..c56051d00 100644 --- a/packages/pdf/src/templates/ditgar/DitgarPage.test.tsx +++ b/packages/pdf/src/templates/ditgar/DitgarPage.test.tsx @@ -7,7 +7,6 @@ import { ResumeDocument } from "../../document"; import { renderToBuffer } from "../../forme/testing"; type FixtureOptions = { - mode: "legacy" | "semantic"; columns: number; gapX: number; rtl?: boolean; @@ -19,7 +18,7 @@ type FixtureOptions = { type TextRun = { text: string; x: number; right: number; y: number }; -function fixture({ mode, columns, gapX, rtl, sidebar, longTitle, experience, css = "" }: FixtureOptions): ResumeData { +function fixture({ columns, gapX, rtl, sidebar, longTitle, experience, css = "" }: FixtureOptions): ResumeData { const data = structuredClone(defaultResumeData); data.metadata.typography.body.fontFamily = "Helvetica"; data.metadata.typography.heading.fontFamily = "Helvetica"; @@ -30,7 +29,7 @@ function fixture({ mode, columns, gapX, rtl, sidebar, longTitle, experience, css data.metadata.layout.pages = [ { fullWidth: false, main: sidebar ? [] : [section], sidebar: sidebar ? [section] : [] }, ]; - data.metadata.stylesheet = { mode, source: { languageVersion: 1, text: `@version 1; ${css}` } }; + data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: `@version 1; ${css}` } }; data.sections.projects.columns = columns; data.sections.experience.columns = columns; for (let index = 0; index < 3; index++) { @@ -82,29 +81,26 @@ function assertAligned(runs: TextRun[], rtl = false, expectedOffset = 0) { } describe("Ditgar item-header alignment (#3068)", () => { - for (const mode of ["legacy", "semantic"] as const) { - for (const columns of [1, 2]) { - it.each([0, 4, 12])(`aligns ${mode} Projects in ${columns} columns at gapX %i`, async (gapX) => { - assertAligned(await renderText({ mode, columns, gapX })); - }); - } - it(`aligns wrapped ${mode} project titles with their descriptions and links`, async () => { - assertAligned(await renderText({ mode, columns: 2, gapX: 4, longTitle: true })); - }); - it(`aligns the shared ${mode} Experience header`, async () => { - assertAligned(await renderText({ mode, columns: 2, gapX: 4, experience: true })); - }); - it(`preserves ${mode} sidebar alignment`, async () => { - assertAligned(await renderText({ mode, columns: 1, gapX: 4, sidebar: true })); - }); - it(`preserves ${mode} RTL alignment`, async () => { - assertAligned(await renderText({ mode, columns: 2, gapX: 4, rtl: true }), true); + for (const columns of [1, 2]) { + it.each([0, 4, 12])(`aligns Projects in ${columns} columns at gapX %i`, async (gapX) => { + assertAligned(await renderText({ columns, gapX })); }); } + it("aligns wrapped project titles with their descriptions and links", async () => { + assertAligned(await renderText({ columns: 2, gapX: 4, longTitle: true })); + }); + it("aligns the shared Experience header", async () => { + assertAligned(await renderText({ columns: 2, gapX: 4, experience: true })); + }); + it("preserves sidebar alignment", async () => { + assertAligned(await renderText({ columns: 1, gapX: 4, sidebar: true })); + }); + it("preserves RTL alignment", async () => { + assertAligned(await renderText({ columns: 2, gapX: 4, rtl: true }), true); + }); it("retains an authored Semantic CSS header inset", async () => { assertAligned( await renderText({ - mode: "semantic", columns: 2, gapX: 4, css: "item-header { margin-left: 7pt; padding-left: 3pt; border-left: 2pt solid #0000ff; }", diff --git a/packages/pdf/src/templates/gengar/gengar-skills.test.tsx b/packages/pdf/src/templates/gengar/gengar-skills.test.tsx index 812702e6f..841c1a21b 100644 --- a/packages/pdf/src/templates/gengar/gengar-skills.test.tsx +++ b/packages/pdf/src/templates/gengar/gengar-skills.test.tsx @@ -13,7 +13,6 @@ import { rasterizePdf } from "../../semantic/test/rasterize-pdf"; type SkillLayout = "default" | "inline"; type Placement = "main" | "sidebar"; type LevelDesign = "circle" | "rectangle" | "rectangle-full"; -type StylesheetMode = "legacy" | "semantic"; type GengarFixtureOptions = { keywordLayout?: "inline" | "list"; @@ -25,7 +24,6 @@ type GengarFixtureOptions = { proficiency?: string; keywords?: string[]; custom?: boolean; - mode?: StylesheetMode; count?: number; overflow?: boolean; }; @@ -45,7 +43,6 @@ const gengarFixture = ({ proficiency = "Experienced", keywords = ["Alpha", "Beta"], custom = false, - mode = "legacy", count = 1, overflow = false, }: GengarFixtureOptions = {}): ResumeData => { @@ -89,8 +86,6 @@ const gengarFixture = ({ mode: "semantic", source: { languageVersion: 1, text: "@version 1; page { size: 300pt 220pt; }" }, }; - } else if (mode === "semantic") { - data.metadata.stylesheet = { mode, source: { languageVersion: 1, text: "@version 1;" } }; } if (custom) data.customSections = [{ ...section, id: sectionId, type: "skills" }]; else data.sections.skills = section; @@ -125,11 +120,7 @@ describe("Gengar skill rating placement (#2611)", () => { { layout: "default" as const, placement: "main" as const, columns: 2, design: "rectangle-full" as const, level: 5 }, ])("orders name, rating, proficiency, keywords in $layout/$placement/$design", (options) => { const data = gengarFixture(options); - const runtime = resolveResumeRuntime({ - data, - template: "gengar", - mode: options.layout === "inline" ? "semantic" : "legacy", - }); + const runtime = resolveResumeRuntime({ data, template: "gengar" }); const item = required(getSkillItem(runtime)); const level = required(item.children.find((node) => node.kind === "level")); const header = required(item.children.find((node) => node.kind === "item-header")); @@ -143,7 +134,7 @@ describe("Gengar skill rating placement (#2611)", () => { it.each([0, 3, 5])("keeps level %s semantic decorations", (level) => { const data = gengarFixture({ level }); - const runtime = resolveResumeRuntime({ data, template: "gengar", mode: "legacy" }); + const runtime = resolveResumeRuntime({ data, template: "gengar" }); const item = required(getSkillItem(runtime)); const rating = item.children.find((node) => node.kind === "level"); if (level === 0) expect(rating).toBeUndefined(); @@ -153,7 +144,7 @@ describe("Gengar skill rating placement (#2611)", () => { it("hides rating without leaving a rating node or spacing", async () => { const data = gengarFixture({ design: "circle", level: 5 }); data.metadata.design.level = { type: "hidden", icon: "star" }; - const runtime = resolveResumeRuntime({ data, template: "gengar", mode: "semantic" }); + const runtime = resolveResumeRuntime({ data, template: "gengar" }); expect(required(getSkillItem(runtime)).children.map((node) => node.kind)).toEqual([ "item-header", "field", @@ -169,7 +160,7 @@ describe("Gengar skill rating placement (#2611)", () => { it("omits level-zero rating without adding rating spacing and keeps empty proficiency", async () => { const data = gengarFixture({ level: 0, proficiency: "", keywords: ["Short"] }); - const runtime = resolveResumeRuntime({ data, template: "gengar", mode: "legacy" }); + const runtime = resolveResumeRuntime({ data, template: "gengar" }); const item = required(getSkillItem(runtime)); expect(item.children.map((node) => node.kind)).toEqual(["item-header", "field"]); expect(item.children.at(-1)?.attributes.name).toBe("keywords"); @@ -177,9 +168,9 @@ describe("Gengar skill rating placement (#2611)", () => { expect(result.pages.flat().map((item) => item.str)).toContain("Short"); }); - it.each([false, true])("keeps Gengar ordering for %s stylesheet mode", async (semantic) => { - const data = gengarFixture({ mode: semantic ? "semantic" : "legacy", custom: semantic, columns: 1 }); - const runtime = resolveResumeRuntime({ data, template: "gengar", mode: semantic ? "semantic" : "legacy" }); + it.each([false, true])("keeps Gengar ordering for custom=%s Skills", async (custom) => { + const data = gengarFixture({ custom, columns: 1 }); + const runtime = resolveResumeRuntime({ data, template: "gengar" }); const item = required(getSkillItem(runtime)); expect(item.children.map((node) => node.kind)).toEqual(["item-header", "level", "field", "field"]); const result = await renderGengar(data); @@ -204,7 +195,7 @@ describe("Gengar skill rating placement (#2611)", () => { it("keeps long keywords and mixed-height ratings across overflow pages", async () => { const data = gengarFixture({ count: 12, columns: 2, overflow: true, keywords: ["Long keyword"] }); - const runtime = resolveResumeRuntime({ data, template: "gengar", mode: "semantic" }); + const runtime = resolveResumeRuntime({ data, template: "gengar" }); expect(required(getSkillItem(runtime)).children.map((node) => node.kind)).toEqual([ "item-header", "level", @@ -224,7 +215,7 @@ describe("Gengar skill rating placement (#2611)", () => { it("does not change Onyx semantic ordering", () => { const data = gengarFixture(); - const runtime = resolveResumeRuntime({ data, template: "onyx", mode: "legacy" }); + const runtime = resolveResumeRuntime({ data, template: "onyx" }); const item = required(getSkillItem(runtime)); expect(item.children.map((node) => node.kind)).toEqual(["item-header", "field", "field", "level"]); }); diff --git a/packages/pdf/src/templates/shared/context.tsx b/packages/pdf/src/templates/shared/context.tsx index 82378118a..71105391a 100644 --- a/packages/pdf/src/templates/shared/context.tsx +++ b/packages/pdf/src/templates/shared/context.tsx @@ -1,6 +1,4 @@ -import type { StyleSlot } from "@reactive-resume/schema/resume/data"; import type { ReactNode } from "react"; -import type { SectionStyleRuleContext } from "./style-rules"; import type { StyleInput, TemplatePlacement } from "./styles"; import type { SectionTimelineStyleSlots, @@ -13,9 +11,6 @@ import type { TemplateStyleSlots, } from "./types"; import { createContext, use, useMemo } from "react"; -import { useRender } from "../../context"; -import { useSemanticRenderMode } from "../../semantic/context"; -import { resolveStyleRuleSlot } from "./style-rules"; type TemplateContextValue = { styles: TemplateStyleSlots; @@ -37,14 +32,8 @@ type TemplatePlacementProviderProps = { children: ReactNode; }; -type SectionStyleProviderProps = { - context: SectionStyleRuleContext; - children: ReactNode; -}; - const TemplateContext = createContext(null); const TemplatePlacementContext = createContext("main"); -const SectionStyleContext = createContext(null); const resolveStyleSlot = (slot: TemplateStyleSlot | undefined, context: TemplateStyleContextValue): StyleInput => { if (!slot) return undefined; @@ -91,10 +80,6 @@ export const TemplatePlacementProvider = ({ placement, children }: TemplatePlace return {children}; }; -export const SectionStyleProvider = ({ context, children }: SectionStyleProviderProps) => { - return {children}; -}; - const useTemplateContext = () => { const context = use(TemplateContext); @@ -127,16 +112,6 @@ export const useTemplateStyle = (slot: keyof TemplateStyleSlots): StyleInput => return resolveStyleSlot(styles[slot] as TemplateStyleSlot | undefined, context); }; -export const useSectionStyleRule = (slot: StyleSlot): StyleInput => { - const data = useRender(); - const context = use(SectionStyleContext); - const mode = useSemanticRenderMode(); - - if (!context || mode === "semantic") return undefined; - - return resolveStyleRuleSlot(data, { ...context, slot }); -}; - export const useTemplateFeatureStyle = ( feature: keyof TemplateFeatureStyleSlots, slot: keyof SectionTimelineStyleSlots, diff --git a/packages/pdf/src/templates/shared/date-layout.test.tsx b/packages/pdf/src/templates/shared/date-layout.test.tsx index c9174d16e..6c2e15bf4 100644 --- a/packages/pdf/src/templates/shared/date-layout.test.tsx +++ b/packages/pdf/src/templates/shared/date-layout.test.tsx @@ -612,7 +612,7 @@ describe("date layout characterization (#3155, #2841)", () => { data.metadata.layout.pages = [{ fullWidth: true, main: ["skills"], sidebar: [] }]; for (const type of ["hidden", "circle", "square", "rectangle", "rectangle-full", "progress-bar", "icon"] as const) { data.metadata.design.level = { type, icon: "star" }; - const runtime = resolveResumeRuntime({ data, template: "chikorita", mode: "legacy" }); + const runtime = resolveResumeRuntime({ data, template: "chikorita" }); const level = flatten(runtime.sourceTree).find((node) => node.kind === "level"); if (type === "hidden") expect(level).toBeUndefined(); else expect(level?.children.every((node) => node.attributes.type === type)).toBe(true); diff --git a/packages/pdf/src/templates/shared/level-display.tsx b/packages/pdf/src/templates/shared/level-display.tsx index 19848dfa4..981f41092 100644 --- a/packages/pdf/src/templates/shared/level-display.tsx +++ b/packages/pdf/src/templates/shared/level-display.tsx @@ -11,7 +11,7 @@ import { useSemanticNodeVisible, } from "../../semantic/context"; import { semanticNodeKeys } from "../../semantic/node-keys"; -import { useSectionStyleRule, useTemplateIconSlot, useTemplateStyle } from "./context"; +import { useTemplateIconSlot, useTemplateStyle } from "./context"; import { resolveStyleFontSize } from "./icon-size"; import { getTemplateMetrics } from "./metrics"; import { Icon } from "./primitives"; @@ -37,12 +37,9 @@ export const LevelDisplay = ({ level }: LevelDisplayProps) => { const levelItemStyle = useTemplateStyle("levelItem"); const levelItemActiveStyle = useTemplateStyle("levelItemActive"); const levelItemInactiveStyle = useTemplateStyle("levelItemInactive"); - const iconRuleStyle = useSectionStyleRule("icon"); - const levelRuleStyle = useSectionStyleRule("level"); const { decorationSize, levelIconExplicitSize } = resolveLevelDisplaySizes({ bodyFontSize: data.metadata.typography.body.fontSize, - iconFontSize: resolveStyleFontSize(iconRuleStyle), - levelFontSize: resolveStyleFontSize(levelRuleStyle, resolved.style), + levelFontSize: resolveStyleFontSize(resolved.style), }); const color = typeof iconProps.color === "string" ? iconProps.color : "#000000"; @@ -66,7 +63,6 @@ export const LevelDisplay = ({ level }: LevelDisplayProps) => { style={composeStyles( { flexDirection: "row", alignItems: "center", marginTop: 2, columnGap: gap }, levelContainerStyle, - levelRuleStyle, resolved.style, )} > diff --git a/packages/pdf/src/templates/shared/level-gap.test.tsx b/packages/pdf/src/templates/shared/level-gap.test.tsx index 958130141..4159bbbd6 100644 --- a/packages/pdf/src/templates/shared/level-gap.test.tsx +++ b/packages/pdf/src/templates/shared/level-gap.test.tsx @@ -11,7 +11,7 @@ import { rasterizePdf } from "../../semantic/test/rasterize-pdf"; const pdfRasterScale = 1.5; const circleDiameterPt = 8; -async function circlePositions(declaration = "", mode: "semantic" | "legacy" = "semantic") { +async function circlePositions(declaration = "") { const data = structuredClone(defaultResumeData); data.metadata.typography.body.fontFamily = "Helvetica"; data.metadata.typography.heading.fontFamily = "Helvetica"; @@ -19,7 +19,7 @@ async function circlePositions(declaration = "", mode: "semantic" | "legacy" = " data.metadata.design.colors.primary = "rgba(255, 0, 0, 1)"; data.metadata.layout.pages = [{ fullWidth: true, main: ["skills"], sidebar: [] }]; data.metadata.stylesheet = { - mode, + mode: "semantic", source: { languageVersion: 1, text: `@version 1; section[type="skills"] level { ${declaration} }` }, }; data.sections.skills.items = [ @@ -34,7 +34,7 @@ async function circlePositions(declaration = "", mode: "semantic" | "legacy" = " keywords: [], }, ]; - const runtime = resolveResumeRuntime({ data, template: "onyx", mode }); + const runtime = resolveResumeRuntime({ data, template: "onyx" }); const bytes = await act(() => renderToBuffer()); const [page] = await rasterizePdf(new Uint8Array(bytes)); if (!page) throw new Error("Missing PDF page"); @@ -67,9 +67,6 @@ async function circlePositions(declaration = "", mode: "semantic" | "legacy" = " } describe("semantic level gaps (#3040)", () => { - it("preserves default circle geometry in legacy and semantic modes", async () => { - expect(await circlePositions()).toEqual(await circlePositions("", "legacy")); - }); it.each([ ["gap: 0;", 0], ["gap: 4pt;", 4], diff --git a/packages/pdf/src/templates/shared/list-pagination.test.tsx b/packages/pdf/src/templates/shared/list-pagination.test.tsx index 09067dd86..b618381e6 100644 --- a/packages/pdf/src/templates/shared/list-pagination.test.tsx +++ b/packages/pdf/src/templates/shared/list-pagination.test.tsx @@ -35,7 +35,7 @@ async function listPages( text: `@version 1; page { size: 300pt 300pt; } rich-text { margin-top: ${margin}pt; } ${css}`, }, }; - const runtime = resolveResumeRuntime({ data, template: "onyx", mode: "semantic" }); + const runtime = resolveResumeRuntime({ data, template: "onyx" }); expect(runtime.diagnostics).toEqual([]); const bytes = await act(() => renderToBuffer()); const task = getDocument({ data: new Uint8Array(bytes), useSystemFonts: true }); diff --git a/packages/pdf/src/templates/shared/ordered-marker.test.tsx b/packages/pdf/src/templates/shared/ordered-marker.test.tsx index c2d5a9976..d1e54ad5a 100644 --- a/packages/pdf/src/templates/shared/ordered-marker.test.tsx +++ b/packages/pdf/src/templates/shared/ordered-marker.test.tsx @@ -45,7 +45,7 @@ async function renderList({ // Distinct body weight keeps marker and content separate in PDF.js text runs. description: `${nested ? "
  • Outer" : ""}
      ${Array.from({ length: count }, (_, index) => `
    1. ITEM${column}_${String(index + 1).padStart(3, "0")}
    2. `).join("")}
    ${nested ? "
" : ""}`, })); - expect(resolveResumeRuntime({ data, template: "rhyhorn", mode: "semantic" }).diagnostics).toEqual([]); + expect(resolveResumeRuntime({ data, template: "rhyhorn" }).diagnostics).toEqual([]); const bytes = await act(() => renderToBuffer()); const loading = getDocument({ data: new Uint8Array(bytes), useSystemFonts: true }); try { diff --git a/packages/pdf/src/templates/shared/page-margins.test.tsx b/packages/pdf/src/templates/shared/page-margins.test.tsx index 67c15f0bf..8eee1e978 100644 --- a/packages/pdf/src/templates/shared/page-margins.test.tsx +++ b/packages/pdf/src/templates/shared/page-margins.test.tsx @@ -13,14 +13,13 @@ const renderOverflow = async ( template: Template, placement: "main" | "sidebar", locale = "en-US", - mode: "semantic" | "legacy" = "semantic", explicitPage?: { fullWidth: boolean }, stylesheet = "@version 1;", fullWidth = false, ) => { const data = structuredClone(defaultResumeData); data.basics.name = "Margin Audit"; - data.metadata.stylesheet = { mode, source: { languageVersion: 1, text: stylesheet } }; + data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: stylesheet } }; data.metadata.typography.body.fontFamily = "Helvetica"; data.metadata.typography.heading.fontFamily = "Helvetica"; data.metadata.page.marginY = 48; @@ -90,7 +89,6 @@ describe("physical page margins (#3337, #3175)", () => { "glalie", "main", "en-US", - "semantic", undefined, `@version 1; template-part[name="sidebar-background"] { background-color: ${color}; }`, ); @@ -102,7 +100,7 @@ describe("physical page margins (#3337, #3175)", () => { expect(backgroundAt(overflow, 3, overflow.height - 4)).toEqual(inside); }); it("preserves the existing Glalie sidebar background on full-width overflow", async () => { - const { rasters } = await renderOverflow("glalie", "main", "en-US", "semantic", undefined, "@version 1;", true); + const { rasters } = await renderOverflow("glalie", "main", "en-US", undefined, "@version 1;", true); const overflow = rasters[1]; if (!overflow) throw new Error("Missing overflow raster"); expect(backgroundAt(overflow, 3, 100)).toEqual([242, 177, 177]); @@ -174,20 +172,11 @@ describe("physical page margins (#3337, #3175)", () => { expect(line.transform[5]).toBeGreaterThanOrEqual(47); } }); - it.each(templates)("keeps legacy overflow within margins (%s)", async (template) => { - const { pages } = await renderOverflow(template, "sidebar", "en-US", "legacy"); - expect(pages.length).toBeGreaterThan(1); - for (const page of pages) - for (const line of page.lines) { - expect(page.height - line.transform[5] - line.height).toBeGreaterThanOrEqual(45.8); - expect(line.transform[5]).toBeGreaterThanOrEqual(47); - } - }); for (const fullWidth of [false, true]) { it.each(templates)( `starts explicit headerless pages at the margin (fullWidth: ${fullWidth}, %s)`, async (template) => { - const { pages } = await renderOverflow(template, "main", "en-US", "semantic", { fullWidth }); + const { pages } = await renderOverflow(template, "main", "en-US", { fullWidth }); expect(pages).toHaveLength(2); const page = pages[1]; if (!page) throw new Error("Missing explicit second page"); diff --git a/packages/pdf/src/templates/shared/picture-border.test.tsx b/packages/pdf/src/templates/shared/picture-border.test.tsx index ee12272ad..bd9df9442 100644 --- a/packages/pdf/src/templates/shared/picture-border.test.tsx +++ b/packages/pdf/src/templates/shared/picture-border.test.tsx @@ -16,7 +16,6 @@ context.fillRect(0, 0, 100, 100); async function picturePixels( template: "onyx" | "ditto" | "glalie", borderWidth: number, - mode: "semantic" | "legacy" = "semantic", stylesheet = "@version 1;", shadowWidth = 0, url = source.toDataURL("image/png"), @@ -26,7 +25,7 @@ async function picturePixels( data.basics.name = "Picture"; data.metadata.typography.body.fontFamily = "Helvetica"; data.metadata.typography.heading.fontFamily = "Helvetica"; - data.metadata.stylesheet = { mode, source: { languageVersion: 1, text: stylesheet } }; + data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: stylesheet } }; data.metadata.layout.pages = [{ fullWidth: false, main: [], sidebar: [] }]; Object.assign(data.picture, { url, @@ -38,7 +37,7 @@ async function picturePixels( shadowWidth, shadowColor: "rgba(0, 0, 255, 1)", }); - let runtime = resolveResumeRuntime({ data, template, mode }); + let runtime = resolveResumeRuntime({ data, template }); if (styleOverride) { const entry = Object.entries(runtime.presentation).find(([key]) => key.endsWith("/picture")); if (!entry) throw new Error("Missing picture presentation"); @@ -115,13 +114,12 @@ async function picturePixels( describe("picture border visibility (#3017)", () => { it("keeps the shadow centered on the outer border box when borders and padding change", async () => { - const plain = await picturePixels("onyx", 0, "semantic", "@version 1;", 10); - const bordered = await picturePixels("onyx", 10, "semantic", "@version 1; picture { padding: 5pt; }", 10); + const plain = await picturePixels("onyx", 0, "@version 1;", 10); + const bordered = await picturePixels("onyx", 10, "@version 1; picture { padding: 5pt; }", 10); expect(bordered.shadowBounds).toEqual(plain.shadowBounds); const asymmetric = await picturePixels( "onyx", 0, - "semantic", "@version 1; picture { border-top: 12pt solid #ff00ff; border-right: 3pt solid #ff00ff; border-bottom: 8pt solid #ff00ff; border-left: 5pt solid #ff00ff; padding: 3pt 4pt 5pt 6pt; }", 10, ); @@ -130,9 +128,9 @@ describe("picture border visibility (#3017)", () => { it("preserves percentage dimensions, padding, rounded borders, rotation and opacity", async () => { const css = "@version 1; picture { width: 40%; height: 100pt; padding: 1%; border-radius: 25%; transform: rotate(15deg); }"; - const opaque = await picturePixels("onyx", 10, "semantic", css); - const plain = await picturePixels("onyx", 10, "semantic", css, 0, undefined, { opacity: 0.5 }); - const shadow = await picturePixels("onyx", 10, "semantic", css, 10, undefined, { opacity: 0.5 }); + const opaque = await picturePixels("onyx", 10, css); + const plain = await picturePixels("onyx", 10, css, 0, undefined, { opacity: 0.5 }); + const shadow = await picturePixels("onyx", 10, css, 10, undefined, { opacity: 0.5 }); expect(opaque.borderPixels).toBeGreaterThan(1000); expect(plain.imagePixels).toBeGreaterThan(1000); expect(shadow).toEqual(plain); // Unresolved percentage dimensions omit the shadow. @@ -141,15 +139,15 @@ describe("picture border visibility (#3017)", () => { }); // Forme 0.25 takes percentages only for box sizes, so percentage padding is left out; this passes once it isn't. it.fails.each([0, 10])("keeps percentage picture padding outside the border inset (%s)", async (shadowWidth) => { - const plain = await picturePixels("onyx", 10, "semantic", "@version 1;", shadowWidth); - const padded = await picturePixels("onyx", 10, "semantic", "@version 1; picture { padding: 1%; }", shadowWidth); + const plain = await picturePixels("onyx", 10, "@version 1;", shadowWidth); + const padded = await picturePixels("onyx", 10, "@version 1; picture { padding: 1%; }", shadowWidth); expect(padded.borderPixels).toBe(plain.borderPixels); expect(padded.imagePixels).toBeLessThan(plain.imagePixels); }); it.each([0, 10])("preserves border and authored padding with shadow width %s", async (shadowWidth) => { - const plain = await picturePixels("onyx", 10, "semantic", "@version 1;", shadowWidth); - const zero = await picturePixels("onyx", 10, "semantic", "@version 1; picture { padding: 0; }", shadowWidth); - const padded = await picturePixels("onyx", 10, "semantic", "@version 1; picture { padding: 5pt; }", shadowWidth); + const plain = await picturePixels("onyx", 10, "@version 1;", shadowWidth); + const zero = await picturePixels("onyx", 10, "@version 1; picture { padding: 0; }", shadowWidth); + const padded = await picturePixels("onyx", 10, "@version 1; picture { padding: 5pt; }", shadowWidth); expect(zero).toEqual(plain); expect(padded.borderPixels).toBe(plain.borderPixels); expect(padded.imagePixels).toBeLessThan(plain.imagePixels); @@ -167,23 +165,14 @@ describe("picture border visibility (#3017)", () => { }); it("honors semantic border width overrides", async () => { const metadataBorder = await picturePixels("onyx", 10); - const overridden = await picturePixels( - "onyx", - 0, - "semantic", - "@version 1; picture { border: 10pt solid #ff00ff; }", - ); + const overridden = await picturePixels("onyx", 0, "@version 1; picture { border: 10pt solid #ff00ff; }"); expect(overridden).toEqual(metadataBorder); }); - it("keeps legacy picture borders visible", async () => { - const bordered = await picturePixels("onyx", 10, "legacy"); - expect(bordered.borderPixels).toBeGreaterThan(1000); - }); it.each(["onyx", "ditto", "glalie"] as const)( "draws a soft centered shadow without moving the photo (%s)", async (template) => { const plain = await picturePixels(template, 0); - const shadow = await picturePixels(template, 0, "semantic", "@version 1;", 10); + const shadow = await picturePixels(template, 0, "@version 1;", 10); expect(plain.shadowPixels).toBe(0); expect(shadow.shadowPixels).toBeGreaterThan(100); expect(shadow.bounds).toEqual(plain.bounds); @@ -194,7 +183,6 @@ describe("picture border visibility (#3017)", () => { const shadow = await picturePixels( "onyx", 0, - "semantic", "@version 1; picture { -resume-shadow-width: 10pt; -resume-shadow-color: rgba(0, 0, 255, 0.5); border-radius: 50pt; }", ); expect(shadow.shadowPixels).toBeGreaterThan(100); @@ -206,25 +194,25 @@ describe("picture border visibility (#3017)", () => { context.fillStyle = "#00aa00"; context.fillRect(0, 0, 100, 100); context.clearRect(30, 30, 40, 40); - const shadow = await picturePixels("onyx", 0, "semantic", "@version 1;", 10, transparent.toDataURL("image/png")); + const shadow = await picturePixels("onyx", 0, "@version 1;", 10, transparent.toDataURL("image/png")); expect(shadow.shadowPixels).toBeGreaterThan(100); expect(shadow.center).toEqual([255, 255, 255]); }); it("preserves rotated photo geometry and opacity", async () => { const css = "@version 1; picture { transform: rotate(25deg); }"; - const plain = await picturePixels("onyx", 0, "semantic", css, 0, undefined, { opacity: 0.5 }); - const shadow = await picturePixels("onyx", 0, "semantic", css, 10, undefined, { opacity: 0.5 }); + const plain = await picturePixels("onyx", 0, css, 0, undefined, { opacity: 0.5 }); + const shadow = await picturePixels("onyx", 0, css, 10, undefined, { opacity: 0.5 }); expect(shadow.shadowPixels).toBeGreaterThan(100); expect(shadow.bounds).toEqual(plain.bounds); expect(shadow.center).toEqual(plain.center); }); it("keeps the outer shadow visible when the picture clips its contents", async () => { - const shadow = await picturePixels("onyx", 0, "semantic", "@version 1;", 10, undefined, { overflow: "hidden" }); + const shadow = await picturePixels("onyx", 0, "@version 1;", 10, undefined, { overflow: "hidden" }); expect(shadow.shadowPixels).toBeGreaterThan(100); }); it("matches percentage and absolute picture corner radii", async () => { - const absolute = await picturePixels("onyx", 0, "semantic", "@version 1; picture { border-radius: 50pt; }", 10); - const percent = await picturePixels("onyx", 0, "semantic", "@version 1; picture { border-radius: 50%; }", 10); + const absolute = await picturePixels("onyx", 0, "@version 1; picture { border-radius: 50pt; }", 10); + const percent = await picturePixels("onyx", 0, "@version 1; picture { border-radius: 50%; }", 10); expect(percent).toEqual(absolute); }); }); diff --git a/packages/pdf/src/templates/shared/primitives.tsx b/packages/pdf/src/templates/shared/primitives.tsx index 3de1676ec..204f75305 100644 --- a/packages/pdf/src/templates/shared/primitives.tsx +++ b/packages/pdf/src/templates/shared/primitives.tsx @@ -17,7 +17,7 @@ import { } from "../../semantic/context"; import { semanticNodeKeys } from "../../semantic/node-keys"; import { Link as PdfLink, Text as PdfText } from "../../text"; -import { useSectionStyleRule, useTemplateIconSlot, useTemplatePageNodeKey, useTemplateStyle } from "./context"; +import { useTemplateIconSlot, useTemplatePageNodeKey, useTemplateStyle } from "./context"; import { resolveIconSize } from "./icon-size"; import { getPictureShadow } from "./picture-shadow"; import { safeTextStyle } from "./safe-text-style"; @@ -135,7 +135,6 @@ export const Text = ({ ...props }: ComponentProps & SemanticProps) => { const textStyle = useTemplateStyle("text"); - const textRuleStyle = useSectionStyleRule("text"); const resolvedNodeKey = usePrimitiveNodeKey({ nodeKey, semanticField, @@ -150,7 +149,7 @@ export const Text = ({ ); }; @@ -164,7 +163,6 @@ export const Heading = ({ ...props }: ComponentProps & SemanticProps) => { const headingStyle = useTemplateStyle("heading"); - const headingRuleStyle = useSectionStyleRule("heading"); const resolvedNodeKey = usePrimitiveNodeKey({ nodeKey, semanticField, @@ -180,7 +178,7 @@ export const Heading = ({ ); }; @@ -196,7 +194,6 @@ export const Link = ({ }: ComponentProps & SemanticLinkProps) => { const { metadata } = useRender(); const linkStyle = useTemplateStyle("link"); - const linkRuleStyle = useSectionStyleRule("link"); const parentKey = useSemanticNodeKey(); const resolvedNodeKey = nodeKey ?? @@ -211,12 +208,7 @@ export const Link = ({ {...props} {...resolvedPdfTextProps(resolved)} style={composeStyles( - composeLinkStyles( - { hideUnderline: metadata.page.hideLinkUnderline }, - linkStyle, - linkRuleStyle, - asStyleInput(style), - ), + composeLinkStyles({ hideUnderline: metadata.page.hideLinkUnderline }, linkStyle, asStyleInput(style)), resolved.style, safeTextStyle, )} @@ -234,7 +226,6 @@ export const Small = ({ }: ComponentProps & SemanticProps) => { const textStyle = useTemplateStyle("text"); const smallStyle = useTemplateStyle("small"); - const secondaryTextRuleStyle = useSectionStyleRule("secondaryText"); const resolvedNodeKey = usePrimitiveNodeKey({ nodeKey, semanticField, @@ -249,14 +240,7 @@ export const Small = ({ ); }; @@ -271,7 +255,6 @@ export const Bold = ({ }: ComponentProps & SemanticProps) => { const textStyle = useTemplateStyle("text"); const boldStyle = useTemplateStyle("bold"); - const textRuleStyle = useSectionStyleRule("text"); const resolvedNodeKey = usePrimitiveNodeKey({ nodeKey, semanticField, @@ -286,7 +269,7 @@ export const Bold = ({ ); }; @@ -298,8 +281,7 @@ export const Icon = ({ ...props }: ComponentProps & { nodeKey?: string | undefined }) => { const { style: iconStyle, size: templateSize, ...iconProps } = useTemplateIconSlot("icon"); - const iconRuleStyle = useSectionStyleRule("icon"); - const composedStyle = composeStyles(asStyleInput(iconStyle), iconRuleStyle, asStyleInput(style)); + const composedStyle = composeStyles(asStyleInput(iconStyle), asStyleInput(style)); const templateIconSize = typeof templateSize === "number" || typeof templateSize === "string" ? templateSize : undefined; const parentKey = useSemanticNodeKey(); @@ -312,7 +294,7 @@ export const Icon = ({ const resolvedSize = resolveIconSize({ size: sizeProp, - styles: [iconRuleStyle, asStyleInput(style), resolved.style], + styles: [asStyleInput(style), resolved.style], }) ?? templateIconSize; if (iconProps.display === "none" || !visible) return null; diff --git a/packages/pdf/src/templates/shared/rich-text.tsx b/packages/pdf/src/templates/shared/rich-text.tsx index ab95f52dd..fc3f93155 100644 --- a/packages/pdf/src/templates/shared/rich-text.tsx +++ b/packages/pdf/src/templates/shared/rich-text.tsx @@ -14,7 +14,7 @@ import { import { semanticNodeKeys } from "../../semantic/node-keys"; import { getRichTextSemanticNodeKey } from "../../semantic/rich-text-keys"; import { Html, Link as PdfLink, Text as PdfText } from "../../text"; -import { useSectionStyleRule, useTemplateStyle } from "./context"; +import { useTemplateStyle } from "./context"; import { normalizeRichTextHtml, projectNormalizedRichTextHtml, @@ -93,19 +93,7 @@ export const RichText = ({ children, semanticField }: RichTextProps) => { const richListItemRowStyle = useTemplateStyle("richListItemRow"); const richListItemMarkerStyle = useTemplateStyle("richListItemMarker"); const richListItemContentStyle = useTemplateStyle("richListItemContent"); - const richParagraphRuleStyle = useSectionStyleRule("richParagraph"); - const richListRuleStyle = useSectionStyleRule("richList"); - const richListItemRowRuleStyle = useSectionStyleRule("richListItemRow"); - const richListItemContentRuleStyle = useSectionStyleRule("richListItemContent"); - const richLinkRuleStyle = useSectionStyleRule("richLink"); - const richBoldRuleStyle = useSectionStyleRule("richBold"); - const richMarkRuleStyle = useSectionStyleRule("richMark"); - const bodyLineHeight = resolveRichTextBodyLineHeight( - richParagraphStyle, - richParagraphRuleStyle, - richListItemContentStyle, - richListItemContentRuleStyle, - ); + const bodyLineHeight = resolveRichTextBodyLineHeight(richParagraphStyle, richListItemContentStyle); const proseSpacing = createRichTextProseSpacing(bodyLineHeight); const normalizedHtml = normalizeRichTextHtml(children, { @@ -317,7 +305,6 @@ export const RichText = ({ children, semanticField }: RichTextProps) => { {...resolvedPdfTextProps(contentResolved)} style={composeStyles( richListItemContentStyle, - richListItemContentRuleStyle, contentItemStyles, contentResolved.style, safeTextStyle, @@ -333,7 +320,6 @@ export const RichText = ({ children, semanticField }: RichTextProps) => { {...resolvedPdfFlowProps(contentResolved)} style={composeStyles( richListItemContentStyle, - richListItemContentRuleStyle, contentItemStyles, contentResolved.style, richListItemContentStackStyle, @@ -365,7 +351,6 @@ export const RichText = ({ children, semanticField }: RichTextProps) => { {...resolvedPdfFlowProps(itemResolved)} style={composeStyles( richListItemRowStyle, - richListItemRowRuleStyle, itemStyles, getRichTextEdgeTrimStyle(element), itemResolved.style, @@ -385,11 +370,6 @@ export const RichText = ({ children, semanticField }: RichTextProps) => { hideLinkUnderline: metadata.page.hideLinkUnderline, linkStyle, richParagraphStyle, - richParagraphRuleStyle, - richListRuleStyle, - richBoldRuleStyle, - richLinkRuleStyle, - richMarkRuleStyle, proseSpacing, })} > diff --git a/packages/pdf/src/templates/shared/section-header-alignment.test.tsx b/packages/pdf/src/templates/shared/section-header-alignment.test.tsx index 13982a1a7..68239f7d6 100644 --- a/packages/pdf/src/templates/shared/section-header-alignment.test.tsx +++ b/packages/pdf/src/templates/shared/section-header-alignment.test.tsx @@ -75,15 +75,12 @@ const expectTrailingAlignment = (items: TextItem[], rtl = false) => { }; describe("optional experience and education header fields (#3338)", () => { - it.each(["legacy", "semantic"] as const)( - "keeps dates at the trailing edge with empty leading fields in %s mode", - async (mode) => { - const data = fixture(); - data.metadata.stylesheet = { mode, source: { languageVersion: 1, text: "@version 1;" } }; - const items = await renderText(data); - expectTrailingAlignment(items); - }, - ); + it("keeps dates at the trailing edge with empty leading fields", async () => { + const data = fixture(); + data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: "@version 1;" } }; + const items = await renderText(data); + expectTrailingAlignment(items); + }); it("preserves RTL row alignment when leading fields are empty", async () => { const data = fixture(); diff --git a/packages/pdf/src/templates/shared/sections.test.ts b/packages/pdf/src/templates/shared/sections.test.ts index ee30b2781..3262476dc 100644 --- a/packages/pdf/src/templates/shared/sections.test.ts +++ b/packages/pdf/src/templates/shared/sections.test.ts @@ -32,12 +32,10 @@ describe("SectionShell", () => { expect(getSectionHeadingTextStyle({ paddingLeft: 6 })).toEqual([{ paddingLeft: 1 }]); }); - it("keeps section and heading style rules when section heading icons are hidden", () => { - expect(source).toContain( - "const resolvedSectionStyle = composeStyles(sectionStyle, sectionRuleStyle, resolved.style)", - ); + it("keeps section and heading styles when section heading icons are hidden", () => { + expect(source).toContain("const resolvedSectionStyle = composeStyles(sectionStyle, resolved.style)"); expect(source).toContain(""); - expect(source).toContain(""); + expect(source).toContain(""); }); it("wires the section heading container style slot into the icon row", () => { @@ -51,7 +49,7 @@ describe("SectionShell", () => { ); expect(headingContainerBlock?.groups?.body).toContain('alignItems: "flex-start"'); - expect(source).toMatch(/getSectionHeadingTextStyle\(\s*sectionHeadingStyle,\s*sectionHeadingRuleStyle(?:,|\))/); + expect(source).toMatch(/getSectionHeadingTextStyle\(\s*sectionHeadingStyle(?:,|\))/); expect(source).toContain("width: _width"); expect(source).not.toContain('width: "auto"'); }); diff --git a/packages/pdf/src/templates/shared/sections.tsx b/packages/pdf/src/templates/shared/sections.tsx index 2ea394345..9e5ee1c27 100644 --- a/packages/pdf/src/templates/shared/sections.tsx +++ b/packages/pdf/src/templates/shared/sections.tsx @@ -46,9 +46,7 @@ import { ITEM_HEADER_ROW_PART_KEYS } from "../../semantic/shared-parts"; import { getSectionItemRows, getSectionItemsLayout, shouldUseSectionTimeline } from "./columns"; import { getWebsiteDisplayText } from "./contact"; import { - SectionStyleProvider, TemplatePlacementProvider, - useSectionStyleRule, useTemplateFeature, useTemplateFeatureStyle, useTemplatePageNodeKey, @@ -74,7 +72,6 @@ import { RichText } from "./rich-text"; import { createRtlStyleHelpers } from "./rtl"; import { getInlineItemWebsiteUrl, shouldRenderSeparateItemWebsite } from "./section-links"; import { hasSplitRowText } from "./split-row"; -import { getSectionStyleRuleContext } from "./style-rules"; import { composeStyles, mergeStyles } from "./styles"; type SectionItemsContextValue = { @@ -321,10 +318,8 @@ const SectionShell = ({ sectionId, title, showHeading = true, children }: Sectio const resolved = useResolvedNode(sectionNodeKey); const visible = useSemanticNodeVisible(sectionNodeKey); const sectionStyle = useTemplateStyle("section"); - const sectionRuleStyle = useSectionStyleRule("section"); const sectionHeadingStyle = useTemplateStyle("sectionHeading"); const sectionHeadingContainerStyle = useTemplateStyle("sectionHeadingContainer"); - const sectionHeadingRuleStyle = useSectionStyleRule("heading"); const sectionTitle = getResumeSectionTitle(data, sectionId, title); const sectionHeadingEnabled = (() => { if (sectionId === "summary") return data.summary.showHeading !== false; @@ -346,7 +341,7 @@ const SectionShell = ({ sectionId, title, showHeading = true, children }: Sectio if (keepTogether) breakProps.wrap = false; if (startOnNewPage) breakProps.break = true; const flowProps = { ...breakProps, ...resolvedPdfFlowProps(resolved) }; - const resolvedSectionStyle = composeStyles(sectionStyle, sectionRuleStyle, resolved.style); + const resolvedSectionStyle = composeStyles(sectionStyle, resolved.style); if (!visible) return null; if (!showIcon) { @@ -355,7 +350,7 @@ const SectionShell = ({ sectionId, title, showHeading = true, children }: Sectio {showHeading && sectionHeadingEnabled && ( - {sectionTitle} + {sectionTitle} )} {children} @@ -374,7 +369,6 @@ const SectionShell = ({ sectionId, title, showHeading = true, children }: Sectio sectionHeadingStyle, defaultSectionHeadingContainerStyle, sectionHeadingContainerStyle, - sectionHeadingRuleStyle, sectionHeadingResolved.style, )} > @@ -386,7 +380,6 @@ const SectionShell = ({ sectionId, title, showHeading = true, children }: Sectio bindSemanticNode={false} style={getSectionHeadingTextStyle( sectionHeadingStyle, - sectionHeadingRuleStyle, sectionHeadingResolved.style?.color === undefined ? undefined : { color: sectionHeadingResolved.style.color }, @@ -506,7 +499,6 @@ const SectionItem = ({ itemId, children, style }: SectionItemProps) => { const visible = useSemanticNodeVisible(itemNodeKey); const { itemStyle: sectionItemStyle, useTimeline } = useSectionItemsContext(); const itemStyle = useTemplateStyle("item"); - const itemRuleStyle = useSectionStyleRule("item"); const timelineItemStyle = useTemplateFeatureStyle("sectionTimeline", "item"); const timelineMarkerStyle = useTemplateFeatureStyle("sectionTimeline", "marker"); const timelineDotStyle = useTemplateFeatureStyle("sectionTimeline", "dot"); @@ -518,7 +510,7 @@ const SectionItem = ({ itemId, children, style }: SectionItemProps) => { if (!useTimeline) { return ( -
+
{children}
@@ -542,7 +534,7 @@ const SectionItem = ({ itemId, children, style }: SectionItemProps) => {
{children}
@@ -1597,9 +1589,7 @@ export const Section = ({ section, placement, showHeading = true }: SectionProps return ( - - {render ? render() : } - + {render ? render() : } ); }; diff --git a/packages/pdf/src/templates/shared/skill-keyword-presentation.test.tsx b/packages/pdf/src/templates/shared/skill-keyword-presentation.test.tsx index a69bd73ac..261813327 100644 --- a/packages/pdf/src/templates/shared/skill-keyword-presentation.test.tsx +++ b/packages/pdf/src/templates/shared/skill-keyword-presentation.test.tsx @@ -110,7 +110,7 @@ describe("skill keyword presentation", () => { text: '@version 1; section[type="skills"] field[name="keywords"] { font-size: 18pt; } section[type="skills"] item[id="css-hidden"] { display: none; }', }, }; - const runtime = resolveResumeRuntime({ data, template: "leafish", mode: "semantic" }); + const runtime = resolveResumeRuntime({ data, template: "leafish" }); expect(runtime.diagnostics).toEqual([]); const { text, pages } = await renderKeywords(data); expect(text).toContain("Engineering"); diff --git a/packages/pdf/src/templates/shared/skill-level-alignment.test.tsx b/packages/pdf/src/templates/shared/skill-level-alignment.test.tsx index 317513baf..aece43f17 100644 --- a/packages/pdf/src/templates/shared/skill-level-alignment.test.tsx +++ b/packages/pdf/src/templates/shared/skill-level-alignment.test.tsx @@ -11,7 +11,6 @@ import { rasterizePdf } from "../../semantic/test/rasterize-pdf"; type FixtureOptions = { columns: number; count: number; - mode?: "semantic" | "legacy"; configure?: (data: ResumeData) => void; }; @@ -19,14 +18,14 @@ function setCss(data: ResumeData, css: string) { data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: `@version 1; ${css}` } }; } -async function renderRatings({ columns, count, mode = "semantic", configure }: FixtureOptions) { +async function renderRatings({ columns, count, configure }: FixtureOptions) { const data = structuredClone(defaultResumeData); data.metadata.typography.body.fontFamily = "Helvetica"; data.metadata.typography.heading.fontFamily = "Helvetica"; data.metadata.page.hideIcons = true; data.metadata.design.colors.primary = "rgba(255, 0, 0, 1)"; data.metadata.layout.pages = [{ fullWidth: true, main: ["skills"], sidebar: [] }]; - data.metadata.stylesheet = { mode, source: { languageVersion: 1, text: "@version 1;" } }; + data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: "@version 1;" } }; data.sections.skills.columns = columns; data.sections.skills.items = Array.from({ length: count }, (_, index) => ({ id: `skill-${index}`, @@ -39,7 +38,7 @@ async function renderRatings({ columns, count, mode = "semantic", configure }: F keywords: index === 1 ? Array.from({ length: 12 }, (_, word) => `Keyword${word}`) : ["Short"], })); configure?.(data); - expect(resolveResumeRuntime({ data, template: "onyx", mode }).diagnostics).toEqual([]); + expect(resolveResumeRuntime({ data, template: "onyx" }).diagnostics).toEqual([]); const bytes = await act(() => renderToBuffer()); const pages = await rasterizePdf(new Uint8Array(bytes)); const loading = getDocument({ data: new Uint8Array(bytes) }); @@ -82,21 +81,18 @@ async function renderRatings({ columns, count, mode = "semantic", configure }: F } describe("skill rating alignment (#3343)", () => { - it.each(["semantic", "legacy"] as const)( - "aligns mixed-height skills and preserves an incomplete row in %s mode", - async (mode) => { - const { - rows: [rows], - text, - } = await renderRatings({ columns: 2, count: 3, mode }); - expect(rows).toHaveLength(2); - if (!rows?.[0] || !rows[1]) throw new Error("Missing rating rows"); - // Ten circles share the first row; the remaining skill has five. - expect(rows.map((row) => row.circles)).toEqual([10, 5]); - expect(text).toContain("Keyword11"); - expect(text).toContain("Skill 2"); - }, - ); + it("aligns mixed-height skills and preserves an incomplete row", async () => { + const { + rows: [rows], + text, + } = await renderRatings({ columns: 2, count: 3 }); + expect(rows).toHaveLength(2); + if (!rows?.[0] || !rows[1]) throw new Error("Missing rating rows"); + // Ten circles share the first row; the remaining skill has five. + expect(rows.map((row) => row.circles)).toEqual([10, 5]); + expect(text).toContain("Keyword11"); + expect(text).toContain("Skill 2"); + }); it("aligns three columns and preserves an incomplete row", async () => { const { rows: [rows], diff --git a/packages/pdf/src/templates/shared/style-rules.test.ts b/packages/pdf/src/templates/shared/style-rules.test.ts index 386aef12b..237332add 100644 --- a/packages/pdf/src/templates/shared/style-rules.test.ts +++ b/packages/pdf/src/templates/shared/style-rules.test.ts @@ -1,7 +1,8 @@ import type { ResumeData } from "@reactive-resume/schema/resume/data"; import { describe, expect, it } from "vitest"; import { defaultResumeData } from "@reactive-resume/schema/resume/default"; -import { getSectionStyleRuleContext, resolveStyleRuleSlot } from "./style-rules"; +import { getSectionStyleRuleContext } from "@reactive-resume/schema/resume/style-rules"; +import { resolveStyleRuleSlot } from "./style-rules"; const createResumeData = (styleRules: ResumeData["metadata"]["styleRules"]): ResumeData => ({ ...defaultResumeData, diff --git a/packages/pdf/src/templates/shared/style-rules.ts b/packages/pdf/src/templates/shared/style-rules.ts index 6d7759171..028d3fa96 100644 --- a/packages/pdf/src/templates/shared/style-rules.ts +++ b/packages/pdf/src/templates/shared/style-rules.ts @@ -1,17 +1,13 @@ import type { ResumeData, StyleIntent, StyleSlot } from "@reactive-resume/schema/resume/data"; import type { SectionStyleRuleContext } from "@reactive-resume/schema/resume/style-rules"; import type { Style } from "../../forme/style-types"; -import { getSectionStyleRuleContext, resolveStyleIntentForSlot } from "@reactive-resume/schema/resume/style-rules"; +import { resolveStyleIntentForSlot } from "@reactive-resume/schema/resume/style-rules"; import { rgbaStringToHex } from "@reactive-resume/utils/color"; -export type { SectionStyleRuleContext }; - export type ResolveStyleRuleSlotOptions = SectionStyleRuleContext & { slot: StyleSlot; }; -export { getSectionStyleRuleContext }; - const spacingProperties = [ "padding", "paddingTop", diff --git a/packages/schema/src/resume/style-rules.test.ts b/packages/schema/src/resume/style-rules.test.ts deleted file mode 100644 index 65df3e083..000000000 --- a/packages/schema/src/resume/style-rules.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { defaultResumeData } from "./default"; -import { resolveStyleRuleFontSize } from "./style-rules"; - -describe("resolveStyleRuleFontSize", () => { - it("returns global icon font sizes without section context", () => { - const data = { - ...defaultResumeData, - metadata: { - ...defaultResumeData.metadata, - styleRules: [ - { - id: "icon-global", - label: "", - enabled: true, - target: { scope: "global" as const }, - slots: { icon: { fontSize: 22 } }, - }, - ], - }, - }; - - expect(resolveStyleRuleFontSize(data, { slot: "icon" })).toBe(22); - }); - - it("does not apply level font sizes to the icon slot", () => { - const data = { - ...defaultResumeData, - metadata: { - ...defaultResumeData.metadata, - styleRules: [ - { - id: "level-global", - label: "", - enabled: true, - target: { scope: "global" as const }, - slots: { level: { fontSize: 18 } }, - }, - ], - }, - }; - - expect(resolveStyleRuleFontSize(data, { slot: "icon" })).toBeUndefined(); - }); -}); diff --git a/packages/schema/src/resume/style-rules.ts b/packages/schema/src/resume/style-rules.ts index 0cdb5c84e..206ff8011 100644 --- a/packages/schema/src/resume/style-rules.ts +++ b/packages/schema/src/resume/style-rules.ts @@ -26,8 +26,6 @@ const builtInSectionTypes = new Set([ "references", ]); -const clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value)); - export const getSectionStyleRuleContext = (data: ResumeData, sectionId: string): SectionStyleRuleContext => { if (sectionId === "summary") return { sectionId, sectionType: "summary" }; if (builtInSectionTypes.has(sectionId as SectionType)) { @@ -62,13 +60,3 @@ export const resolveStyleIntentForSlot = (data: ResumeData, options: ResolveStyl return Object.assign({}, ...bySpecificity.map((rule) => rule.slots[options.slot])); }; - -export const resolveStyleRuleFontSize = ( - data: ResumeData, - options: ResolveStyleRuleSlotOptions, -): number | undefined => { - const fontSize = resolveStyleIntentForSlot(data, options).fontSize; - if (fontSize === undefined) return undefined; - - return clamp(fontSize, 6, 48); -}; diff --git a/tests/e2e/fixtures/db.ts b/tests/e2e/fixtures/db.ts index e0b71ebd6..e04a1d0f9 100644 --- a/tests/e2e/fixtures/db.ts +++ b/tests/e2e/fixtures/db.ts @@ -1,15 +1,6 @@ import type { E2EAccount } from "./data"; -import { readFileSync } from "node:fs"; -import { resolve } from "node:path"; import { Pool } from "pg"; -const legacyParityRules = JSON.parse( - readFileSync( - resolve(process.cwd(), "packages/pdf/src/semantic/__fixtures__/legacy/custom-section-type.json"), - "utf8", - ), -) as unknown[]; - function getDatabaseUrl() { const databaseUrl = process.env.DATABASE_URL; if (!databaseUrl) throw new Error("DATABASE_URL is required for E2E cleanup."); @@ -28,7 +19,7 @@ export async function deleteE2EUser(account: E2EAccount) { } type SemanticStylesheetSeed = { - mode: "legacy" | "semantic"; + mode: "semantic"; source: { languageVersion: number; text: string }; }; @@ -38,7 +29,6 @@ async function _updateSemanticCssFixture( stylesheet?: SemanticStylesheetSeed; portableLayout?: "balanced" | "pagination-stress"; experienceItemId?: string; - legacyStyleRule?: boolean; hidePicture?: boolean; basicsName?: string; }, @@ -116,11 +106,6 @@ async function _updateSemanticCssFixture( }, ]; } - if (update.legacyStyleRule) { - const metadata = data.metadata as Record; - delete metadata.stylesheet; - metadata.styleRules = structuredClone(legacyParityRules); - } if (update.hidePicture) { const picture = data.picture as Record; picture.hidden = true;