From f0a1835fa25c9b0225701804d1bb7d76ad5a27d7 Mon Sep 17 00:00:00 2001 From: Duhan BALCI Date: Sun, 29 Mar 2026 22:35:57 +0300 Subject: [PATCH] refactor & improvements --- CLAUDE.md | 183 +- Cargo.lock | 238 +- ELEMENTS.md | 271 ++ backend/Cargo.lock | 4100 ----------------- core/Cargo.toml | 7 +- core/src/lib.rs | 4 - core/src/template_to_typst.rs | 1367 ------ core/src/wasm_api.rs | 26 - frontend/bun.lock | 217 +- frontend/package.json | 18 +- frontend/playwright.config.ts | 21 + frontend/src/App.vue | 157 +- .../src/components/editor/EditorCanvas.vue | 5 - .../src/components/editor/ElementHandle.vue | 2 +- .../components/editor/InteractionOverlay.vue | 59 +- .../src/components/editor/LayoutRenderer.vue | 2 +- .../src/components/editor/TypstSvgLayer.vue | 35 - .../src/components/panels/PropertiesPanel.vue | 993 +--- .../src/components/panels/SchemaTreeNode.vue | 266 ++ .../src/components/panels/SchemaTreePanel.vue | 51 + .../properties/BarcodeProperties.vue | 152 + .../properties/ContainerProperties.vue | 115 + .../components/properties/ImageProperties.vue | 62 + .../components/properties/LineProperties.vue | 34 + .../properties/PageNumberProperties.vue | 59 + .../properties/PositioningProperties.vue | 43 + .../properties/RepeatingTableProperties.vue | 242 + .../components/properties/SizeProperties.vue | 67 + .../components/properties/TextProperties.vue | 65 + frontend/src/composables/useSnapGuides.ts | 178 + frontend/src/composables/useTypstCompiler.ts | 90 - .../__tests__/mock-data-generator.test.ts | 144 + .../src/core/__tests__/schema-parser.test.ts | 216 + frontend/src/core/template-to-typst.ts | 25 - frontend/src/core/wasm/dreport_core.d.ts | 48 - frontend/src/core/wasm/dreport_core.js | 260 -- .../src/core/wasm/dreport_core_bg.wasm.d.ts | 11 - frontend/src/lib/DreportEditor.vue | 46 +- frontend/src/stores/__tests__/editor.test.ts | 109 + .../src/stores/__tests__/template.test.ts | 202 + frontend/src/styles/properties.css | 207 + frontend/src/workers/typst.worker.ts | 115 - frontend/tests/visual/editor.spec.ts | 63 + .../editor-canvas-darwin.png | Bin 0 -> 75561 bytes .../editor-full-darwin.png | Bin 0 -> 108448 bytes .../properties-panel-selected-darwin.png | Bin 0 -> 27494 bytes .../toolbox-panel-darwin.png | Bin 0 -> 12364 bytes .../tests/visual/test-results/.last-run.json | 4 + frontend/vitest.config.ts | 9 + justfile | 9 - layout-engine/Cargo.toml | 4 +- layout-engine/src/barcode_gen.rs | 2 +- layout-engine/src/data_resolve.rs | 293 +- layout-engine/src/sizing.rs | 206 +- layout-engine/src/table_layout.rs | 217 + layout-engine/src/text_measure.rs | 2 +- layout-engine/src/tree.rs | 10 +- .../tests/fixtures/visual_test_data.json | 4 + .../tests/fixtures/visual_test_template.json | 73 + layout-engine/tests/layout_integration.rs | 321 ++ layout-engine/tests/pdf_render_test.rs | 256 + .../tests/snapshots/visual_test_reference.png | Bin 0 -> 34399 bytes layout-engine/tests/visual_test.rs | 205 + 63 files changed, 4803 insertions(+), 7387 deletions(-) create mode 100644 ELEMENTS.md delete mode 100644 backend/Cargo.lock delete mode 100644 core/src/template_to_typst.rs delete mode 100644 core/src/wasm_api.rs create mode 100644 frontend/playwright.config.ts delete mode 100644 frontend/src/components/editor/TypstSvgLayer.vue create mode 100644 frontend/src/components/panels/SchemaTreeNode.vue create mode 100644 frontend/src/components/panels/SchemaTreePanel.vue create mode 100644 frontend/src/components/properties/BarcodeProperties.vue create mode 100644 frontend/src/components/properties/ContainerProperties.vue create mode 100644 frontend/src/components/properties/ImageProperties.vue create mode 100644 frontend/src/components/properties/LineProperties.vue create mode 100644 frontend/src/components/properties/PageNumberProperties.vue create mode 100644 frontend/src/components/properties/PositioningProperties.vue create mode 100644 frontend/src/components/properties/RepeatingTableProperties.vue create mode 100644 frontend/src/components/properties/SizeProperties.vue create mode 100644 frontend/src/components/properties/TextProperties.vue create mode 100644 frontend/src/composables/useSnapGuides.ts delete mode 100644 frontend/src/composables/useTypstCompiler.ts create mode 100644 frontend/src/core/__tests__/mock-data-generator.test.ts create mode 100644 frontend/src/core/__tests__/schema-parser.test.ts delete mode 100644 frontend/src/core/template-to-typst.ts delete mode 100644 frontend/src/core/wasm/dreport_core.d.ts delete mode 100644 frontend/src/core/wasm/dreport_core.js delete mode 100644 frontend/src/core/wasm/dreport_core_bg.wasm.d.ts create mode 100644 frontend/src/stores/__tests__/editor.test.ts create mode 100644 frontend/src/stores/__tests__/template.test.ts create mode 100644 frontend/src/styles/properties.css delete mode 100644 frontend/src/workers/typst.worker.ts create mode 100644 frontend/tests/visual/editor.spec.ts create mode 100644 frontend/tests/visual/editor.spec.ts-snapshots/editor-canvas-darwin.png create mode 100644 frontend/tests/visual/editor.spec.ts-snapshots/editor-full-darwin.png create mode 100644 frontend/tests/visual/editor.spec.ts-snapshots/properties-panel-selected-darwin.png create mode 100644 frontend/tests/visual/editor.spec.ts-snapshots/toolbox-panel-darwin.png create mode 100644 frontend/tests/visual/test-results/.last-run.json create mode 100644 frontend/vitest.config.ts create mode 100644 layout-engine/tests/fixtures/visual_test_data.json create mode 100644 layout-engine/tests/fixtures/visual_test_template.json create mode 100644 layout-engine/tests/layout_integration.rs create mode 100644 layout-engine/tests/pdf_render_test.rs create mode 100644 layout-engine/tests/snapshots/visual_test_reference.png create mode 100644 layout-engine/tests/visual_test.rs diff --git a/CLAUDE.md b/CLAUDE.md index 07e01aa..4cfed60 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,16 +10,16 @@ Temel fark: Editorde ayri bir canvas render engine (fabric.js, konva.js vb.) KUL ## Teknoloji Kararlari -| Katman | Teknoloji | Gerekce | -| ----------------- | ------------------------------------ | -------------------------------------------------------------- | -| Frontend | Vue 3 (Composition API) + TypeScript | Kullanici tercihi | -| Layout Engine | taffy (flexbox) + cosmic-text | Template JSON → hesaplanmis pozisyonlar; hem WASM hem native | -| Editor Render | HTML div'ler (LayoutRenderer.vue) | Layout engine sonuclarina gore CSS ile render | +| Katman | Teknoloji | Gerekce | +| ----------------- | ------------------------------------ | ---------------------------------------------------------------- | +| Frontend | Vue 3 (Composition API) + TypeScript | Kullanici tercihi | +| Layout Engine | taffy (flexbox) + cosmic-text | Template JSON → hesaplanmis pozisyonlar; hem WASM hem native | +| Editor Render | HTML div'ler (LayoutRenderer.vue) | Layout engine sonuclarina gore CSS ile render | | Etkilesim Katmani | DOM overlay (Vue bilesenleri) | Layout sonuclari uzerine secim, surekleme, yeniden boyutlandirma | -| Backend | Rust + Axum | Layout engine'i dogrudan kullanabilme; performans | -| PDF Render | krilla (server-side) | LayoutResult → PDF; font tutarliligi garantisi | -| Veri Formati | JSON (sablon tanimi + veri) | Evrensel, kolay serialize/deserialize | -| Paket Yonetimi | bun (frontend), cargo (backend) | — | +| Backend | Rust + Axum | Layout engine'i dogrudan kullanabilme; performans | +| PDF Render | krilla (server-side) | LayoutResult → PDF; font tutarliligi garantisi | +| Veri Formati | JSON (sablon tanimi + veri) | Evrensel, kolay serialize/deserialize | +| Paket Yonetimi | bun (frontend), cargo (backend) | — | --- @@ -90,9 +90,10 @@ let layout: LayoutResult = compute_layout(&template, &data, &fonts); ``` WASM tarafinda (frontend): + ```typescript // layout.worker.ts icinde -import init, { computeLayout, loadFonts } from 'dreport-layout-wasm'; +import init, { computeLayout, loadFonts } from "dreport-layout-wasm"; await init(); await loadFonts(fontBytes); @@ -116,6 +117,7 @@ CSS Flexbox mantigina benzeyen container-based layout: - **Opsiyonel absolute positioning:** Kullanici isterse bir elemani `position: "absolute"` yapabilir. Bu sayede: + - Tablo satirlari artarsa alttaki elemanlar otomatik kayar. - Ayni satira iki kolon koymak icin ic ice container yeterlidir. - Absolute mod ile serbest pozisyonlama da mumkundur. @@ -124,11 +126,11 @@ Bu sayede: Her eleman ve container icin `width` ve `height` su tiplerden biri olabilir: -| Tip | Aciklama | Taffy karsiligi | -| ------- | ------------------------------------- | ------------------------------ | -| `fixed` | Sabit boyut (mm) | `Dimension::Length(pt)` | -| `auto` | Iceriqe gore otomatik | `Dimension::Auto` | -| `fr` | Kalan alani oransal doldur | `flex_grow: n, flex_basis: 0` | +| Tip | Aciklama | Taffy karsiligi | +| ------- | -------------------------- | ----------------------------- | +| `fixed` | Sabit boyut (mm) | `Dimension::Length(pt)` | +| `auto` | Iceriqe gore otomatik | `Dimension::Auto` | +| `fr` | Kalan alani oransal doldur | `flex_grow: n, flex_basis: 0` | Ek olarak `minWidth`, `maxWidth`, `minHeight`, `maxHeight` (mm) desteklenir. @@ -156,7 +158,10 @@ Ek olarak `minWidth`, `maxWidth`, `minHeight`, `maxHeight` (mm) desteklenir. "id": "c_header", "type": "container", "position": { "type": "flow" }, - "size": { "width": { "type": "fr", "value": 1 }, "height": { "type": "auto" } }, + "size": { + "width": { "type": "fr", "value": 1 }, + "height": { "type": "auto" }, + }, "direction": "row", "gap": 5, "padding": { "top": 0, "right": 0, "bottom": 0, "left": 0 }, @@ -168,61 +173,70 @@ Ek olarak `minWidth`, `maxWidth`, `minHeight`, `maxHeight` (mm) desteklenir. "id": "el_firma", "type": "text", "position": { "type": "flow" }, - "size": { "width": { "type": "fr", "value": 1 }, "height": { "type": "auto" } }, + "size": { + "width": { "type": "fr", "value": 1 }, + "height": { "type": "auto" }, + }, "style": { "fontSize": 14, "fontWeight": "bold" }, - "binding": { "type": "scalar", "path": "firma.unvan" } + "binding": { "type": "scalar", "path": "firma.unvan" }, }, { "id": "el_fatura_baslik", "type": "static_text", "position": { "type": "flow" }, - "size": { "width": { "type": "auto" }, "height": { "type": "auto" } }, + "size": { + "width": { "type": "auto" }, + "height": { "type": "auto" }, + }, "style": { "fontSize": 12, "fontWeight": "bold", "align": "right" }, - "content": "FATURA" - } - ] + "content": "FATURA", + }, + ], }, { "id": "el_cizgi", "type": "line", "position": { "type": "flow" }, - "size": { "width": { "type": "fr", "value": 1 }, "height": { "type": "auto" } }, - "style": { "strokeColor": "#000000", "strokeWidth": 0.5 } - } - ] - } + "size": { + "width": { "type": "fr", "value": 1 }, + "height": { "type": "auto" }, + }, + "style": { "strokeColor": "#000000", "strokeWidth": 0.5 }, + }, + ], + }, } ``` ### Eleman Tipleri -| Tip | Aciklama | Binding | -| ----------------- | ------------------------------------- | ---------------- | -| `container` | Duzen kutusu, cocuk elemanlari barindirir | Yok | -| `static_text` | Sabit metin, veri baglantisi yok | Yok | -| `text` | Dinamik metin, schema'dan veri ceker | Scalar | -| `repeating_table` | Array verisinden tekrarlayan tablo | Array | -| `line` | Yatay/dikey cizgi | Yok | -| `image` | Statik veya dinamik gorsel | Opsiyonel scalar | -| `page_number` | Sayfa numarasi (cok sayfali belgeler) | Otomatik | +| Tip | Aciklama | Binding | +| ----------------- | ----------------------------------------- | ---------------- | +| `container` | Duzen kutusu, cocuk elemanlari barindirir | Yok | +| `static_text` | Sabit metin, veri baglantisi yok | Yok | +| `text` | Dinamik metin, schema'dan veri ceker | Scalar | +| `repeating_table` | Array verisinden tekrarlayan tablo | Array | +| `line` | Yatay/dikey cizgi | Yok | +| `image` | Statik veya dinamik gorsel | Opsiyonel scalar | +| `page_number` | Sayfa numarasi (cok sayfali belgeler) | Otomatik | ### Container Ozellikleri -| Ozellik | Tip | Aciklama | -| ----------- | ---------------------------------------- | --------------------------------- | -| `direction` | `"row"` \| `"column"` | Cocuklari yatay mi dikey mi diz | -| `gap` | number (mm) | Cocuklar arasi bosluk | -| `padding` | `{ top, right, bottom, left }` (mm) | Ic bosluk | -| `align` | `"start"` \| `"center"` \| `"end"` \| `"stretch"` | Cross-axis hizalama | -| `justify` | `"start"` \| `"center"` \| `"end"` \| `"space-between"` | Main-axis dagilim | -| `style` | `{ backgroundColor, borderColor, borderWidth, borderRadius }` | Gorsel stil | +| Ozellik | Tip | Aciklama | +| ----------- | ------------------------------------------------------------- | ------------------------------- | +| `direction` | `"row"` \| `"column"` | Cocuklari yatay mi dikey mi diz | +| `gap` | number (mm) | Cocuklar arasi bosluk | +| `padding` | `{ top, right, bottom, left }` (mm) | Ic bosluk | +| `align` | `"start"` \| `"center"` \| `"end"` \| `"stretch"` | Cross-axis hizalama | +| `justify` | `"start"` \| `"center"` \| `"end"` \| `"space-between"` | Main-axis dagilim | +| `style` | `{ backgroundColor, borderColor, borderWidth, borderRadius }` | Gorsel stil | ### Positioning Modlari -| Mod | Aciklama | Taffy karsiligi | -| ---------- | ------------------------------------------- | ---------------------------------- | -| `flow` | Parent container'in flow'una katil (default)| `Position::Relative` | -| `absolute` | Parent container icinde sabit konum | `Position::Absolute, inset: top/left` | +| Mod | Aciklama | Taffy karsiligi | +| ---------- | -------------------------------------------- | ------------------------------------- | +| `flow` | Parent container'in flow'una katil (default) | `Position::Relative` | +| `absolute` | Parent container icinde sabit konum | `Position::Absolute, inset: top/left` | ### Fatura Ornegi — Container Agaci @@ -412,18 +426,18 @@ pub struct ElementLayout { ### Taffy Mapping -| dreport | taffy | -| ------------------------------- | ---------------------------------- | -| `container(direction: row)` | `FlexDirection::Row` | -| `container(direction: column)` | `FlexDirection::Column` | -| `gap` | `gap: Size { width, height }` | -| `padding` | `padding: Rect { top, right, bottom, left }` | -| `align: start/center/end/stretch` | `align_items` | -| `justify: start/center/end/space-between` | `justify_content` | -| `SizeValue::Fixed(mm)` | `Dimension::Length(pt)` | -| `SizeValue::Auto` | `Dimension::Auto` | -| `SizeValue::Fr(n)` | `flex_grow: n, flex_basis: 0` | -| `PositionMode::Absolute` | `Position::Absolute, inset: top/left` | +| dreport | taffy | +| ----------------------------------------- | -------------------------------------------- | +| `container(direction: row)` | `FlexDirection::Row` | +| `container(direction: column)` | `FlexDirection::Column` | +| `gap` | `gap: Size { width, height }` | +| `padding` | `padding: Rect { top, right, bottom, left }` | +| `align: start/center/end/stretch` | `align_items` | +| `justify: start/center/end/space-between` | `justify_content` | +| `SizeValue::Fixed(mm)` | `Dimension::Length(pt)` | +| `SizeValue::Auto` | `Dimension::Auto` | +| `SizeValue::Fr(n)` | `flex_grow: n, flex_basis: 0` | +| `PositionMode::Absolute` | `Position::Absolute, inset: top/left` | Text leaf node'lari → taffy `MeasureFunc` callback'i ile cosmic-text'ten olcum alir. @@ -586,6 +600,7 @@ Template JSON + Data JSON alir, PDF doner. **Response:** `Content-Type: application/pdf` — binary PDF **Akis:** + 1. Template + Data JSON parse edilir. 2. `compute_layout(template, data, fonts)` → `LayoutResult` 3. `render_pdf(layout_result, fonts)` → PDF bytes @@ -629,57 +644,11 @@ Sunucu saglik kontrolu. --- -## Gelistirme Oncelikleri (Roadmap) +## Roadmap -### Faz 1: Temel Altyapi ✓ - -- [x] Proje iskeleti kurulumu (Vue + Vite + Pinia, Axum boilerplate) -- [x] Container-based layout sistemi (tree yapi, flow + absolute positioning) -- [x] Font dosyalari (Noto Sans ailesi) - -### Faz 2: Custom Layout Engine ✓ - -- [x] layout-engine crate olusturma (taffy + cosmic-text) -- [x] Template → taffy node tree donusumu (tree.rs) -- [x] SizeValue mapping (sizing.rs) -- [x] Text olcum (text_measure.rs, cosmic-text) -- [x] Binding cozumleme (data_resolve.rs) -- [x] Tablo expansion (table_layout.rs) -- [x] WASM bindings (wasm_api.rs) -- [x] Frontend entegrasyonu (layout.worker.ts, useLayoutEngine.ts, LayoutRenderer.vue) -- [x] InteractionOverlay adaptasyonu -- [x] Typst bagimliliklarinin kaldirilmasi (backend) - -### Faz 3: PDF Render ✓ - -- [x] pdf_render.rs — krilla ile PDF uretimi -- [x] Backend route guncelleme (POST /api/render) -- [x] Page break desteqi (page_break.rs) - -### Faz 4: Editor Temelleri - -- [ ] Schema tree paneli — JSON schema'dan agac olusturma -- [ ] Schema'dan drag ile binding olusturma -- [ ] Properties paneli — secili elemanin stillerini duzenleme (font, renk, boyut, hizalama) -- [ ] Container properties paneli — direction, gap, padding, align ayarlari -- [ ] Mock data generator — schema'dan ornek veri uretip onizlemede kullanma -- [ ] Undo/redo -- [ ] Toolbox paneli — eleman/container ekleme - -### Faz 5: Tablo ve Array Binding - -- [ ] Sutun tanimlama UI'i (alan secimi, genislik, hizalama) -- [ ] Array field'larina binding - [ ] Tablo stili ayarlari (header, zebra, border) - [ ] Format fonksiyonlari (currency, date) - -### Faz 6: Polish - -- [ ] Snap guides ve hizalama -- [ ] Zoom / pan - [ ] `image` eleman tipi (statik + dinamik) -- [ ] Sayfa numarasi -- [ ] Template kaydetme / yukleme (JSON dosyasi export/import) --- diff --git a/Cargo.lock b/Cargo.lock index a743104..fec335e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -248,21 +248,22 @@ dependencies = [ [[package]] name = "cosmic-text" -version = "0.12.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fd57d82eb4bfe7ffa9b1cec0c05e2fd378155b47f255a67983cb4afe0e80c2" +checksum = "bbe782a9e7520cc7de2232c957a47f99d3a35e855552677d07a557bc1a3b66ed" dependencies = [ "bitflags 2.11.0", "fontdb", + "harfrust", + "linebender_resource_handle", "log", "rangemap", - "rayon", - "rustc-hash 1.1.0", - "rustybuzz 0.14.1", + "rustc-hash", "self_cell", + "skrifa 0.40.0", + "smol_str", "swash", "sys-locale", - "ttf-parser 0.21.1", "unicode-bidi", "unicode-linebreak", "unicode-script", @@ -278,31 +279,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - [[package]] name = "csv" version = "1.4.0" @@ -346,7 +322,6 @@ dependencies = [ "base64", "serde", "serde_json", - "wasm-bindgen", ] [[package]] @@ -366,12 +341,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - [[package]] name = "encoding_rs" version = "0.8.35" @@ -458,15 +427,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "font-types" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3971f9a5ca983419cdc386941ba3b9e1feba01a0ab888adf78739feb2798492" -dependencies = [ - "bytemuck", -] - [[package]] name = "font-types" version = "0.10.1" @@ -477,16 +437,25 @@ dependencies = [ ] [[package]] -name = "fontdb" -version = "0.16.2" +name = "font-types" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +checksum = "73829a7b5c91198af28a99159b7ae4afbb252fb906159ff7f189f3a2ceaa3df2" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fontdb" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" dependencies = [ "log", "memmap2", "slotmap", "tinyvec", - "ttf-parser 0.20.0", + "ttf-parser", ] [[package]] @@ -543,9 +512,22 @@ dependencies = [ [[package]] name = "grid" -version = "0.15.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36119f3a540b086b4e436bb2b588cf98a68863470e0e880f4d0842f112a3183a" +checksum = "f9e2d4c0a8296178d8802098410ca05d86b17a10bb5ab559b3fb404c1f948220" + +[[package]] +name = "harfrust" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9da2e5ae821f6e96664977bf974d6d6a2d6682f9ccee23e62ec1d134246845f9" +dependencies = [ + "bitflags 2.11.0", + "bytemuck", + "core_maths", + "read-fonts 0.37.0", + "smallvec", +] [[package]] name = "hashbrown" @@ -732,8 +714,8 @@ dependencies = [ "once_cell", "pdf-writer", "png 0.17.16", - "rustc-hash 2.1.2", - "rustybuzz 0.20.1", + "rustc-hash", + "rustybuzz", "siphasher", "skrifa 0.37.0", "smallvec", @@ -773,6 +755,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +[[package]] +name = "linebender_resource_handle" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" + [[package]] name = "lock_api" version = "0.4.14" @@ -1067,36 +1055,6 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "read-fonts" -version = "0.22.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69aacb76b5c29acfb7f90155d39759a29496aebb49395830e928a9703d2eec2f" -dependencies = [ - "bytemuck", - "font-types 0.7.3", -] - [[package]] name = "read-fonts" version = "0.35.0" @@ -1107,6 +1065,17 @@ dependencies = [ "font-types 0.10.1", ] +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "core_maths", + "font-types 0.11.1", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -1145,12 +1114,6 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.2" @@ -1163,23 +1126,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "rustybuzz" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" -dependencies = [ - "bitflags 2.11.0", - "bytemuck", - "libm", - "smallvec", - "ttf-parser 0.21.1", - "unicode-bidi-mirroring 0.2.0", - "unicode-ccc 0.2.0", - "unicode-properties", - "unicode-script", -] - [[package]] name = "rustybuzz" version = "0.20.1" @@ -1191,9 +1137,9 @@ dependencies = [ "core_maths", "log", "smallvec", - "ttf-parser 0.25.1", - "unicode-bidi-mirroring 0.4.0", - "unicode-ccc 0.4.0", + "ttf-parser", + "unicode-bidi-mirroring", + "unicode-ccc", "unicode-properties", "unicode-script", ] @@ -1342,16 +1288,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" -[[package]] -name = "skrifa" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1c44ad1f6c5bdd4eefed8326711b7dbda9ea45dfd36068c427d332aa382cbe" -dependencies = [ - "bytemuck", - "read-fonts 0.22.7", -] - [[package]] name = "skrifa" version = "0.37.0" @@ -1362,6 +1298,16 @@ dependencies = [ "read-fonts 0.35.0", ] +[[package]] +name = "skrifa" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" +dependencies = [ + "bytemuck", + "read-fonts 0.37.0", +] + [[package]] name = "slab" version = "0.4.12" @@ -1383,6 +1329,12 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "smol_str" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" + [[package]] name = "socket2" version = "0.6.3" @@ -1412,18 +1364,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb6895a12ac5599bb6057362f00e8a3cf1daab4df33f553a55690a44e4fed8d0" dependencies = [ "kurbo", - "rustc-hash 2.1.2", + "rustc-hash", "skrifa 0.37.0", "write-fonts", ] [[package]] name = "swash" -version = "0.1.19" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd59f3f359ddd2c95af4758c18270eddd9c730dde98598023cdabff472c2ca2" +checksum = "842f3cd369c2ba38966204f983eaa5e54a8e84a7d7159ed36ade2b6c335aae64" dependencies = [ - "skrifa 0.22.3", + "skrifa 0.40.0", "yazi", "zeno", ] @@ -1467,9 +1419,9 @@ dependencies = [ [[package]] name = "taffy" -version = "0.7.7" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4f4d046dd956a47a7e1a2947083d7ac3e6aa3cfaaead36173ceaa5ab11878c" +checksum = "41ba83ebaf2954d31d05d67340fd46cebe99da2b7133b0dd68d70c65473a437b" dependencies = [ "arrayvec", "grid", @@ -1613,18 +1565,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "ttf-parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" - -[[package]] -name = "ttf-parser" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" - [[package]] name = "ttf-parser" version = "0.25.1" @@ -1640,24 +1580,12 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" -[[package]] -name = "unicode-bidi-mirroring" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86" - [[package]] name = "unicode-bidi-mirroring" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfa6e8c60bb66d49db113e0125ee8711b7647b5579dc7f5f19c42357ed039fe" -[[package]] -name = "unicode-ccc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" - [[package]] name = "unicode-ccc" version = "0.4.0" @@ -1862,9 +1790,9 @@ checksum = "ce9e2f4a404d9ebffc0a9832cf4f50907220ba3d7fffa9099261a5cab52f2dd7" [[package]] name = "yazi" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" +checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" [[package]] name = "yoke" @@ -1891,9 +1819,9 @@ dependencies = [ [[package]] name = "zeno" -version = "0.2.3" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697" +checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerofrom" diff --git a/ELEMENTS.md b/ELEMENTS.md new file mode 100644 index 0000000..da5846a --- /dev/null +++ b/ELEMENTS.md @@ -0,0 +1,271 @@ +# Eleman Tipleri — dreport + +Bu belge, dreport toolbar'inda bulunan ve planlanmis tum eleman tiplerini aciklar. + +--- + +## Mevcut Elemanlar + +### `container` — Duzen Kutusu + +CSS Flexbox mantiginda calisan layout container'i. Cocuk elemanlari `direction` (row/column) dogrultusunda dizer. Ic ice gecebilir. Tum diger elemanlar bir container icinde yer alir. + +- **Binding:** Yok +- **Ozellikler:** `direction`, `gap`, `padding`, `align`, `justify`, `style` + +--- + +### `static_text` — Sabit Metin + +Veri baglantisi olmayan, kullanicinin dogrudan yazdigi metin. Fatura basliklari, etiketler, aciklama satirlari icin kullanilir. + +- **Binding:** Yok +- **Ozellikler:** `content`, `style` (fontSize, fontWeight, color, align) + +--- + +### `text` — Dinamik Metin + +JSON schema'dan veri ceken metin elemani. Kullanici schema agacindan bir alani surukleyip bu elemana baglar. + +- **Binding:** Scalar (`"binding": { "type": "scalar", "path": "firma.unvan" }`) +- **Ozellikler:** `binding`, `style`, `format` (currency, date, percentage) + +--- + +### `repeating_table` — Tekrarlayan Tablo + +Array verisinden tekrarlayan satirlar ureten tablo bileseni. Fatura kalemleri, stok listeleri gibi tekrarlayan veri icin kullanilir. + +- **Binding:** Array (`"dataSource": "kalemler"`) +- **Ozellikler:** `columns` (alan, genislik, hizalama), `headerStyle`, `rowStyle`, `zebraStyle` + +--- + +### `line` — Cizgi + +Yatay veya dikey ayirici cizgi. Bolum ayirma, dekoratif amaclarla kullanilir. + +- **Binding:** Yok +- **Ozellikler:** `style` (strokeColor, strokeWidth) + +--- + +### `image` — Gorsel + +Statik (base64/URL) veya dinamik (schema'dan) gorsel. Logo, imza, urun gorseli gibi kullanim alanlari. + +- **Binding:** Opsiyonel scalar (dinamik gorsel icin) +- **Ozellikler:** `src` (statik), `binding`, `style` (objectFit) + +--- + +### `page_number` — Sayfa Numarasi + +Cok sayfali belgelerde otomatik sayfa numarasi. Format sablonu destekler (or: "Sayfa {current} / {total}"). + +- **Binding:** Otomatik +- **Ozellikler:** `format`, `style` + +--- + +### `barcode` — Barkod / QR Kod + +1D ve 2D barkod ureteci. e-Fatura, e-Arsiv, urun etiketleri icin kullanilir. + +- **Binding:** Scalar (barkod verisi icin) +- **Desteklenen formatlar:** QR, EAN-13, EAN-8, CODE128, CODE39 +- **Ozellikler:** `barcodeType`, `binding`, `style` + +--- + +## Planlanmis Elemanlar + +### `rich_text` — Zengin Metin [Henuz implemente edilmedi] + +Tek bir metin blogu icinde karisik formatlama destekleyen eleman. Kalin, italik, farkli font boyutu, renk gibi stilleri ayni paragraf icinde kullanmayi saglar. + +- **Kullanim alanlari:** Fatura aciklama alanlari, sozlesme maddeleri, rapor notlari, uzun formlu metin icerikleri +- **Binding:** Opsiyonel scalar (dinamik icerik icin) +- **Yaklasim:** Inline span'lar ile zengin metin. cosmic-text attributed text destekledigi icin layout engine tarafinda uyumlu. + +```jsonc +{ + "type": "rich_text", + "content": [ + { "text": "Odeme vadesi: ", "style": {} }, + { "text": "30 gun", "style": { "fontWeight": "bold", "color": "#e00" } } + ] +} +``` + +**Referans:** Telerik (HtmlTextBox), DevExpress (Rich Text), Stimulsoft, FastReport, CraftMyPDF — hepsinde mevcut. Belge tasarim araclarinda standart bir beklenti. + +--- + +### `shape` — Sekil (Dikdortgen / Elips) [Henuz implemente edilmedi] + +Cocuk eleman barindirmayan sade gorsel element. Vurgu kutulari, dekoratif cerceveler, arka plan alanlari icin kullanilir. Container'dan farki: layout'a katilmaz, sadece gorsel amaclidir. + +- **Kullanim alanlari:** Toplam kutusunun arka plani, raporlarda highlight alanlari, dekoratif cerceveler +- **Binding:** Yok +- **Sekil tipleri:** `rectangle`, `ellipse`, `rounded_rectangle` + +```jsonc +{ + "type": "shape", + "shapeType": "rectangle", + "style": { + "backgroundColor": "#f0f0f0", + "borderColor": "#333", + "borderWidth": 0.5, + "borderRadius": 2 + } +} +``` + +**Referans:** JasperReports, Telerik, DevExpress, Stimulsoft, FastReport, CraftMyPDF — neredeyse tum araclarda var. + +--- + +### `checkbox` — Onay Kutusu [Henuz implemente edilmedi] + +Boolean deger gosteren isaret kutusu. Isaretsiz kare veya isaretli (checkmark) kare olarak render edilir. Veri baglantisi ile dinamik calisan veya statik olarak kullanilabilen basit bir element. + +- **Kullanim alanlari:** Irsaliyelerde "teslim edildi / edilmedi", faturalarda odeme durumu, raporlarda checklist, form benzeri belgeler +- **Binding:** Scalar (boolean alan) + +```jsonc +{ + "type": "checkbox", + "binding": { "type": "scalar", "path": "fatura.odpiendi" }, + "style": { "size": 4, "checkColor": "#000", "borderColor": "#333" } +} +``` + +**Referans:** DevExpress, Telerik, Stimulsoft, FastReport, CraftMyPDF. + +--- + +### `calculated_text` — Hesaplanmis Alan [Henuz implemente edilmedi] + +Basit ifadeler (expression) ile hesaplanmis deger gosteren metin elemani. Aritmetik islemler, string birlestirme ve kosullu metin destekler. + +- **Kullanim alanlari:** Ara toplam hesaplari (`araToplam * 0.20`), string birlestirme (`"Fatura No: " + fatura.no`), kosullu metin, rapor ozetleri +- **Binding:** Expression-based (birden fazla alana referans verebilir) +- **Format:** currency, date, percentage, number destegi + +```jsonc +{ + "type": "calculated_text", + "expression": "toplamlar.araToplam * 0.20", + "format": "currency", + "style": { "fontSize": 10 } +} +``` + +**Referans:** Crystal Reports (Formula Field), JasperReports (Variable), Stimulsoft (Expression). + +--- + +### `current_date` — Tarih / Zaman [Henuz implemente edilmedi] + +Belgenin basilma/render anindaki tarihi otomatik gosteren element. `page_number` gibi otomatik deger uretir, veri baglantisi gerektirmez. + +- **Kullanim alanlari:** Fatura basim tarihi, rapor olusturma zamani, belge altbilgisi +- **Binding:** Otomatik +- **Format:** Konfigurasyon ile (or: `DD.MM.YYYY`, `DD MMMM YYYY`, `DD.MM.YYYY HH:mm`) + +```jsonc +{ + "type": "current_date", + "format": "DD.MM.YYYY", + "style": { "fontSize": 8, "color": "#666" } +} +``` + +**Referans:** Crystal Reports (Print Date), JasperReports (Current Date), BIRT (AutoText). + +--- + +### `page_break` — Sayfa Sonu [Henuz implemente edilmedi] + +Kullanicinin belirli bir noktada yeni sayfaya gecmesini saglayan kontrol elemani. Otomatik sayfa sonu (page_break.rs) zaten mevcut, bu element manuel kontrol saglar. + +- **Kullanim alanlari:** Rapor ozet sayfasi + detay sayfasi ayrimi, faturada ek bilgi sayfasi, belirli bolumlerin ayri sayfada baslamasi +- **Binding:** Yok +- **Gorsel:** Editorde kesikli cizgi olarak gosterilir, PDF'te sayfa gecisi uretir. + +```jsonc +{ + "type": "page_break" +} +``` + +**Referans:** DevExpress (Page Break kontrol), Stimulsoft. + +--- + +### `chart` — Grafik [Henuz implemente edilmedi] + +Veri gorselIestirme icin basit grafik elemani. Rapor ciktilari icin degerli, fatura/irsaliye icin genellikle gereksiz. + +- **Kullanim alanlari:** Satis raporlari, performans ozetleri, karsilastirmali veriler +- **Binding:** Array veya multiple scalar +- **Grafik tipleri:** `bar`, `pie`, `line` (baslangic seti) +- **Yaklasim:** Backend'de SVG olarak render edilip PDF'e image olarak gomulur. + +```jsonc +{ + "type": "chart", + "chartType": "bar", + "dataSource": "aylik_satislar", + "labelField": "ay", + "valueField": "tutar", + "style": { "width": 120, "height": 80 } +} +``` + +**Referans:** JasperReports, Crystal Reports, Telerik, DevExpress, Stimulsoft, CraftMyPDF — enterprise araclarin tamami destekler. + +--- + +## Toolbar Organizasyonu + +``` +Toolbar +├── Duzen +│ ├── Container (mevcut) +│ └── Page Break (planlanmis) +├── Metin +│ ├── Statik Metin (mevcut) +│ ├── Rich Text (planlanmis) +│ └── Hesaplanmis Alan (planlanmis) +├── Veri +│ ├── Tekrarlayan Tablo (mevcut) +│ └── Checkbox (planlanmis) +├── Gorsel +│ ├── Gorsel (mevcut) +│ ├── Cizgi (mevcut) +│ ├── Sekil (planlanmis) +│ └── Barkod / QR (mevcut) +├── Otomatik +│ ├── Sayfa No (mevcut) +│ └── Tarih (planlanmis) +└── Rapor + └── Grafik (planlanmis) +``` + +--- + +## Oncelik Sirasi + +| Oncelik | Element | Gerekce | +|---------|---------|---------| +| 1 | `rich_text` | Karisik formatlama en cok talep edilen ozellik, cosmic-text uyumlu | +| 2 | `shape` | Basit implementasyon, gorsel zenginlik katiyor | +| 3 | `checkbox` | Boolean gosterim, form/irsaliye icin onemli | +| 4 | `calculated_text` | Hesaplama ihtiyaci fatura/rapor icin kritik | +| 5 | `current_date` | Kucuk ama kullanisli, hizli implemente edilir | +| 6 | `page_break` | Manuel sayfa kontrolu, rapor senaryolari icin | +| 7 | `chart` | En karmasik, rapor fazinda ele alinabilir | diff --git a/backend/Cargo.lock b/backend/Cargo.lock deleted file mode 100644 index 6ebc56c..0000000 --- a/backend/Cargo.lock +++ /dev/null @@ -1,4100 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ar_archive_writer" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" -dependencies = [ - "object", -] - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "axum" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" -dependencies = [ - "axum-core", - "bytes", - "form_urlencoded", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "serde_core", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "sync_wrapper", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "az" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "biblatex" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d0c374feba1b9a59042a7c1cf00ce7c34b977b9134fe7c42b08e5183729f66" -dependencies = [ - "paste", - "roman-numerals-rs", - "strum", - "unic-langid", - "unicode-normalization", - "unscanny", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bit-set" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -dependencies = [ - "serde_core", -] - -[[package]] -name = "bumpalo" -version = "3.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" - -[[package]] -name = "by_address" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" - -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - -[[package]] -name = "bytes" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" - -[[package]] -name = "cc" -version = "1.2.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" -dependencies = [ - "find-msvc-tools", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "chinese-number" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e964125508474a83c95eb935697abbeb446ff4e9d62c71ce880e3986d1c606b" -dependencies = [ - "chinese-variant", - "enum-ordinalize", - "num-bigint", - "num-traits", -] - -[[package]] -name = "chinese-variant" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b52a9840ffff5d4d0058ae529fa066a75e794e3125546acfc61c23ad755e49" - -[[package]] -name = "chrono" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "citationberg" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6597e8bdbca37f1f56e5a80d15857b0932aead21a78d20de49e99e74933046" -dependencies = [ - "quick-xml", - "serde", -] - -[[package]] -name = "cobs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" -dependencies = [ - "thiserror", -] - -[[package]] -name = "codex" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9589e1effc5cacbea347899645c654158b03b2053d24bb426fd3128ced6e423c" - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "comemo" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c963350b2b08aa4b725d7802593245380ab53dacfedcaa971385fc33306c0d4" -dependencies = [ - "comemo-macros", - "parking_lot", - "rustc-hash", - "siphasher", - "slab", -] - -[[package]] -name = "comemo-macros" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c400139ba1389ef9e20ad2d87cda68b437a66483aa0da616bdf2cea7413853" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "core_maths" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" -dependencies = [ - "libm", -] - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "csv" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde_core", -] - -[[package]] -name = "csv-core" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" -dependencies = [ - "memchr", -] - -[[package]] -name = "data-url" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.59.0", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dreport-backend" -version = "0.1.0" -dependencies = [ - "anyhow", - "axum", - "base64", - "chrono", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower-http", - "typst", - "typst-kit", - "typst-pdf", -] - -[[package]] -name = "ecow" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78e4f79b296fbaab6ce2e22d52cb4c7f010fe0ebe7a32e34fa25885fd797bd02" -dependencies = [ - "serde", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "embedded-io" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" - -[[package]] -name = "enum-ordinalize" -version = "4.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" -dependencies = [ - "enum-ordinalize-derive", -] - -[[package]] -name = "enum-ordinalize-derive" -version = "4.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "env_proxy" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a5019be18538406a43b5419a5501461f0c8b49ea7dfda0cfc32f4e51fc44be1" -dependencies = [ - "log", - "url", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "euclid" -version = "0.22.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" -dependencies = [ - "num-traits", -] - -[[package]] -name = "fancy-regex" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998b056554fbe42e03ae0e152895cd1a7e1002aec800fdc6635d20270260c46f" -dependencies = [ - "bit-set", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "fast-srgb8" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "filetime" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" -dependencies = [ - "cfg-if", - "libc", - "libredox", -] - -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - -[[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -dependencies = [ - "crc32fast", - "miniz_oxide", - "zlib-rs", -] - -[[package]] -name = "float-cmp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" - -[[package]] -name = "float-cmp" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" -dependencies = [ - "num-traits", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "font-types" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "fontconfig-parser" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" -dependencies = [ - "roxmltree", -] - -[[package]] -name = "fontdb" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" -dependencies = [ - "fontconfig-parser", - "log", - "memmap2", - "slotmap", - "tinyvec", - "ttf-parser", -] - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "slab", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "getrandom" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", - "wasip3", -] - -[[package]] -name = "gif" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "gif" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "glidesort" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e102e6eb644d3e0b186fc161e4460417880a0a0b87d235f2e5b8fb30f2e9e0" - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "zerocopy", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" - -[[package]] -name = "hayagriva" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb69425736f184173b3ca6e27fcba440a61492a790c786b1c6af7e06a03e575" -dependencies = [ - "biblatex", - "ciborium", - "citationberg", - "indexmap", - "paste", - "roman-numerals-rs", - "serde", - "serde_yaml", - "thiserror", - "unic-langid", - "unicode-segmentation", - "unscanny", - "url", -] - -[[package]] -name = "hayro" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048488ba88552bb0fb2a7e4001c64d5bed65d1a92167186a1bb9151571f32e60" -dependencies = [ - "bytemuck", - "hayro-interpret", - "image", - "kurbo 0.12.0", -] - -[[package]] -name = "hayro-font" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10e7e97ce840a6a70e7901e240ec65ba61106b66b37a4a1b899a2ce484248463" -dependencies = [ - "log", - "phf", -] - -[[package]] -name = "hayro-interpret" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56204c972d08e844f3db13b1e14be769f846e576699b46d4f4637cc4f8f70102" -dependencies = [ - "bitflags 2.11.0", - "hayro-font", - "hayro-syntax", - "kurbo 0.12.0", - "log", - "moxcms 0.7.11", - "phf", - "rustc-hash", - "siphasher", - "skrifa", - "smallvec", - "yoke 0.8.1", -] - -[[package]] -name = "hayro-svg" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c673304cec6e0dfd3b4f71fccecd45646899aa70279b62d3f933842abc4ac5" -dependencies = [ - "base64", - "hayro-interpret", - "image", - "kurbo 0.12.0", - "siphasher", - "xmlwriter", -] - -[[package]] -name = "hayro-syntax" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9e5c7dbc0f11dc42775d1a6cc00f5f5137b90b6288dd7fe5f71d17b14d10be" -dependencies = [ - "flate2", - "kurbo 0.12.0", - "log", - "rustc-hash", - "smallvec", - "zune-jpeg 0.4.21", -] - -[[package]] -name = "hayro-write" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc05d8b4bc878b9aee48d980ecb25ed08f1dd9fad6da5ab4d9b7c56ec03a0cf6" -dependencies = [ - "flate2", - "hayro-syntax", - "log", - "pdf-writer", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "http" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", -] - -[[package]] -name = "hyper-util" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" -dependencies = [ - "bytes", - "http", - "http-body", - "hyper", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "hypher" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e25026c579b170c59f8d3ddfc523d7dab0abe079f09eb8edaebd2417044f60" - -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "serde", - "yoke 0.7.5", - "zerofrom", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_collections" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke 0.8.1", - "zerofrom", - "zerovec 0.11.5", -] - -[[package]] -name = "icu_locale_core" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" -dependencies = [ - "displaydoc", - "litemap 0.8.1", - "tinystr 0.8.2", - "writeable 0.6.2", - "zerovec 0.11.5", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap 0.7.5", - "tinystr 0.7.6", - "writeable 0.5.5", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider 1.5.0", - "tinystr 0.7.6", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - -[[package]] -name = "icu_normalizer" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" -dependencies = [ - "icu_collections 2.1.1", - "icu_normalizer_data", - "icu_properties 2.1.2", - "icu_provider 2.1.1", - "smallvec", - "zerovec 0.11.5", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections 1.5.0", - "icu_locid_transform", - "icu_properties_data 1.5.1", - "icu_provider 1.5.0", - "serde", - "tinystr 0.7.6", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_properties" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" -dependencies = [ - "icu_collections 2.1.1", - "icu_locale_core", - "icu_properties_data 2.1.2", - "icu_provider 2.1.1", - "zerotrie 0.2.3", - "zerovec 0.11.5", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" - -[[package]] -name = "icu_properties_data" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "postcard", - "serde", - "stable_deref_trait", - "tinystr 0.7.6", - "writeable 0.5.5", - "yoke 0.7.5", - "zerofrom", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_provider" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable 0.6.2", - "yoke 0.8.1", - "zerofrom", - "zerotrie 0.2.3", - "zerovec 0.11.5", -] - -[[package]] -name = "icu_provider_adapters" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6324dfd08348a8e0374a447ebd334044d766b1839bb8d5ccf2482a99a77c0bc" -dependencies = [ - "icu_locid", - "icu_locid_transform", - "icu_provider 1.5.0", - "tinystr 0.7.6", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_provider_blob" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c24b98d1365f55d78186c205817631a4acf08d7a45bdf5dc9dcf9c5d54dccf51" -dependencies = [ - "icu_provider 1.5.0", - "postcard", - "serde", - "writeable 0.5.5", - "zerotrie 0.1.3", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "icu_segmenter" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a717725612346ffc2d7b42c94b820db6908048f39434504cb130e8b46256b0de" -dependencies = [ - "core_maths", - "displaydoc", - "icu_collections 1.5.0", - "icu_locid", - "icu_provider 1.5.0", - "icu_segmenter_data", - "serde", - "utf8_iter", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_segmenter_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e52775179941363cc594e49ce99284d13d6948928d8e72c755f55e98caa1eb" - -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties 2.1.2", -] - -[[package]] -name = "image" -version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" -dependencies = [ - "bytemuck", - "byteorder-lite", - "color_quant", - "gif 0.14.1", - "image-webp", - "moxcms 0.8.1", - "num-traits", - "png 0.18.1", - "zune-core 0.5.1", - "zune-jpeg 0.5.15", -] - -[[package]] -name = "image-webp" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" -dependencies = [ - "byteorder-lite", - "quick-error", -] - -[[package]] -name = "imagesize" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" - -[[package]] -name = "imagesize" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e54e57b4c48b40f7aec75635392b12b3421fa26fe8b4332e63138ed278459c" - -[[package]] -name = "indexmap" -version = "2.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" -dependencies = [ - "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", -] - -[[package]] -name = "infer" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "js-sys" -version = "0.3.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "kamadak-exif" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1130d80c7374efad55a117d715a3af9368f0fa7a2c54573afc15a188cd984837" -dependencies = [ - "mutate_once", -] - -[[package]] -name = "krilla" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ddfec86fec13d068075e14f22a7e217c281f3ed69ddcb427bf3f5d504fd674" -dependencies = [ - "base64", - "bumpalo", - "comemo", - "flate2", - "float-cmp 0.10.0", - "gif 0.13.3", - "hayro-write", - "image-webp", - "imagesize 0.14.0", - "indexmap", - "once_cell", - "pdf-writer", - "png 0.17.16", - "rayon", - "rustc-hash", - "rustybuzz", - "siphasher", - "skrifa", - "smallvec", - "subsetter", - "tiny-skia-path", - "xmp-writer", - "yoke 0.8.1", - "zune-jpeg 0.5.15", -] - -[[package]] -name = "krilla-svg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f485e1a850201a01dcd8d73e7cf09f2cd4c4cc85c2cd296359094d49336d8ef7" -dependencies = [ - "flate2", - "fontdb", - "krilla", - "png 0.17.16", - "resvg", - "tiny-skia", - "usvg", -] - -[[package]] -name = "kurbo" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62" -dependencies = [ - "arrayvec", - "euclid", - "smallvec", -] - -[[package]] -name = "kurbo" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce9729cc38c18d86123ab736fd2e7151763ba226ac2490ec092d1dd148825e32" -dependencies = [ - "arrayvec", - "euclid", - "smallvec", -] - -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - -[[package]] -name = "libc" -version = "0.2.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" - -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "libredox" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" -dependencies = [ - "bitflags 2.11.0", - "libc", - "plain", - "redox_syscall 0.7.3", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "lipsum" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "636860251af8963cc40f6b4baadee105f02e21b28131d76eba8e40ce84ab8064" -dependencies = [ - "rand", - "rand_chacha", -] - -[[package]] -name = "litemap" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" -dependencies = [ - "serde", -] - -[[package]] -name = "litemap" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "matchit" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "memmap2" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" -dependencies = [ - "libc", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "moxcms" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "moxcms" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "mutate_once" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d2233c9842d08cfe13f9eac96e207ca6a2ea10b80259ebe8ad0268be27d2af" - -[[package]] -name = "native-tls" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "openssl" -version = "0.10.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" -dependencies = [ - "bitflags 2.11.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - -[[package]] -name = "openssl-sys" -version = "0.9.112" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "palette" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" -dependencies = [ - "approx", - "fast-srgb8", - "libm", - "palette_derive", -] - -[[package]] -name = "palette_derive" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" -dependencies = [ - "by_address", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.18", - "smallvec", - "windows-link", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pdf-writer" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a79477295a713c2ed425aa82a8b5d20cec3fdee203706cbe6f3854880c1c81" -dependencies = [ - "bitflags 2.11.0", - "itoa", - "memchr", - "ryu", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "phf" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" -dependencies = [ - "phf_macros", - "phf_shared", - "serde", -] - -[[package]] -name = "phf_generator" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" -dependencies = [ - "fastrand", - "phf_shared", -] - -[[package]] -name = "phf_macros" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pico-args" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "plist" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" -dependencies = [ - "base64", - "indexmap", - "quick-xml", - "serde", - "time", -] - -[[package]] -name = "png" -version = "0.17.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags 2.11.0", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "postcard" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" -dependencies = [ - "cobs", - "embedded-io 0.4.0", - "embedded-io 0.6.1", - "serde", -] - -[[package]] -name = "potential_utf" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" -dependencies = [ - "zerovec 0.11.5", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "psm" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852766467df634d74f0b2d7819bf8dc483a0eb2e3b0f50f756f9cfe8b0d18d8" -dependencies = [ - "ar_archive_writer", - "cc", -] - -[[package]] -name = "pxfm" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" - -[[package]] -name = "qcms" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edecfcd5d755a5e5d98e24cf43113e7cdaec5a070edd0f6b250c03a573da30fa" - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] -name = "quick-xml" -version = "0.38.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "read-fonts" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717cf23b488adf64b9d711329542ba34de147df262370221940dfabc2c91358" -dependencies = [ - "bytemuck", - "font-types", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "redox_syscall" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" - -[[package]] -name = "resvg" -version = "0.45.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8928798c0a55e03c9ca6c4c6846f76377427d2c1e1f7e6de3c06ae57942df43" -dependencies = [ - "gif 0.13.3", - "image-webp", - "log", - "pico-args", - "rgb", - "svgtypes", - "tiny-skia", - "usvg", - "zune-jpeg 0.4.21", -] - -[[package]] -name = "rgb" -version = "0.8.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "roman-numerals-rs" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85cd47a33a4510b1424fe796498e174c6a9cf94e606460ef022a19f3e4ff85e" - -[[package]] -name = "roxmltree" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" - -[[package]] -name = "rust_decimal" -version = "1.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce901f9a19d251159075a4c37af514c3b8ef99c22e02dd8c19161cf397ee94a" -dependencies = [ - "arrayvec", - "num-traits", -] - -[[package]] -name = "rustc-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" - -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags 2.11.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "rustybuzz" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" -dependencies = [ - "bitflags 2.11.0", - "bytemuck", - "core_maths", - "log", - "smallvec", - "ttf-parser", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", -] - -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" -dependencies = [ - "bitflags 2.11.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" -dependencies = [ - "itoa", - "serde", - "serde_core", -] - -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - -[[package]] -name = "simd-adler32" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" - -[[package]] -name = "simplecss" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c" -dependencies = [ - "log", -] - -[[package]] -name = "siphasher" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" - -[[package]] -name = "skrifa" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c31071dedf532758ecf3fed987cdb4bd9509f900e026ab684b4ecb81ea49841" -dependencies = [ - "bytemuck", - "read-fonts", -] - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "slotmap" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "socket2" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "stacker" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d74a23609d509411d10e2176dc2a4346e3b4aea2e7b1869f19fdedbc71c013" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.59.0", -] - -[[package]] -name = "strict-num" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" -dependencies = [ - "float-cmp 0.9.0", -] - -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "subsetter" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6895a12ac5599bb6057362f00e8a3cf1daab4df33f553a55690a44e4fed8d0" -dependencies = [ - "kurbo 0.12.0", - "rustc-hash", - "skrifa", - "write-fonts", -] - -[[package]] -name = "svgtypes" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc" -dependencies = [ - "kurbo 0.11.3", - "siphasher", -] - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "syntect" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "656b45c05d95a5704399aeef6bd0ddec7b2b3531b7c9e900abbf7c4d2190c925" -dependencies = [ - "bincode", - "fancy-regex", - "flate2", - "fnv", - "once_cell", - "plist", - "regex-syntax", - "serde", - "serde_derive", - "serde_json", - "thiserror", - "walkdir", - "yaml-rust", -] - -[[package]] -name = "tar" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom 0.4.2", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "thin-vec" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d" - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" - -[[package]] -name = "time-macros" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-skia" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "log", - "png 0.17.16", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "serde", - "zerovec 0.10.4", -] - -[[package]] -name = "tinystr" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" -dependencies = [ - "displaydoc", - "serde_core", - "zerovec 0.11.5", -] - -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "toml_write", - "winnow", -] - -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - -[[package]] -name = "tower" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" -dependencies = [ - "bitflags 2.11.0", - "bytes", - "http", - "pin-project-lite", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "log", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "ttf-parser" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" -dependencies = [ - "core_maths", -] - -[[package]] -name = "two-face" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e51b6e60e545cfdae5a4639ff423818f52372211a8d9a3e892b4b0761f76b2" -dependencies = [ - "serde", - "serde_derive", - "syntect", -] - -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - -[[package]] -name = "typst" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6511ee598476f4f322b4d13891083d96dbacb8f9c2b908604c7094ba390653" -dependencies = [ - "comemo", - "ecow", - "rustc-hash", - "typst-eval", - "typst-html", - "typst-layout", - "typst-library", - "typst-macros", - "typst-realize", - "typst-syntax", - "typst-timing", - "typst-utils", -] - -[[package]] -name = "typst-assets" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5613cb719a6222fe9b74027c3625d107767ec187bff26b8fc931cf58942c834f" - -[[package]] -name = "typst-eval" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687757487dfc0c1e941344d5024cf7a28364e70c3e304faad89ac65597f62526" -dependencies = [ - "comemo", - "ecow", - "indexmap", - "rustc-hash", - "stacker", - "toml", - "typst-library", - "typst-macros", - "typst-syntax", - "typst-timing", - "typst-utils", - "unicode-segmentation", -] - -[[package]] -name = "typst-html" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e29f8da4f964d4c90739c3c1e0288b0ba1bccc3cc50623a6d558300b86ca8aad" -dependencies = [ - "bumpalo", - "comemo", - "ecow", - "palette", - "rustc-hash", - "time", - "typst-assets", - "typst-library", - "typst-macros", - "typst-svg", - "typst-syntax", - "typst-timing", - "typst-utils", -] - -[[package]] -name = "typst-kit" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31476ec753e080ffdd543a0e74b6d319355449ff3eca3f216634f31cfd09a92a" -dependencies = [ - "dirs", - "ecow", - "env_proxy", - "fastrand", - "flate2", - "fontdb", - "native-tls", - "once_cell", - "openssl", - "serde", - "serde_json", - "tar", - "typst-library", - "typst-syntax", - "typst-timing", - "typst-utils", - "ureq", -] - -[[package]] -name = "typst-layout" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cab0200105831a9158e63718a0f6141c78cb2c1722ed17d19ad28941e3b8491" -dependencies = [ - "az", - "bumpalo", - "codex", - "comemo", - "ecow", - "either", - "hypher", - "icu_properties 1.5.1", - "icu_provider 1.5.0", - "icu_provider_adapters", - "icu_provider_blob", - "icu_segmenter", - "kurbo 0.12.0", - "memchr", - "rustc-hash", - "rustybuzz", - "smallvec", - "ttf-parser", - "typst-assets", - "typst-library", - "typst-macros", - "typst-syntax", - "typst-timing", - "typst-utils", - "unicode-bidi", - "unicode-math-class", - "unicode-script", - "unicode-segmentation", -] - -[[package]] -name = "typst-library" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e276a5de53020c43efe2111ec236252e54ea4480b5ac18063e663dfbe03d9d1b" -dependencies = [ - "az", - "bitflags 2.11.0", - "bumpalo", - "chinese-number", - "ciborium", - "codex", - "comemo", - "csv", - "ecow", - "flate2", - "fontdb", - "glidesort", - "hayagriva", - "hayro-syntax", - "icu_properties 1.5.1", - "icu_provider 1.5.0", - "icu_provider_blob", - "image", - "indexmap", - "kamadak-exif", - "kurbo 0.12.0", - "lipsum", - "memchr", - "palette", - "phf", - "png 0.17.16", - "qcms", - "rayon", - "regex", - "regex-syntax", - "roxmltree", - "rust_decimal", - "rustc-hash", - "rustybuzz", - "serde", - "serde_json", - "serde_yaml", - "siphasher", - "smallvec", - "syntect", - "time", - "toml", - "ttf-parser", - "two-face", - "typed-arena", - "typst-assets", - "typst-macros", - "typst-syntax", - "typst-timing", - "typst-utils", - "unicode-math-class", - "unicode-normalization", - "unicode-segmentation", - "unscanny", - "usvg", - "utf8_iter", - "wasmi", - "xmlwriter", -] - -[[package]] -name = "typst-macros" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141cbd1027129fbf6bda1013f52a264df7befc7388cc8f47767d65e803fd3a59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "typst-pdf" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c8a4630754767cd10d48e8b8186e7dc784631a30a3a93521edf7d77aebd0c0" -dependencies = [ - "az", - "bytemuck", - "comemo", - "ecow", - "image", - "indexmap", - "infer", - "krilla", - "krilla-svg", - "rustc-hash", - "serde", - "smallvec", - "typst-assets", - "typst-library", - "typst-macros", - "typst-syntax", - "typst-timing", - "typst-utils", -] - -[[package]] -name = "typst-realize" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7ffe964757fb93d2e98978aa2a74ee85b0f94c8643e8f3550737258b58f39d8" -dependencies = [ - "arrayvec", - "bumpalo", - "comemo", - "ecow", - "regex", - "typst-library", - "typst-macros", - "typst-syntax", - "typst-timing", - "typst-utils", -] - -[[package]] -name = "typst-svg" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46b811837ade1f0243ef0d8bf3fb06d166443090eac22c28643f374c2ccdc9d" -dependencies = [ - "base64", - "comemo", - "ecow", - "flate2", - "hayro", - "hayro-svg", - "image", - "rustc-hash", - "ttf-parser", - "typst-assets", - "typst-library", - "typst-macros", - "typst-timing", - "typst-utils", - "xmlparser", - "xmlwriter", -] - -[[package]] -name = "typst-syntax" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a95d9192060e23b1e491b0b94dff676acddc92a4d672aeb8ca3890a5a734e879" -dependencies = [ - "ecow", - "rustc-hash", - "serde", - "toml", - "typst-timing", - "typst-utils", - "unicode-ident", - "unicode-math-class", - "unicode-script", - "unicode-segmentation", - "unscanny", -] - -[[package]] -name = "typst-timing" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be94f8faf19841b49574ef5c7fd7a12e2deb7c3d8deba5a596f35d2222024cd" -dependencies = [ - "parking_lot", - "serde", - "serde_json", -] - -[[package]] -name = "typst-utils" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3966c92e8fa48c7ce898130d07000d985f18206d92b250f0f939287fbccdee3" -dependencies = [ - "once_cell", - "portable-atomic", - "rayon", - "rustc-hash", - "siphasher", - "thin-vec", - "unicode-math-class", -] - -[[package]] -name = "unic-langid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05" -dependencies = [ - "unic-langid-impl", - "unic-langid-macros", -] - -[[package]] -name = "unic-langid-impl" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658" -dependencies = [ - "serde", - "tinystr 0.8.2", -] - -[[package]] -name = "unic-langid-macros" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5957eb82e346d7add14182a3315a7e298f04e1ba4baac36f7f0dbfedba5fc25" -dependencies = [ - "proc-macro-hack", - "tinystr 0.8.2", - "unic-langid-impl", - "unic-langid-macros-impl", -] - -[[package]] -name = "unic-langid-macros-impl" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1249a628de3ad34b821ecb1001355bca3940bcb2f88558f1a8bd82e977f75b5" -dependencies = [ - "proc-macro-hack", - "quote", - "syn", - "unic-langid-impl", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - -[[package]] -name = "unicode-bidi-mirroring" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfa6e8c60bb66d49db113e0125ee8711b7647b5579dc7f5f19c42357ed039fe" - -[[package]] -name = "unicode-ccc" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e" - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-math-class" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d246cf599d5fae3c8d56e04b20eb519adb89a8af8d0b0fbcded369aa3647d65" - -[[package]] -name = "unicode-normalization" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-properties" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" - -[[package]] -name = "unicode-script" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" - -[[package]] -name = "unicode-segmentation" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" - -[[package]] -name = "unicode-vo" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] -name = "unscanny" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9df2af067a7953e9c3831320f35c1cc0600c30d44d9f7a12b01db1cd88d6b47" - -[[package]] -name = "ureq" -version = "2.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" -dependencies = [ - "base64", - "flate2", - "log", - "native-tls", - "once_cell", - "serde", - "serde_json", - "url", -] - -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", - "serde_derive", -] - -[[package]] -name = "usvg" -version = "0.45.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef" -dependencies = [ - "base64", - "data-url", - "flate2", - "fontdb", - "imagesize 0.13.0", - "kurbo 0.11.3", - "log", - "pico-args", - "roxmltree", - "rustybuzz", - "simplecss", - "siphasher", - "strict-num", - "svgtypes", - "tiny-skia-path", - "unicode-bidi", - "unicode-script", - "unicode-vo", - "xmlwriter", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.2+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6523d69017b7633e396a89c5efab138161ed5aafcbc8d3e5c5a42ae38f50495a" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3a6c758eb2f701ed3d052ff5737f5bfe6614326ea7f3bbac7156192dc32e67" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921de2737904886b52bcbb237301552d05969a6f9c40d261eb0533c8b055fedf" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93e946af942b58934c604527337bad9ae33ba1d5c6900bbb41c2c07c2364a93" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser 0.244.0", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser 0.244.0", -] - -[[package]] -name = "wasmi" -version = "0.51.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb321403ce594274827657a908e13d1d9918aa02257b8bf8391949d9764023ff" -dependencies = [ - "spin", - "wasmi_collections", - "wasmi_core", - "wasmi_ir", - "wasmparser 0.228.0", -] - -[[package]] -name = "wasmi_collections" -version = "0.51.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b8e98e45a2a534489f8225e765cbf1cb9a3078072605e58158910cf4749172" - -[[package]] -name = "wasmi_core" -version = "0.51.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c25f375c0cdf14810eab07f532f61f14d4966f09c747a55067fdf3196e8512e6" -dependencies = [ - "libm", -] - -[[package]] -name = "wasmi_ir" -version = "0.51.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624e2a68a4293ecb8f564260b68394b29cf3b3edba6bce35532889a2cb33c3d9" -dependencies = [ - "wasmi_core", -] - -[[package]] -name = "wasmparser" -version = "0.228.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abf1132c1fdf747d56bbc1bb52152400c70f336870f968b85e89ea422198ae3" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.0", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - -[[package]] -name = "weezl" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.0", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser 0.244.0", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser 0.244.0", -] - -[[package]] -name = "write-fonts" -version = "0.43.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "886614b5ce857341226aa091f3c285e450683894acaaa7887f366c361efef79d" -dependencies = [ - "font-types", - "indexmap", - "kurbo 0.12.0", - "log", - "read-fonts", -] - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "writeable" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" - -[[package]] -name = "xattr" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" -dependencies = [ - "libc", - "rustix", -] - -[[package]] -name = "xmlparser" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" - -[[package]] -name = "xmlwriter" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" - -[[package]] -name = "xmp-writer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce9e2f4a404d9ebffc0a9832cf4f50907220ba3d7fffa9099261a5cab52f2dd7" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive 0.7.5", - "zerofrom", -] - -[[package]] -name = "yoke" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" -dependencies = [ - "stable_deref_trait", - "yoke-derive 0.8.1", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "yoke-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerotrie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb594dd55d87335c5f60177cee24f19457a5ec10a065e0a3014722ad252d0a1f" -dependencies = [ - "displaydoc", - "litemap 0.7.5", - "serde", - "zerovec 0.10.4", -] - -[[package]] -name = "zerotrie" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" -dependencies = [ - "displaydoc", - "yoke 0.8.1", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "serde", - "yoke 0.7.5", - "zerofrom", - "zerovec-derive 0.10.3", -] - -[[package]] -name = "zerovec" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" -dependencies = [ - "serde", - "yoke 0.8.1", - "zerofrom", - "zerovec-derive 0.11.2", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zlib-rs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - -[[package]] -name = "zune-core" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" - -[[package]] -name = "zune-core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" - -[[package]] -name = "zune-jpeg" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" -dependencies = [ - "zune-core 0.4.12", -] - -[[package]] -name = "zune-jpeg" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" -dependencies = [ - "zune-core 0.5.1", -] diff --git a/core/Cargo.toml b/core/Cargo.toml index e653258..0652e9d 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -4,14 +4,9 @@ version = "0.1.0" edition = "2024" [lib] -crate-type = ["cdylib", "rlib"] +crate-type = ["rlib"] [dependencies] serde = { version = "1", features = ["derive"] } serde_json = "1" base64 = "0.22" -wasm-bindgen = "0.2" - -[features] -default = [] -wasm = [] diff --git a/core/src/lib.rs b/core/src/lib.rs index 0d2bcd0..c446ac8 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,5 +1 @@ pub mod models; -pub mod template_to_typst; - -#[cfg(feature = "wasm")] -mod wasm_api; diff --git a/core/src/template_to_typst.rs b/core/src/template_to_typst.rs deleted file mode 100644 index ae8a338..0000000 --- a/core/src/template_to_typst.rs +++ /dev/null @@ -1,1367 +0,0 @@ -use crate::models::*; -use base64::{Engine, engine::general_purpose::STANDARD as BASE64}; -use std::collections::{HashMap, HashSet}; -use std::fmt::Write; - -/// Render modu — editör önizleme vs. PDF çıktı -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum RenderMode { - /// Editör: layout query ekle, image placeholder göster - Editor, - /// PDF: layout query yok, gerçek image referansları - Pdf, -} - -// --- Ana fonksiyon --- - -/// Template JSON + Data JSON → Typst markup string -pub fn template_to_typst( - template: &Template, - data: &serde_json::Value, - mode: RenderMode, -) -> String { - let mut out = String::new(); - let root = &template.root; - let p = &root.padding; - - // Sayfa ayarları - writeln!( - out, - "#set page(width: {}mm, height: {}mm, margin: (top: {}mm, right: {}mm, bottom: {}mm, left: {}mm))", - template.page.width, template.page.height, p.top, p.right, p.bottom, p.left - ).unwrap(); - writeln!(out).unwrap(); - - // Veri enjeksiyonu - writeln!(out, "#let data = {}", json_to_typst_dict(data)).unwrap(); - writeln!(out).unwrap(); - - // Topological order ile tüm elemanlar - let all_refs = collect_all_topological(root); - - // Barcode import — tiaoma paketi - let barcode_formats = collect_barcode_formats(&all_refs, root); - if !barcode_formats.is_empty() { - let mut import_names: Vec<&str> = barcode_formats - .iter() - .map(|f| barcode_format_to_tiaoma(f)) - .collect(); - import_names.sort(); - import_names.dedup(); - writeln!( - out, - "#import \"@preview/tiaoma:0.3.0\": {}", - import_names.join(", ") - ) - .unwrap(); - writeln!(out).unwrap(); - } - - // Format helpers - let mut used_formats = HashSet::new(); - for el_ref in &all_refs { - if let ElementRef::Leaf(TemplateElement::RepeatingTable(t)) = el_ref { - for col in &t.columns { - if let Some(ref fmt) = col.format { - used_formats.insert(fmt.clone()); - } - } - } - } - let mut sorted_formats: Vec = used_formats.into_iter().collect(); - sorted_formats.sort(); - for fmt in &sorted_formats { - writeln!(out, "{}", generate_format_helper(fmt)).unwrap(); - } - if !sorted_formats.is_empty() { - writeln!(out).unwrap(); - } - - // Parent direction map — line elemanları için - // Her eleman için #let tanımı - for el_ref in &all_refs { - let (id, content) = match el_ref { - ElementRef::Container(c) => { - let is_root = c.id == root.id; - (c.id.as_str(), render_container_content(c, is_root, mode)) - } - ElementRef::Leaf(e) => (e.id(), render_element_content(e, mode)), - }; - writeln!(out, "#let {} = {}", id_to_var(id), content).unwrap(); - } - // Root - writeln!( - out, - "#let {} = {}", - id_to_var(&root.id), - render_container_content(root, true, mode) - ) - .unwrap(); - writeln!(out).unwrap(); - - // Kök container'ı renderla - writeln!(out, "#[#{} <{}>]", id_to_var(&root.id), root.id).unwrap(); - - // Layout query — sadece editör modunda - if mode == RenderMode::Editor { - writeln!(out).unwrap(); - write!( - out, - "{}", - generate_layout_query(&all_refs, root, template.page.width) - ) - .unwrap(); - } - - out -} - -// --- Topological sort --- - -enum ElementRef<'a> { - Container(&'a ContainerElement), - Leaf(&'a TemplateElement), -} - -fn collect_all_topological(root: &ContainerElement) -> Vec> { - let mut result = Vec::new(); - walk_topological(root, &mut result); - result -} - -fn walk_topological<'a>(container: &'a ContainerElement, result: &mut Vec>) { - for child in &container.children { - match child { - TemplateElement::Container(c) => { - walk_topological(c, result); - result.push(ElementRef::Container(c)); - } - other => { - result.push(ElementRef::Leaf(other)); - } - } - } -} - -// --- Element content rendering --- - -fn render_element_content(el: &TemplateElement, mode: RenderMode) -> String { - match el { - TemplateElement::Container(c) => render_container_content(c, false, mode), - TemplateElement::StaticText(e) => render_static_text_content(e), - TemplateElement::Text(e) => render_text_content(e), - TemplateElement::Line(e) => render_line_content(e), - TemplateElement::RepeatingTable(e) => render_repeating_table_content(e), - TemplateElement::Image(e) => render_image_content(e, mode), - TemplateElement::PageNumber(e) => render_page_number_content(e), - TemplateElement::Barcode(e) => render_barcode_content(e), - } -} - -fn render_container_content( - el: &ContainerElement, - skip_padding: bool, - _mode: RenderMode, -) -> String { - let box_params = build_box_params(el, skip_padding); - - let flow_children: Vec<&TemplateElement> = el - .children - .iter() - .filter(|c| !matches!(c.position(), PositionMode::Absolute { .. })) - .collect(); - let absolute_children: Vec<&TemplateElement> = el - .children - .iter() - .filter(|c| matches!(c.position(), PositionMode::Absolute { .. })) - .collect(); - - let mut inner_parts = Vec::new(); - - // Alignment hesapla - let alignment = container_alignment_typst(&el.direction, &el.align, &el.justify); - let is_space_between = el.justify == "space-between"; - - if !flow_children.is_empty() { - if flow_children.len() == 1 { - let c = flow_children[0]; - inner_parts.push(format!( - "#[#{} <{}>]", - id_to_var(c.id()), - c.id() - )); - } else if el.direction == "row" { - // Row container → grid - let row_align_param = match el.align.as_str() { - "center" => Some("horizon"), - "end" => Some("bottom"), - "start" => Some("top"), - _ => None, // stretch = default - }; - - if is_space_between { - // space-between: araya 1fr spacer sütunları ekle - let mut cols = Vec::new(); - let mut items = Vec::new(); - for (i, c) in flow_children.iter().enumerate() { - cols.push(size_value_to_typst(&c.size().width, true)); - items.push(format!(" [#{} <{}>]", id_to_var(c.id()), c.id())); - if i < flow_children.len() - 1 { - cols.push("1fr".to_string()); - items.push(" []".to_string()); - } - } - let mut extra_params = String::new(); - if el.gap > 0.0 { - write!(extra_params, ", column-gutter: {}mm", el.gap).unwrap(); - } - if let Some(a) = row_align_param { - write!(extra_params, ", align: {}", a).unwrap(); - } - inner_parts.push(format!( - "#grid(columns: ({}){},\n{}\n )", - cols.join(", "), - extra_params, - items.join(",\n") - )); - } else { - let col_widths: Vec = flow_children - .iter() - .map(|c| size_value_to_typst(&c.size().width, true)) - .collect(); - let mut extra_params = String::new(); - if el.gap > 0.0 { - write!(extra_params, ", column-gutter: {}mm", el.gap).unwrap(); - } - if let Some(a) = row_align_param { - write!(extra_params, ", align: {}", a).unwrap(); - } - let items: Vec = flow_children - .iter() - .map(|c| format!(" [#{} <{}>]", id_to_var(c.id()), c.id())) - .collect(); - inner_parts.push(format!( - "#grid(columns: ({}){},\n{}\n )", - col_widths.join(", "), - extra_params, - items.join(",\n") - )); - } - } else { - // Column container - if is_space_between && flow_children.len() > 1 { - // space-between: stack yerine v(1fr) spacer'ları ile ayrı bloklar - let mut parts = Vec::new(); - for (i, c) in flow_children.iter().enumerate() { - parts.push(format!("#[#{} <{}>]", id_to_var(c.id()), c.id())); - if i < flow_children.len() - 1 { - parts.push("#v(1fr)".to_string()); - } - } - inner_parts.push(parts.join("\n ")); - } else { - let gap = if el.gap > 0.0 { - format!(", spacing: {}mm", el.gap) - } else { - String::new() - }; - let items: Vec = flow_children - .iter() - .map(|c| format!(" [#{} <{}>]", id_to_var(c.id()), c.id())) - .collect(); - inner_parts.push(format!( - "#stack(dir: ttb{},\n{}\n )", - gap, - items.join(",\n") - )); - } - } - } - - for child in &absolute_children { - if let PositionMode::Absolute { x, y } = child.position() { - inner_parts.push(format!( - "#place(top + left, dx: {}mm, dy: {}mm)[#{} <{}>]", - x, - y, - id_to_var(child.id()), - child.id() - )); - } - } - - if inner_parts.is_empty() { - inner_parts.push("#v(5mm)".to_string()); - } - - let inner = inner_parts.join("\n "); - - // Alignment wrapper ekle (space-between hariç, o zaten yukarıda handle edildi) - if let Some(align_str) = alignment { - if is_space_between { - // space-between durumunda sadece cross-axis alignment uygula - let cross_only = container_cross_axis_typst(&el.direction, &el.align); - if let Some(cross) = cross_only { - format!("box({})[\n #align({})[{}\n ]\n]", box_params, cross, inner) - } else { - format!("box({})[\n {}\n]", box_params, inner) - } - } else { - format!("box({})[\n #align({})[{}\n ]\n]", box_params, align_str, inner) - } - } else { - format!("box({})[\n {}\n]", box_params, inner) - } -} - -/// Container align + justify özelliklerini Typst alignment stringine dönüştür -fn container_alignment_typst(direction: &str, align: &str, justify: &str) -> Option { - let cross = container_cross_axis_typst(direction, align); - - let main = match (direction, justify) { - (_, "start") | (_, "space-between") => None, - ("column", "center") => Some("horizon"), - ("column", "end") => Some("bottom"), - ("row", "center") => Some("center"), - ("row", "end") => Some("right"), - _ => None, - }; - - match (cross, main) { - (Some(c), Some(m)) => Some(format!("{} + {}", c, m)), - (Some(c), None) => Some(c.to_string()), - (None, Some(m)) => Some(m.to_string()), - (None, None) => None, - } -} - -/// Sadece cross-axis alignment (row: align parametresinde kullanılır) -fn container_cross_axis_typst(direction: &str, align: &str) -> Option<&'static str> { - match (direction, align) { - (_, "stretch") => None, - ("column", "start") => Some("left"), - ("column", "center") => Some("center"), - ("column", "end") => Some("right"), - ("row", "start") => Some("top"), - ("row", "center") => Some("horizon"), - ("row", "end") => Some("bottom"), - _ => None, - } -} - -fn render_static_text_content(el: &StaticTextElement) -> String { - let size_params = build_box_size_params(&el.size, false); - let text_cmd = build_text_command(&el.style, &escape_typst_content(&el.content)); - - if !size_params.is_empty() { - format!("box({})[{}]", size_params, text_cmd) - } else { - format!("[{}]", text_cmd) - } -} - -fn render_text_content(el: &TextElement) -> String { - let size_params = build_box_size_params(&el.size, false); - let data_access = format!("#data.{}", el.binding.path); - let content = if let Some(ref prefix) = el.content { - format!("{}{}", escape_typst_content(prefix), data_access) - } else { - data_access - }; - let text_cmd = build_text_command(&el.style, &content); - - if !size_params.is_empty() { - format!("box({})[{}]", size_params, text_cmd) - } else { - format!("[{}]", text_cmd) - } -} - -fn render_line_content(el: &LineElement) -> String { - let stroke = el.style.stroke_width.unwrap_or(0.5); - let color = el.style.stroke_color.as_deref().unwrap_or("#000000"); - - match &el.size.width { - SizeValue::Fr { .. } | SizeValue::Auto => { - format!( - "box(width: 1fr)[#line(length: 100%, stroke: {}pt + rgb(\"{}\"))]", - stroke, color - ) - } - SizeValue::Fixed { value } => { - format!( - "line(length: {}mm, stroke: {}pt + rgb(\"{}\"))", - value, stroke, color - ) - } - } -} - -fn render_image_content(el: &ImageElement, mode: RenderMode) -> String { - let size_params = build_box_size_params(&el.size, false); - let placeholder_size = if size_params.is_empty() { - "width: 40mm, height: 30mm".to_string() - } else { - size_params - }; - - // Dinamik binding - if el.binding.is_some() { - if mode == RenderMode::Pdf { - if let Some(ref binding) = el.binding { - return format!( - "box({}, fill: rgb(\"#f0f4ff\"), stroke: 0.5pt + rgb(\"#bfdbfe\"))[#align(center + horizon)[#text(size: 9pt, fill: rgb(\"#3b82f6\"))[#data.{}]]]", - placeholder_size, binding.path - ); - } - } - return format!( - "box({}, fill: rgb(\"#f0f4ff\"), stroke: 0.5pt + rgb(\"#bfdbfe\"))[#align(center + horizon)[#text(size: 9pt, fill: rgb(\"#3b82f6\"))[Dinamik gorsel]]]", - placeholder_size - ); - } - - if let Some(ref src) = el.src { - if src.starts_with("data:") { - if mode == RenderMode::Pdf { - // Backend: sanal dosya referansı - let img_filename = format!( - "__img_{}.dat", - el.id.replace(|c: char| !c.is_alphanumeric(), "_") - ); - return format!( - "box({})[#image(\"{}\", width: 100%, height: 100%)]", - placeholder_size, img_filename - ); - } - // Editor: placeholder - let mime_match = if src.contains("image/jpeg") { - "jpg" - } else if src.contains("image/svg+xml") { - "svg" - } else { - "png" - }; - return format!( - "box({}, fill: rgb(\"#f8f8f8\"), stroke: 0.5pt + rgb(\"#dddddd\"))[#align(center + horizon)[#text(size: 9pt, fill: rgb(\"#888888\"))[Gorsel (.{})]]]", - placeholder_size, mime_match - ); - } - } - - // Placeholder - format!( - "box({}, fill: rgb(\"#f0f0f0\"), stroke: 0.5pt + rgb(\"#cccccc\"))[#align(center + horizon)[#text(size: 10pt, fill: rgb(\"#999999\"))[Gorsel]]]", - placeholder_size - ) -} - -fn render_page_number_content(el: &PageNumberElement) -> String { - let mut text_params = Vec::new(); - if let Some(fs) = el.style.font_size { - text_params.push(format!("size: {}pt", fs)); - } - if el.style.font_weight.as_deref() == Some("bold") { - text_params.push("weight: \"bold\"".to_string()); - } - if let Some(ref color) = el.style.color { - text_params.push(format!("fill: rgb(\"{}\")", color)); - } - let params = text_params.join(", "); - - let fmt = el.format.as_deref().unwrap_or("{current} / {total}"); - let inner = fmt - .replace( - "{current}", - "\" + str(counter(page).get().first()) + \"", - ) - .replace( - "{total}", - "\" + str(counter(page).final().first()) + \"", - ); - let inner = format!("\"{}\"", inner); - - if let Some(ref align) = el.style.align { - if align != "left" { - return format!( - "[#align({})[#context text({})[#({})]]]", - align, params, inner - ); - } - } - format!("[#context text({})[#({})]]", params, inner) -} - -fn render_barcode_content(el: &BarcodeElement) -> String { - let tiaoma_fn = barcode_format_to_tiaoma(&el.format); - - // Değer: statik veya binding - let value_expr = if let Some(ref binding) = el.binding { - format!("data.{}", binding.path) - } else if let Some(ref value) = el.value { - format!("\"{}\"", value.replace('"', "\\\"")) - } else { - "\"\"".to_string() - }; - - // Options: renk vb. - let mut options = Vec::new(); - if let Some(ref color) = el.style.color { - options.push(format!("fg: rgb(\"{}\")", color)); - } - let options_param = if options.is_empty() { - String::new() - } else { - format!(", options: ({})", options.join(", ")) - }; - - // Boyutu sadece width olarak geçir — tiaoma kendi aspect ratio'sunu korusun - let w = size_value_to_typst(&el.size.width, false); - let size_param = if w != "auto" { - format!(", width: {}", w) - } else { - String::new() - }; - - format!("[#{}({}{}{})]", tiaoma_fn, value_expr, options_param, size_param) -} - -/// Barcode format string → tiaoma fonksiyon adı -fn barcode_format_to_tiaoma(format: &str) -> &'static str { - match format { - "qr" => "qrcode", - "ean13" | "ean8" => "ean", - "code128" => "code128", - "code39" => "code39", - _ => "qrcode", - } -} - -/// Tüm barcode elemanlarının format'larını topla (import için) -fn collect_barcode_formats(all_refs: &[ElementRef<'_>], root: &ContainerElement) -> Vec { - let mut formats = HashSet::new(); - fn walk_barcode(el: &TemplateElement, formats: &mut HashSet) { - match el { - TemplateElement::Barcode(b) => { - formats.insert(b.format.clone()); - } - TemplateElement::Container(c) => { - for child in &c.children { - walk_barcode(child, formats); - } - } - _ => {} - } - } - for child in &root.children { - walk_barcode(child, &mut formats); - } - // Also check non-root refs (shouldn't duplicate but be safe) - for el_ref in all_refs { - if let ElementRef::Leaf(TemplateElement::Barcode(b)) = el_ref { - formats.insert(b.format.clone()); - } - } - let mut sorted: Vec = formats.into_iter().collect(); - sorted.sort(); - sorted -} - -fn render_repeating_table_content(el: &RepeatingTableElement) -> String { - let cols = &el.columns; - if cols.is_empty() || el.data_source.path.is_empty() { - return "box(width: 100%)[#text(fill: rgb(\"#999999\"))[Tablo: veri kaynagi veya sutun tanimlanmamis]]".to_string(); - } - - // Sutun genislikleri - let mut raw_col_widths: Vec = cols - .iter() - .map(|c| match &c.width { - SizeValue::Fixed { value } => format!("{}mm", value), - SizeValue::Fr { value } => format!("{}fr", value), - SizeValue::Auto => "auto".to_string(), - }) - .collect(); - - if !raw_col_widths.iter().any(|w| w.contains("fr")) { - if let Some(pos) = raw_col_widths.iter().rposition(|w| w == "auto") { - raw_col_widths[pos] = "1fr".to_string(); - } - } - let col_widths = raw_col_widths.join(", "); - - let col_aligns: Vec<&str> = cols.iter().map(|c| c.align.as_str()).collect(); - let col_aligns = col_aligns.join(", "); - - let style = &el.style; - let header_bg = style.header_bg.as_deref().unwrap_or("#f0f0f0"); - let zebra_odd = style - .zebra_odd - .as_ref() - .map(|c| format!("rgb(\"{}\")", c)) - .unwrap_or_else(|| "none".to_string()); - let zebra_even = style - .zebra_even - .as_ref() - .map(|c| format!("rgb(\"{}\")", c)) - .unwrap_or_else(|| "none".to_string()); - let fill_fn = format!( - "(_, row) => if row == 0 {{ rgb(\"{}\") }} else if calc.odd(row) {{ {} }} else {{ {} }}", - header_bg, zebra_odd, zebra_even - ); - - let stroke_param = if let Some(ref border_color) = style.border_color { - let bw = style.border_width.unwrap_or(0.5); - format!(", stroke: {}pt + rgb(\"{}\")", bw, border_color) - } else { - String::new() - }; - - let header_color = style.header_color.as_deref().unwrap_or("#000000"); - let header_font_size = style - .header_font_size - .or(style.font_size) - .unwrap_or(10.0); - let header_cells: Vec = cols - .iter() - .map(|c| { - format!( - "[#text(size: {}pt, weight: \"bold\", fill: rgb(\"{}\"))[{}]]", - header_font_size, - header_color, - escape_typst_content(&c.title) - ) - }) - .collect(); - let header_cells = header_cells.join(", "); - - let data_path = format!("data.{}", el.data_source.path); - let font_size = style.font_size.unwrap_or(10.0); - let row_cells: Vec = cols - .iter() - .map(|c| { - let accessor = format!("k.{}", c.field); - if let Some(ref fmt) = c.format { - format!( - "[#text(size: {}pt)[#{}({})]]", - font_size, - format_fn_name(fmt), - accessor - ) - } else { - format!("[#text(size: {}pt)[#{}]]", font_size, accessor) - } - }) - .collect(); - let row_cells = row_cells.join(", "); - - let size_params = build_box_size_params(&el.size, false); - let box_width = if size_params.is_empty() { - "width: 100%".to_string() - } else { - size_params - }; - - format!( - "block({}, clip: false)[#block(width: 100%)[#table(\n columns: ({}),\n align: ({}),\n fill: {}{},\n {},\n ..{}.map(k => ({})).flatten()\n)]]", - box_width, col_widths, col_aligns, fill_fn, stroke_param, header_cells, data_path, row_cells - ) -} - -// --- Layout query (editör modu) --- - -fn generate_layout_query( - all_refs: &[ElementRef<'_>], - root: &ContainerElement, - page_width: f64, -) -> String { - let parent_map = build_parent_map(root); - let width_map = compute_available_widths(root, page_width, &parent_map); - - // Row container'lardaki auto çocukların ID'lerini ve parent bilgisini topla - // Bunlar için Typst context'inde dinamik genişlik hesabı yapacağız - let row_child_info = collect_row_child_info(root); - - let mut var_lines = String::new(); - - // Önce auto çocukları ölç (genişlik kısıtlaması olmadan) - for info in &row_child_info { - if info.is_auto { - let v = id_to_var(&info.id); - writeln!( - var_lines, - " let {}auto_w = measure({}).width", - v, v - ).unwrap(); - } - } - - // Row container'lar için dinamik fr genişliği hesapla - let row_containers = collect_row_containers_with_children(root); - for rc in &row_containers { - let parent_v = id_to_var(&rc.container_id); - let inner_w_var = format!("{}inner_w", parent_v); - - // Container inner width = own_width - padding - let avail_w = width_map.get(&rc.container_id).copied().unwrap_or(page_width); - let inner_w = avail_w - rc.padding_left - rc.padding_right; - let inner_w_rounded = (inner_w * 100.0).round() / 100.0; - - // Auto çocukların toplam genişliğini hesapla - let auto_sum: Vec = rc.children.iter() - .filter(|c| c.is_auto) - .map(|c| format!("{}auto_w", id_to_var(&c.id))) - .collect(); - - let gap_mm = rc.gap * (rc.children.len().saturating_sub(1) as f64); - let fixed_sum: f64 = rc.children.iter() - .filter_map(|c| c.fixed_width) - .sum(); - - if auto_sum.is_empty() { - writeln!( - var_lines, - " let {} = {}mm - {}mm - {}mm", - inner_w_var, inner_w_rounded, fixed_sum, gap_mm - ).unwrap(); - } else { - writeln!( - var_lines, - " let {} = {}mm - {}mm - {}mm - {}", - inner_w_var, inner_w_rounded, fixed_sum, gap_mm, auto_sum.join(" - ") - ).unwrap(); - } - - // Her fr çocuk için gerçek genişliği hesapla - let total_fr: f64 = rc.children.iter() - .filter_map(|c| c.fr_value) - .sum(); - if total_fr > 0.0 { - for child in &rc.children { - if let Some(fr) = child.fr_value { - let child_v = id_to_var(&child.id); - writeln!( - var_lines, - " let {}dyn_w = {} * {} / {}", - child_v, inner_w_var, fr, total_fr - ).unwrap(); - } - } - } - } - - // Tüm elemanlar için pozisyon ve boyut ölçümü - let mut all_ids: Vec<&str> = Vec::new(); - for el_ref in all_refs { - match el_ref { - ElementRef::Container(c) => all_ids.push(&c.id), - ElementRef::Leaf(e) => all_ids.push(e.id()), - } - } - all_ids.push(&root.id); - - // Hangi elemanların dinamik genişliği var? - let dyn_width_ids: HashSet<&str> = row_child_info.iter() - .filter(|c| c.fr_value.is_some()) - .map(|c| c.id.as_str()) - .collect(); - - for id in &all_ids { - let v = id_to_var(id); - if dyn_width_ids.contains(id) { - // Dinamik hesaplanmış genişlik kullan - writeln!( - var_lines, - " let {}p = locate(<{}>).position()\n let {}s = measure({}, width: {}dyn_w)\n result += \"{}:\" + repr({}p.x) + \",\" + repr({}p.y) + \",\" + repr({}s.width) + \",\" + repr({}s.height) + \"|\"", - v, id, v, v, v, id, v, v, v, v - ).unwrap(); - } else { - let avail_w = width_map.get(*id).copied().unwrap_or(page_width); - let avail_w_rounded = (avail_w * 100.0).round() / 100.0; - writeln!( - var_lines, - " let {}p = locate(<{}>).position()\n let {}s = measure({}, width: {}mm)\n result += \"{}:\" + repr({}p.x) + \",\" + repr({}p.y) + \",\" + repr({}s.width) + \",\" + repr({}s.height) + \"|\"", - v, id, v, v, avail_w_rounded, id, v, v, v, v - ).unwrap(); - } - } - - format!( - "#context {{\n let result = \"\"\n{}\n place(bottom + right, text(size: 0.1pt, fill: white)[#result])\n}}", - var_lines.trim_end() - ) -} - -struct RowChildInfo { - id: String, - is_auto: bool, - fr_value: Option, - fixed_width: Option, -} - -struct RowContainerInfo { - container_id: String, - padding_left: f64, - padding_right: f64, - gap: f64, - children: Vec, -} - -fn collect_row_child_info(root: &ContainerElement) -> Vec { - let mut result = Vec::new(); - fn walk(container: &ContainerElement, result: &mut Vec) { - if container.direction == "row" { - for child in &container.children { - if matches!(child.position(), PositionMode::Absolute { .. }) { - continue; - } - let info = match &child.size().width { - SizeValue::Auto => RowChildInfo { - id: child.id().to_string(), - is_auto: true, - fr_value: None, - fixed_width: None, - }, - SizeValue::Fr { value } => RowChildInfo { - id: child.id().to_string(), - is_auto: false, - fr_value: Some(*value), - fixed_width: None, - }, - SizeValue::Fixed { value } => RowChildInfo { - id: child.id().to_string(), - is_auto: false, - fr_value: None, - fixed_width: Some(*value), - }, - }; - result.push(info); - } - } - for child in &container.children { - if let TemplateElement::Container(c) = child { - walk(c, result); - } - } - } - walk(root, &mut result); - result -} - -fn collect_row_containers_with_children(root: &ContainerElement) -> Vec { - let mut result = Vec::new(); - fn walk(container: &ContainerElement, result: &mut Vec) { - if container.direction == "row" { - let children: Vec = container.children.iter() - .filter(|c| !matches!(c.position(), PositionMode::Absolute { .. })) - .map(|child| match &child.size().width { - SizeValue::Auto => RowChildInfo { - id: child.id().to_string(), - is_auto: true, - fr_value: None, - fixed_width: None, - }, - SizeValue::Fr { value } => RowChildInfo { - id: child.id().to_string(), - is_auto: false, - fr_value: Some(*value), - fixed_width: None, - }, - SizeValue::Fixed { value } => RowChildInfo { - id: child.id().to_string(), - is_auto: false, - fr_value: None, - fixed_width: Some(*value), - }, - }) - .collect(); - - if children.iter().any(|c| c.fr_value.is_some()) { - result.push(RowContainerInfo { - container_id: container.id.clone(), - padding_left: container.padding.left, - padding_right: container.padding.right, - gap: container.gap, - children, - }); - } - } - for child in &container.children { - if let TemplateElement::Container(c) = child { - walk(c, result); - } - } - } - walk(root, &mut result); - result -} - -fn build_parent_map(root: &ContainerElement) -> HashMap { - let mut map = HashMap::new(); - fn walk(parent: &ContainerElement, map: &mut HashMap) { - for child in &parent.children { - map.insert(child.id().to_string(), parent.id.clone()); - if let TemplateElement::Container(c) = child { - walk(c, map); - } - } - } - walk(root, &mut map); - map -} - -fn compute_available_widths( - root: &ContainerElement, - page_width: f64, - _parent_map: &HashMap, -) -> HashMap { - let mut map = HashMap::new(); - let root_content_width = page_width - root.padding.left - root.padding.right; - map.insert(root.id.clone(), root_content_width); - - fn get_container_inner_width( - c: &ContainerElement, - root_id: &str, - root_content_width: f64, - map: &HashMap, - ) -> f64 { - let own_width = map.get(&c.id).copied().unwrap_or(root_content_width); - if c.id == root_id { - return own_width; - } - own_width - c.padding.left - c.padding.right - } - - fn walk( - container: &ContainerElement, - root_id: &str, - root_content_width: f64, - map: &mut HashMap, - ) { - let inner_w = - get_container_inner_width(container, root_id, root_content_width, map); - - if container.direction == "column" { - for child in &container.children { - let child_w = match &child.size().width { - SizeValue::Fixed { value } => *value, - _ => inner_w, - }; - map.insert(child.id().to_string(), child_w); - if let TemplateElement::Container(c) = child { - walk(c, root_id, root_content_width, map); - } - } - } else { - // row - let mut used_width = 0.0; - let mut total_fr = 0.0; - let gap = container.gap - * (container.children.len().saturating_sub(1) as f64); - - for child in &container.children { - match &child.size().width { - SizeValue::Fixed { value } => used_width += value, - SizeValue::Fr { value } => total_fr += value, - _ => {} - } - } - - let remaining_w = (inner_w - used_width - gap).max(0.0); - - for child in &container.children { - let child_w = match &child.size().width { - SizeValue::Fixed { value } => *value, - SizeValue::Fr { value } => { - if total_fr > 0.0 { - (value / total_fr) * remaining_w - } else { - remaining_w - } - } - SizeValue::Auto => inner_w, - }; - map.insert(child.id().to_string(), child_w); - if let TemplateElement::Container(c) = child { - walk(c, root_id, root_content_width, map); - } - } - } - } - - walk(root, &root.id, root_content_width, &mut map); - map -} - -// --- Image dosya cikarimi --- - -/// Template'deki base64 image'lari cikar -pub fn extract_image_files(template: &Template) -> HashMap> { - let mut files = HashMap::new(); - collect_images( - &TemplateElement::Container(template.root.clone()), - &mut files, - ); - files -} - -fn collect_images(el: &TemplateElement, files: &mut HashMap>) { - match el { - TemplateElement::Image(img) => { - if let Some(ref src) = img.src { - if src.starts_with("data:") { - if let Some(b64_data) = src.split(',').nth(1) { - if let Ok(bytes) = BASE64.decode(b64_data) { - let filename = format!( - "__img_{}.dat", - img.id - .replace(|c: char| !c.is_alphanumeric(), "_") - ); - files.insert(filename, bytes); - } - } - } - } - } - TemplateElement::Container(c) => { - for child in &c.children { - collect_images(child, files); - } - } - _ => {} - } -} - -// --- Format helpers --- - -fn format_fn_name(fmt: &str) -> &str { - match fmt { - "currency" => "format-currency", - "date" => "format-date", - "percentage" => "format-pct", - "number" => "format-num", - _ => "str", - } -} - -fn generate_format_helper(fmt: &str) -> String { - match fmt { - "currency" => r#"#let format-currency(v) = { - let s = str(calc.round(float(v) * 100) / 100) - let parts = s.split(".") - let int-part = parts.at(0) - let dec-part = if parts.len() > 1 { parts.at(1) } else { "00" } - if dec-part.len() < 2 { dec-part = dec-part + "0" } - let digits = int-part.clusters() - let grouped = "" - let count = 0 - for d in digits.rev() { - if count > 0 and calc.rem(count, 3) == 0 { grouped = "." + grouped } - grouped = d + grouped - count = count + 1 - } - grouped + "," + dec-part + " \u{20BA}" -}"# - .to_string(), - "date" => r#"#let format-date(v) = { - let parts = str(v).split("-") - if parts.len() == 3 { parts.at(2) + "." + parts.at(1) + "." + parts.at(0) } else { str(v) } -}"# - .to_string(), - "percentage" => { - r#"#let format-pct(v) = { str(calc.round(float(v) * 100) / 100) + "%" }"# - .to_string() - } - "number" => r#"#let format-num(v) = { - let s = str(v) - let parts = s.split(".") - let int-part = parts.at(0) - let digits = int-part.clusters() - let grouped = "" - let count = 0 - for d in digits.rev() { - if count > 0 and calc.rem(count, 3) == 0 { grouped = "." + grouped } - grouped = d + grouped - count = count + 1 - } - if parts.len() > 1 { grouped + "," + parts.at(1) } else { grouped } -}"# - .to_string(), - _ => String::new(), - } -} - -// --- Yardimcilar --- - -fn id_to_var(id: &str) -> String { - let mut result = String::from("v_"); - for c in id.chars() { - if c.is_ascii_alphanumeric() { - result.push(c); - } else { - result.push('_'); - } - } - result -} - -fn build_box_params(el: &ContainerElement, skip_padding: bool) -> String { - let mut parts = Vec::new(); - - let size_params = build_box_size_params(&el.size, false); - if !size_params.is_empty() { - parts.push(size_params); - } - - if !skip_padding { - let p = &el.padding; - let has_padding = p.top > 0.0 || p.right > 0.0 || p.bottom > 0.0 || p.left > 0.0; - if has_padding { - parts.push(format!( - "inset: (top: {}mm, right: {}mm, bottom: {}mm, left: {}mm)", - p.top, p.right, p.bottom, p.left - )); - } - } - - let style_params = build_container_style_params(el); - if !style_params.is_empty() { - parts.push(style_params); - } - - parts.join(", ") -} - -fn build_box_size_params(size: &SizeConstraint, allow_fr: bool) -> String { - let mut parts = Vec::new(); - let w = size_value_to_typst(&size.width, allow_fr); - if w != "auto" { - parts.push(format!("width: {}", w)); - } - let h = size_value_to_typst(&size.height, allow_fr); - if h != "auto" { - parts.push(format!("height: {}", h)); - } - parts.join(", ") -} - -fn size_value_to_typst(sv: &SizeValue, allow_fr: bool) -> String { - match sv { - SizeValue::Fixed { value } => format!("{}mm", value), - SizeValue::Auto => "auto".to_string(), - SizeValue::Fr { value } => { - if allow_fr { - format!("{}fr", value) - } else { - "100%".to_string() - } - } - } -} - -fn build_container_style_params(el: &ContainerElement) -> String { - let mut parts = Vec::new(); - if let Some(ref bg) = el.style.background_color { - parts.push(format!("fill: rgb(\"{}\")", bg)); - } - let bw = el.style.border_width.unwrap_or(0.0); - let has_border = bw > 0.0 || el.style.border_color.is_some(); - if has_border { - let width = if bw > 0.0 { bw } else { 1.0 }; - let color = el.style.border_color.as_deref().unwrap_or("#000000"); - let dash_part = match el.style.border_style.as_deref() { - Some("dashed") => ", dash: \"dashed\"", - Some("dotted") => ", dash: \"dotted\"", - _ => "", - }; - parts.push(format!( - "stroke: (paint: rgb(\"{}\"), thickness: {}pt{})", - color, width, dash_part - )); - } - if let Some(br) = el.style.border_radius { - if br > 0.0 { - parts.push(format!("radius: {}pt", br)); - } - } - parts.join(", ") -} - -fn build_text_command(style: &TextStyle, content: &str) -> String { - let mut parts = Vec::new(); - if let Some(fs) = style.font_size { - parts.push(format!("size: {}pt", fs)); - } - if style.font_weight.as_deref() == Some("bold") { - parts.push("weight: \"bold\"".to_string()); - } - if let Some(ref ff) = style.font_family { - parts.push(format!("font: \"{}\"", ff)); - } - if let Some(ref color) = style.color { - parts.push(format!("fill: rgb(\"{}\")", color)); - } - - let params = parts.join(", "); - let mut result = format!("#text({})[{}]", params, content); - - if let Some(ref align) = style.align { - if align != "left" { - result = format!("#align({})[{}]", align, result); - } - } - result -} - -fn escape_typst_content(text: &str) -> String { - text.replace('\\', "\\\\") - .replace('[', "\\[") - .replace(']', "\\]") - .replace('#', "\\#") - .replace('$', "\\$") - .replace('@', "\\@") - .replace('<', "\\<") - .replace('>', "\\>") -} - -fn json_to_typst_dict(val: &serde_json::Value) -> String { - match val { - serde_json::Value::Null => "none".to_string(), - serde_json::Value::Bool(b) => { - if *b { "true" } else { "false" }.to_string() - } - serde_json::Value::Number(n) => n.to_string(), - serde_json::Value::String(s) => { - format!("\"{}\"", s.replace('"', "\\\"")) - } - serde_json::Value::Array(arr) => { - let items: Vec = arr.iter().map(json_to_typst_dict).collect(); - format!("({},)", items.join(", ")) - } - serde_json::Value::Object(obj) => { - let entries: Vec = obj - .iter() - .map(|(k, v)| format!("{}: {}", k, json_to_typst_dict(v))) - .collect(); - if entries.is_empty() { - "(:)".to_string() - } else { - format!("({})", entries.join(", ")) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::models::*; - - #[test] - fn test_row_container_fr_children() { - let template = Template { - id: "test".into(), - name: "Test".into(), - page: PageSettings { width: 210.0, height: 297.0 }, - fonts: vec![], - root: ContainerElement { - id: "root".into(), - position: PositionMode::Flow, - size: SizeConstraint { - width: SizeValue::Auto, - height: SizeValue::Auto, - min_width: None, min_height: None, max_width: None, max_height: None, - }, - direction: "column".into(), - gap: 5.0, - padding: Padding { top: 15.0, right: 15.0, bottom: 15.0, left: 15.0 }, - align: "stretch".into(), - justify: "start".into(), - style: ContainerStyle::default(), - children: vec![ - TemplateElement::Container(ContainerElement { - id: "row1".into(), - position: PositionMode::Flow, - size: SizeConstraint { - width: SizeValue::Fr { value: 1.0 }, - height: SizeValue::Auto, - min_width: None, min_height: None, max_width: None, max_height: None, - }, - direction: "row".into(), - gap: 5.0, - padding: Padding { top: 0.0, right: 0.0, bottom: 0.0, left: 0.0 }, - align: "start".into(), - justify: "start".into(), - style: ContainerStyle::default(), - children: vec![ - TemplateElement::Container(ContainerElement { - id: "child1".into(), - position: PositionMode::Flow, - size: SizeConstraint { - width: SizeValue::Fr { value: 1.0 }, - height: SizeValue::Auto, - min_width: None, min_height: None, max_width: None, max_height: None, - }, - direction: "column".into(), - gap: 0.0, - padding: Padding { top: 5.0, right: 5.0, bottom: 5.0, left: 5.0 }, - align: "start".into(), - justify: "start".into(), - style: ContainerStyle::default(), - children: vec![ - TemplateElement::StaticText(StaticTextElement { - id: "txt1".into(), - position: PositionMode::Flow, - size: SizeConstraint { - width: SizeValue::Auto, - height: SizeValue::Auto, - min_width: None, min_height: None, max_width: None, max_height: None, - }, - style: TextStyle { font_size: Some(11.0), ..Default::default() }, - content: "Sol".into(), - }), - ], - }), - TemplateElement::Container(ContainerElement { - id: "child2".into(), - position: PositionMode::Flow, - size: SizeConstraint { - width: SizeValue::Fr { value: 1.0 }, - height: SizeValue::Auto, - min_width: None, min_height: None, max_width: None, max_height: None, - }, - direction: "column".into(), - gap: 0.0, - padding: Padding { top: 5.0, right: 5.0, bottom: 5.0, left: 5.0 }, - align: "start".into(), - justify: "start".into(), - style: ContainerStyle::default(), - children: vec![ - TemplateElement::StaticText(StaticTextElement { - id: "txt2".into(), - position: PositionMode::Flow, - size: SizeConstraint { - width: SizeValue::Auto, - height: SizeValue::Auto, - min_width: None, min_height: None, max_width: None, max_height: None, - }, - style: TextStyle { font_size: Some(11.0), ..Default::default() }, - content: "Sag".into(), - }), - ], - }), - ], - }), - ], - }, - }; - - let data = serde_json::json!({}); - let result = template_to_typst(&template, &data, RenderMode::Editor); - println!("=== GENERATED TYPST ===\n{}", result); - - // Grid sütunları 1fr kullanmalı, box'lar 100% kullanmalı - assert!(result.contains("columns: (1fr, 1fr)"), "Grid columns should use 1fr:\n{}", result); - assert!(result.contains("box(width: 100%"), "Boxes should use 100%:\n{}", result); - } -} diff --git a/core/src/wasm_api.rs b/core/src/wasm_api.rs deleted file mode 100644 index 6c36355..0000000 --- a/core/src/wasm_api.rs +++ /dev/null @@ -1,26 +0,0 @@ -use wasm_bindgen::prelude::*; - -use crate::models::Template; -use crate::template_to_typst::{self, RenderMode}; - -/// Template JSON + Data JSON → Typst markup (editör modu, layout query dahil) -#[wasm_bindgen(js_name = "templateToTypstEditor")] -pub fn template_to_typst_editor(template_json: &str, data_json: &str) -> Result { - let template: Template = serde_json::from_str(template_json) - .map_err(|e| JsValue::from_str(&format!("Template parse hatasi: {}", e)))?; - let data: serde_json::Value = serde_json::from_str(data_json) - .map_err(|e| JsValue::from_str(&format!("Data parse hatasi: {}", e)))?; - - Ok(template_to_typst::template_to_typst(&template, &data, RenderMode::Editor)) -} - -/// Template JSON + Data JSON → Typst markup (PDF modu, layout query yok) -#[wasm_bindgen(js_name = "templateToTypstPdf")] -pub fn template_to_typst_pdf(template_json: &str, data_json: &str) -> Result { - let template: Template = serde_json::from_str(template_json) - .map_err(|e| JsValue::from_str(&format!("Template parse hatasi: {}", e)))?; - let data: serde_json::Value = serde_json::from_str(data_json) - .map_err(|e| JsValue::from_str(&format!("Data parse hatasi: {}", e)))?; - - Ok(template_to_typst::template_to_typst(&template, &data, RenderMode::Pdf)) -} diff --git a/frontend/bun.lock b/frontend/bun.lock index 5f2eaf7..44912a8 100644 --- a/frontend/bun.lock +++ b/frontend/bun.lock @@ -5,18 +5,19 @@ "": { "name": "frontend", "dependencies": { - "@myriaddreamin/typst-ts-renderer": "^0.7.0-rc2", - "@myriaddreamin/typst-ts-web-compiler": "^0.7.0-rc2", - "@myriaddreamin/typst.ts": "^0.7.0-rc2", "pinia": "^3.0.4", - "vue": "^3.5.30", + "vue": "^3.5.31", }, "devDependencies": { - "@types/node": "^24.12.0", + "@playwright/test": "^1.58.2", + "@types/node": "^25.5.0", "@vitejs/plugin-vue": "^6.0.5", + "@vue/test-utils": "^2.4.6", "@vue/tsconfig": "^0.9.0", - "typescript": "~5.9.3", + "happy-dom": "^20.8.9", + "typescript": "~6.0.2", "vite": "^8.0.1", + "vitest": "^4.1.2", "vue-tsc": "^3.2.5", }, }, @@ -36,18 +37,20 @@ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="], + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], - "@myriaddreamin/typst-ts-renderer": ["@myriaddreamin/typst-ts-renderer@0.7.0-rc2", "", {}, "sha512-god1tcb2YJDkQfA8gLGcAmykVGBpNKorqqDkXVy3InC18KRbsverJhlrHoONurNIU9JuIHoWjJ2D1ntpjPgzbA=="], - - "@myriaddreamin/typst-ts-web-compiler": ["@myriaddreamin/typst-ts-web-compiler@0.7.0-rc2", "", {}, "sha512-WFO/ecKUfeclld5uDxyjgpnIafKpp2LrS6T1vY+CHaSxCm099AneAQIYFg+OtX+NbFpJsLGCBFSw/qppJJmBAw=="], - - "@myriaddreamin/typst.ts": ["@myriaddreamin/typst.ts@0.7.0-rc2", "", { "dependencies": { "idb": "^7.1.1" }, "peerDependencies": { "@myriaddreamin/typst-ts-renderer": "^0.7.0-rc2", "@myriaddreamin/typst-ts-web-compiler": "^0.7.0-rc2" }, "optionalPeers": ["@myriaddreamin/typst-ts-renderer", "@myriaddreamin/typst-ts-web-compiler"] }, "sha512-VM8JqsRcL3AEJ5cuPBn/YvnGTXK/BRPlxdGB2bR48Of/8OIGaPiunv2QfZBIMBBrtbTygUOtAY9BZvkS1AFqgA=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="], + "@one-ini/wasm": ["@one-ini/wasm@0.1.1", "", {}, "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw=="], + "@oxc-project/types": ["@oxc-project/types@0.122.0", "", {}, "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA=="], + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + + "@playwright/test": ["@playwright/test@1.58.2", "", { "dependencies": { "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" } }, "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA=="], + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.12", "", { "os": "android", "cpu": "arm64" }, "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA=="], "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg=="], @@ -80,12 +83,38 @@ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.2", "", {}, "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw=="], + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - "@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], + "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], + + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="], + + "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], + + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], "@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.5", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.2" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "vue": "^3.2.25" } }, "sha512-bL3AxKuQySfk1iGcBsQnoRVexTPJq0Z/ixFVM8OhVJAP6ZXXXLtM7NFKWhLl30Kg7uTBqIaPXbh+nuQCuBDedg=="], + "@vitest/expect": ["@vitest/expect@4.1.2", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.2", "@vitest/utils": "4.1.2", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ=="], + + "@vitest/mocker": ["@vitest/mocker@4.1.2", "", { "dependencies": { "@vitest/spy": "4.1.2", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q=="], + + "@vitest/pretty-format": ["@vitest/pretty-format@4.1.2", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA=="], + + "@vitest/runner": ["@vitest/runner@4.1.2", "", { "dependencies": { "@vitest/utils": "4.1.2", "pathe": "^2.0.3" } }, "sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ=="], + + "@vitest/snapshot": ["@vitest/snapshot@4.1.2", "", { "dependencies": { "@vitest/pretty-format": "4.1.2", "@vitest/utils": "4.1.2", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A=="], + + "@vitest/spy": ["@vitest/spy@4.1.2", "", {}, "sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA=="], + + "@vitest/utils": ["@vitest/utils@4.1.2", "", { "dependencies": { "@vitest/pretty-format": "4.1.2", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ=="], + "@volar/language-core": ["@volar/language-core@2.4.28", "", { "dependencies": { "@volar/source-map": "2.4.28" } }, "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ=="], "@volar/source-map": ["@volar/source-map@2.4.28", "", {}, "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ=="], @@ -118,32 +147,86 @@ "@vue/shared": ["@vue/shared@3.5.31", "", {}, "sha512-nBxuiuS9Lj5bPkPbWogPUnjxxWpkRniX7e5UBQDWl6Fsf4roq9wwV+cR7ezQ4zXswNvPIlsdj1slcLB7XCsRAw=="], + "@vue/test-utils": ["@vue/test-utils@2.4.6", "", { "dependencies": { "js-beautify": "^1.14.9", "vue-component-type-helpers": "^2.0.0" } }, "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow=="], + "@vue/tsconfig": ["@vue/tsconfig@0.9.1", "", { "peerDependencies": { "typescript": ">= 5.8", "vue": "^3.4.0" }, "optionalPeers": ["typescript", "vue"] }, "sha512-buvjm+9NzLCJL29KY1j1991YYJ5e6275OiK+G4jtmfIb+z4POywbdm0wXusT9adVWqe0xqg70TbI7+mRx4uU9w=="], + "abbrev": ["abbrev@2.0.0", "", {}, "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ=="], + "alien-signals": ["alien-signals@3.1.2", "", {}, "sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw=="], + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "birpc": ["birpc@2.9.0", "", {}, "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw=="], + "brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], + + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + + "config-chain": ["config-chain@1.1.13", "", { "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" } }, "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + "copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "editorconfig": ["editorconfig@1.0.7", "", { "dependencies": { "@one-ini/wasm": "0.1.1", "commander": "^10.0.0", "minimatch": "^9.0.1", "semver": "^7.5.3" }, "bin": { "editorconfig": "bin/editorconfig" } }, "sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw=="], + + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], - "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "es-module-lexer": ["es-module-lexer@2.0.0", "", {}, "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], + + "happy-dom": ["happy-dom@20.8.9", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.18.3" } }, "sha512-Tz23LR9T9jOGVZm2x1EPdXqwA37G/owYMxRwU0E4miurAtFsPMQ1d2Jc2okUaSjZqAFz2oEn3FLXC5a0a+siyA=="], + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], - "idb": ["idb@7.1.1", "", {}, "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="], + "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], "is-what": ["is-what@5.5.0", "", {}, "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw=="], + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "js-beautify": ["js-beautify@1.15.4", "", { "dependencies": { "config-chain": "^1.1.13", "editorconfig": "^1.0.4", "glob": "^10.4.2", "js-cookie": "^3.0.5", "nopt": "^7.2.1" }, "bin": { "css-beautify": "js/bin/css-beautify.js", "html-beautify": "js/bin/html-beautify.js", "js-beautify": "js/bin/js-beautify.js" } }, "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA=="], + + "js-cookie": ["js-cookie@3.0.5", "", {}, "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="], + "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="], @@ -168,16 +251,34 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], + "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], + "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="], "muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="], "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "nopt": ["nopt@7.2.1", "", { "dependencies": { "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w=="], + + "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], @@ -186,34 +287,116 @@ "pinia": ["pinia@3.0.4", "", { "dependencies": { "@vue/devtools-api": "^7.7.7" }, "peerDependencies": { "typescript": ">=4.5.0", "vue": "^3.5.11" }, "optionalPeers": ["typescript"] }, "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw=="], + "playwright": ["playwright@1.58.2", "", { "dependencies": { "playwright-core": "1.58.2" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A=="], + + "playwright-core": ["playwright-core@1.58.2", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg=="], + "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], + "proto-list": ["proto-list@1.2.4", "", {}, "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="], + "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], "rolldown": ["rolldown@1.0.0-rc.12", "", { "dependencies": { "@oxc-project/types": "=0.122.0", "@rolldown/pluginutils": "1.0.0-rc.12" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-x64": "1.0.0-rc.12", "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A=="], + "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], "speakingurl": ["speakingurl@14.0.1", "", {}, "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="], + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + + "std-env": ["std-env@4.0.0", "", {}, "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ=="], + + "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="], + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + + "tinyexec": ["tinyexec@1.0.4", "", {}, "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw=="], + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + "tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="], - "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], "vite": ["vite@8.0.3", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.12", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ=="], + "vitest": ["vitest@4.1.2", "", { "dependencies": { "@vitest/expect": "4.1.2", "@vitest/mocker": "4.1.2", "@vitest/pretty-format": "4.1.2", "@vitest/runner": "4.1.2", "@vitest/snapshot": "4.1.2", "@vitest/spy": "4.1.2", "@vitest/utils": "4.1.2", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.2", "@vitest/browser-preview": "4.1.2", "@vitest/browser-webdriverio": "4.1.2", "@vitest/ui": "4.1.2", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg=="], + "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], "vue": ["vue@3.5.31", "", { "dependencies": { "@vue/compiler-dom": "3.5.31", "@vue/compiler-sfc": "3.5.31", "@vue/runtime-dom": "3.5.31", "@vue/server-renderer": "3.5.31", "@vue/shared": "3.5.31" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-iV/sU9SzOlmA/0tygSmjkEN6Jbs3nPoIPFhCMLD2STrjgOU8DX7ZtzMhg4ahVwf5Rp9KoFzcXeB1ZrVbLBp5/Q=="], + "vue-component-type-helpers": ["vue-component-type-helpers@2.2.12", "", {}, "sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw=="], + "vue-tsc": ["vue-tsc@3.2.6", "", { "dependencies": { "@volar/typescript": "2.4.28", "@vue/language-core": "3.2.6" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": { "vue-tsc": "bin/vue-tsc.js" } }, "sha512-gYW/kWI0XrwGzd0PKc7tVB/qpdeAkIZLNZb10/InizkQjHjnT8weZ/vBarZoj4kHKbUTZT/bAVgoOr8x4NsQ/Q=="], + "whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "ws": ["ws@8.20.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA=="], + + "@types/ws/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], + + "@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "happy-dom/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], + + "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], + "rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.12", "", {}, "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "happy-dom/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], } } diff --git a/frontend/package.json b/frontend/package.json index c2918b1..f10e32f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,21 +6,25 @@ "scripts": { "dev": "vite", "build": "vue-tsc -b && vite build", - "preview": "vite preview" + "preview": "vite preview", + "test": "vitest", + "test:run": "vitest run", + "test:visual": "playwright test" }, "dependencies": { - "@myriaddreamin/typst-ts-renderer": "^0.7.0-rc2", - "@myriaddreamin/typst-ts-web-compiler": "^0.7.0-rc2", - "@myriaddreamin/typst.ts": "^0.7.0-rc2", "pinia": "^3.0.4", - "vue": "^3.5.30" + "vue": "^3.5.31" }, "devDependencies": { - "@types/node": "^24.12.0", + "@playwright/test": "^1.58.2", + "@types/node": "^25.5.0", "@vitejs/plugin-vue": "^6.0.5", + "@vue/test-utils": "^2.4.6", "@vue/tsconfig": "^0.9.0", - "typescript": "~5.9.3", + "happy-dom": "^20.8.9", + "typescript": "~6.0.2", "vite": "^8.0.1", + "vitest": "^4.1.2", "vue-tsc": "^3.2.5" } } diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts new file mode 100644 index 0000000..802856c --- /dev/null +++ b/frontend/playwright.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from '@playwright/test' + +export default defineConfig({ + testDir: './tests/visual', + outputDir: './tests/visual/test-results', + use: { + baseURL: 'http://localhost:5173', + viewport: { width: 1400, height: 900 }, + }, + webServer: { + command: 'bun run dev', + port: 5173, + reuseExistingServer: true, + timeout: 30000, + }, + expect: { + toHaveScreenshot: { + maxDiffPixelRatio: 0.01, + }, + }, +}) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 43bf465..629a5c7 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -5,7 +5,7 @@ import type { Template, JsonSchema } from './lib' // --- Full Invoice Schema --- -const invoiceSchema: JsonSchema = { +const defaultInvoiceSchema: JsonSchema = { $id: 'fatura-schema', type: 'object', properties: { @@ -73,6 +73,31 @@ const invoiceSchema: JsonSchema = { }, } +const currentSchema = ref(structuredClone(defaultInvoiceSchema)) + +// --- Schema persistence --- + +const SCHEMA_STORAGE_KEY = 'dreport-schema' + +function loadSchemaFromLocalStorage(): JsonSchema | null { + try { + const raw = localStorage.getItem(SCHEMA_STORAGE_KEY) + if (!raw) return null + return JSON.parse(raw) as JsonSchema + } catch { + return null + } +} + +const savedSchema = loadSchemaFromLocalStorage() +if (savedSchema) { + currentSchema.value = savedSchema +} + +watch(currentSchema, (val) => { + localStorage.setItem(SCHEMA_STORAGE_KEY, JSON.stringify(val)) +}, { deep: true }) + // --- Sample Invoice Data --- const sampleData: Record = { @@ -457,6 +482,7 @@ watch(template, (val) => { const editorRef = ref | null>(null) const pdfLoading = ref(false) const fileInputRef = ref(null) +const schemaFileInputRef = ref(null) function triggerImport() { fileInputRef.value?.click() @@ -469,6 +495,19 @@ function onImportFile(e: Event) { const reader = new FileReader() reader.onload = () => { try { + const parsed = JSON.parse(reader.result as string) + // Detect bundle (has both 'template' and 'schema' keys) + if (parsed.template && parsed.schema) { + editorRef.value?.importTemplate(JSON.stringify(parsed.template)) + currentSchema.value = parsed.schema + return + } + // Detect standalone template (has 'root' key) + if (parsed.root) { + editorRef.value?.importTemplate(reader.result as string) + return + } + // Fallback: try as template editorRef.value?.importTemplate(reader.result as string) } catch { alert('Gecersiz sablon dosyasi') @@ -490,6 +529,59 @@ function exportTemplate() { URL.revokeObjectURL(url) } +// --- Schema import/export --- + +function triggerSchemaImport() { + schemaFileInputRef.value?.click() +} + +function onSchemaImportFile(e: Event) { + const input = e.target as HTMLInputElement + const file = input.files?.[0] + if (!file) return + const reader = new FileReader() + reader.onload = () => { + try { + const schema = JSON.parse(reader.result as string) + currentSchema.value = schema + } catch { + alert('Gecersiz schema dosyasi') + } + } + reader.readAsText(file) + input.value = '' +} + +function exportSchema() { + const json = JSON.stringify(currentSchema.value, null, 2) + const blob = new Blob([json], { type: 'application/json' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = 'schema.json' + a.click() + URL.revokeObjectURL(url) +} + +// --- Bundle export (template + schema) --- + +function exportBundle() { + const templateJson = editorRef.value?.exportTemplate() + if (!templateJson) return + const bundle = { + template: JSON.parse(templateJson), + schema: currentSchema.value, + } + const json = JSON.stringify(bundle, null, 2) + const blob = new Blob([json], { type: 'application/json' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `${template.value.name || 'sablon'}-bundle.json` + a.click() + URL.revokeObjectURL(url) +} + async function downloadPdf() { pdfLoading.value = true try { @@ -510,7 +602,9 @@ async function downloadPdf() { function resetTemplate() { template.value = structuredClone(defaultInvoiceTemplate) + currentSchema.value = structuredClone(defaultInvoiceSchema) localStorage.removeItem(STORAGE_KEY) + localStorage.removeItem(SCHEMA_STORAGE_KEY) } @@ -521,17 +615,50 @@ function resetTemplate() { Belge Tasarim Araci
- - - + + + + + + + + +
+ + + + + +
+ + @@ -548,8 +675,8 @@ function resetTemplate() { .app-header { display: flex; - align-items: baseline; - gap: 12px; + align-items: center; + gap: 8px; padding: 8px 16px; background: #1e293b; color: white; @@ -599,4 +726,20 @@ function resetTemplate() { background: #334155; color: white; } + +.header-btn svg { + width: 14px; + height: 14px; + vertical-align: -2px; + margin-right: 4px; + flex-shrink: 0; +} + +.header-divider { + width: 1px; + height: 20px; + background: #475569; + margin: 0 4px; + flex-shrink: 0; +} diff --git a/frontend/src/components/editor/EditorCanvas.vue b/frontend/src/components/editor/EditorCanvas.vue index d9a5d99..a940be1 100644 --- a/frontend/src/components/editor/EditorCanvas.vue +++ b/frontend/src/components/editor/EditorCanvas.vue @@ -147,12 +147,7 @@ function applyZoom(delta: number, clientX: number, clientY: number) { const mousePageMmX = (clientX - pageRect.left) / oldScale const mousePageMmY = (clientY - pageRect.top) / oldScale - // Flex centering kayması: sayfa genişliği değişince ortalama kayar - // X ekseni: justify-content: center → kayma = (eskiBoyut - yeniBoyut) / 2 const pageW = templateStore.template.page.width - const centerShiftX = pageW * (oldScale - newScale) / 2 - // Y ekseni: align-items: flex-start → kayma yok - const centerShiftY = 0 // Yeni pan: mouse'un gösterdiği mm noktası aynı ekran pozisyonunda kalmalı const newPanX = editorStore.panX + (mousePageMmX - pageW / 2) * (oldScale - newScale) diff --git a/frontend/src/components/editor/ElementHandle.vue b/frontend/src/components/editor/ElementHandle.vue index 34045c3..c77298c 100644 --- a/frontend/src/components/editor/ElementHandle.vue +++ b/frontend/src/components/editor/ElementHandle.vue @@ -17,7 +17,7 @@ const isSelected = computed(() => editorStore.selectedElementId === props.elemen const isContainerEl = computed(() => isContainer(props.element)) const isAbsolute = computed(() => props.element.position.type === 'absolute') -// --- CSS style: layout'u Typst ile eşleştir --- +// --- CSS style: layout engine sonuçlarına göre --- const layoutStyle = computed(() => { const el = props.element const s = props.scale diff --git a/frontend/src/components/editor/InteractionOverlay.vue b/frontend/src/components/editor/InteractionOverlay.vue index 0c1fcc5..d3f68bf 100644 --- a/frontend/src/components/editor/InteractionOverlay.vue +++ b/frontend/src/components/editor/InteractionOverlay.vue @@ -6,6 +6,7 @@ import type { ElementLayout } from '../../core/layout-types' import type { TemplateElement, SizeValue, ContainerElement } from '../../core/types' import { isContainer, sz } from '../../core/types' import ElementToolbar from './ElementToolbar.vue' +import { useSnapGuides } from '../../composables/useSnapGuides' const props = defineProps<{ scale: number @@ -14,6 +15,7 @@ const props = defineProps<{ const templateStore = useTemplateStore() const editorStore = useEditorStore() +const { activeGuides, collectEdges, calculateSnap, calculateResizeSnap, clearGuides } = useSnapGuides() // Tüm elemanları flat olarak topla (root hariç) const flatElements = computed(() => { @@ -382,6 +384,8 @@ function onAbsoluteDragStart(e: PointerEvent, el: TemplateElement) { elY: el.position.y, } + collectEdges(props.layoutMap, el.id, templateStore.template.page.width, templateStore.template.page.height) + window.addEventListener('pointermove', onAbsoluteDragMove) window.addEventListener('pointerup', onAbsoluteDragEnd) } @@ -400,8 +404,16 @@ function onAbsoluteDragMove(e: PointerEvent) { } const pxToMm = 1 / props.scale - const newX = Math.max(0, absoluteDragStart.value.elX + dx * pxToMm) - const newY = Math.max(0, absoluteDragStart.value.elY + dy * pxToMm) + const proposedX = Math.max(0, absoluteDragStart.value.elX + dx * pxToMm) + const proposedY = Math.max(0, absoluteDragStart.value.elY + dy * pxToMm) + + const layout = props.layoutMap[absoluteDragId.value] + const elW = layout ? layout.width_mm : 0 + const elH = layout ? layout.height_mm : 0 + + const snap = calculateSnap(proposedX, proposedY, elW, elH) + const newX = snap.snappedX_mm + const newY = snap.snappedY_mm templateStore.updateElementPosition(absoluteDragId.value, { type: 'absolute', @@ -417,6 +429,7 @@ function onAbsoluteDragEnd() { isDragging.value = false absoluteDragId.value = null editorStore.setDragging(false) + clearGuides() setTimeout(() => { didDrag.value = false }, 50) } @@ -455,6 +468,8 @@ function onResizeStart(e: PointerEvent, elId: string, handle: string) { resizeGhost.value = { x: l.x_mm * s, y: l.y_mm * s, width: l.width_mm * s, height: l.height_mm * s } resizeFinalMm.value = { width: l.width_mm, height: l.height_mm } + collectEdges(props.layoutMap, elId, templateStore.template.page.width, templateStore.template.page.height) + window.addEventListener('pointermove', onResizeMove) window.addEventListener('pointerup', onResizeEnd) } @@ -485,11 +500,25 @@ function onResizeMove(e: PointerEvent) { const startWMm = resizeStart.value.width * pxToMm const startHMm = resizeStart.value.height * pxToMm + const startXMm = resizeStart.value.x * pxToMm + const startYMm = resizeStart.value.y * pxToMm let wMm = startWMm, hMm = startHMm - if (handle.includes('e')) wMm = Math.max(5, startWMm + dx * pxToMm) - if (handle.includes('w')) wMm = Math.max(5, startWMm - dx * pxToMm) - if (handle.includes('s')) hMm = Math.max(3, startHMm + dy * pxToMm) - if (handle.includes('n')) hMm = Math.max(3, startHMm - dy * pxToMm) + if (handle.includes('e')) { + const rightEdge = calculateResizeSnap('right', startXMm + startWMm + dx * pxToMm) + wMm = Math.max(5, rightEdge - startXMm) + } + if (handle.includes('w')) { + const leftEdge = calculateResizeSnap('left', startXMm + dx * pxToMm) + wMm = Math.max(5, startXMm + startWMm - leftEdge) + } + if (handle.includes('s')) { + const bottomEdge = calculateResizeSnap('bottom', startYMm + startHMm + dy * pxToMm) + hMm = Math.max(3, bottomEdge - startYMm) + } + if (handle.includes('n')) { + const topEdge = calculateResizeSnap('top', startYMm + dy * pxToMm) + hMm = Math.max(3, startYMm + startHMm - topEdge) + } if (ar > 0) { hMm = wMm / ar @@ -519,6 +548,7 @@ function onResizeEnd() { isResizing.value = false resizeElementId.value = null resizeHandle.value = '' + clearGuides() } // ============================================================ @@ -629,6 +659,23 @@ const isAnyDragActive = computed(() =>
+ +
+ () // WASM barcode üretme fonksiyonu (EditorCanvas'tan provide edilir) -const generateBarcode = inject<(format: string, value: string, width: number, height: number) => Promise<{ width: number; height: number; rgba: ArrayBuffer } | null>>('generateBarcode') +const generateBarcode = inject<(format: string, value: string, width: number, height: number, includeText: boolean) => Promise<{ width: number; height: number; rgba: ArrayBuffer } | null>>('generateBarcode') const pageElements = computed(() => { if (!props.layout || props.layout.pages.length === 0) return [] diff --git a/frontend/src/components/editor/TypstSvgLayer.vue b/frontend/src/components/editor/TypstSvgLayer.vue deleted file mode 100644 index f7b4ee3..0000000 --- a/frontend/src/components/editor/TypstSvgLayer.vue +++ /dev/null @@ -1,35 +0,0 @@ - - - - - diff --git a/frontend/src/components/panels/PropertiesPanel.vue b/frontend/src/components/panels/PropertiesPanel.vue index 39d73e9..449fe78 100644 --- a/frontend/src/components/panels/PropertiesPanel.vue +++ b/frontend/src/components/panels/PropertiesPanel.vue @@ -1,29 +1,29 @@ + + + + diff --git a/frontend/src/components/panels/SchemaTreePanel.vue b/frontend/src/components/panels/SchemaTreePanel.vue new file mode 100644 index 0000000..9b3825c --- /dev/null +++ b/frontend/src/components/panels/SchemaTreePanel.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/frontend/src/components/properties/BarcodeProperties.vue b/frontend/src/components/properties/BarcodeProperties.vue new file mode 100644 index 0000000..22ff2ab --- /dev/null +++ b/frontend/src/components/properties/BarcodeProperties.vue @@ -0,0 +1,152 @@ + + + diff --git a/frontend/src/components/properties/ContainerProperties.vue b/frontend/src/components/properties/ContainerProperties.vue new file mode 100644 index 0000000..2b93712 --- /dev/null +++ b/frontend/src/components/properties/ContainerProperties.vue @@ -0,0 +1,115 @@ + + + diff --git a/frontend/src/components/properties/ImageProperties.vue b/frontend/src/components/properties/ImageProperties.vue new file mode 100644 index 0000000..d0a79cd --- /dev/null +++ b/frontend/src/components/properties/ImageProperties.vue @@ -0,0 +1,62 @@ + + + diff --git a/frontend/src/components/properties/LineProperties.vue b/frontend/src/components/properties/LineProperties.vue new file mode 100644 index 0000000..a460ce7 --- /dev/null +++ b/frontend/src/components/properties/LineProperties.vue @@ -0,0 +1,34 @@ + + + diff --git a/frontend/src/components/properties/PageNumberProperties.vue b/frontend/src/components/properties/PageNumberProperties.vue new file mode 100644 index 0000000..9da6e7b --- /dev/null +++ b/frontend/src/components/properties/PageNumberProperties.vue @@ -0,0 +1,59 @@ + + + diff --git a/frontend/src/components/properties/PositioningProperties.vue b/frontend/src/components/properties/PositioningProperties.vue new file mode 100644 index 0000000..b6cf9ee --- /dev/null +++ b/frontend/src/components/properties/PositioningProperties.vue @@ -0,0 +1,43 @@ + + + diff --git a/frontend/src/components/properties/RepeatingTableProperties.vue b/frontend/src/components/properties/RepeatingTableProperties.vue new file mode 100644 index 0000000..473d2cb --- /dev/null +++ b/frontend/src/components/properties/RepeatingTableProperties.vue @@ -0,0 +1,242 @@ + + + diff --git a/frontend/src/components/properties/SizeProperties.vue b/frontend/src/components/properties/SizeProperties.vue new file mode 100644 index 0000000..5dfd447 --- /dev/null +++ b/frontend/src/components/properties/SizeProperties.vue @@ -0,0 +1,67 @@ + + + diff --git a/frontend/src/components/properties/TextProperties.vue b/frontend/src/components/properties/TextProperties.vue new file mode 100644 index 0000000..300913b --- /dev/null +++ b/frontend/src/components/properties/TextProperties.vue @@ -0,0 +1,65 @@ + + + diff --git a/frontend/src/composables/useSnapGuides.ts b/frontend/src/composables/useSnapGuides.ts new file mode 100644 index 0000000..034a42f --- /dev/null +++ b/frontend/src/composables/useSnapGuides.ts @@ -0,0 +1,178 @@ +import { ref } from 'vue' +import type { ElementLayout } from '../core/layout-types' + +export interface SnapGuide { + type: 'vertical' | 'horizontal' + position_mm: number +} + +export interface SnapResult { + snappedX_mm: number + snappedY_mm: number + guides: SnapGuide[] +} + +interface EdgeSet { + verticals: number[] // x positions in mm (left, right, center of elements + page) + horizontals: number[] // y positions in mm (top, bottom, center of elements + page) +} + +export function useSnapGuides() { + const SNAP_THRESHOLD_MM = 1.5 + const activeGuides = ref([]) + let cachedEdges: EdgeSet | null = null + + /** Collect edges from all elements except the one being dragged. Call once on drag start. */ + function collectEdges( + layoutMap: Record, + excludeId: string, + pageWidth: number, + pageHeight: number + ) { + const verticals: number[] = [0, pageWidth / 2, pageWidth] // page edges + center + const horizontals: number[] = [0, pageHeight / 2, pageHeight] + + for (const [id, el] of Object.entries(layoutMap)) { + if (id === excludeId) continue + // Left, center, right + verticals.push(el.x_mm, el.x_mm + el.width_mm / 2, el.x_mm + el.width_mm) + // Top, center, bottom + horizontals.push(el.y_mm, el.y_mm + el.height_mm / 2, el.y_mm + el.height_mm) + } + + cachedEdges = { verticals, horizontals } + } + + /** Calculate snap for a dragged element. Returns adjusted position + active guides. */ + function calculateSnap( + proposedX_mm: number, + proposedY_mm: number, + width_mm: number, + height_mm: number + ): SnapResult { + if (!cachedEdges) { + return { snappedX_mm: proposedX_mm, snappedY_mm: proposedY_mm, guides: [] } + } + + const guides: SnapGuide[] = [] + let snappedX = proposedX_mm + let snappedY = proposedY_mm + + // Element edges to check + const myLeft = proposedX_mm + const myCenter = proposedX_mm + width_mm / 2 + const myRight = proposedX_mm + width_mm + + // Find closest vertical snap + let bestVDist = SNAP_THRESHOLD_MM + let bestVSnap: { edge: number; offset: number } | null = null + + for (const v of cachedEdges.verticals) { + // Check left edge + const dLeft = Math.abs(myLeft - v) + if (dLeft < bestVDist) { + bestVDist = dLeft + bestVSnap = { edge: v, offset: 0 } + } + // Check center + const dCenter = Math.abs(myCenter - v) + if (dCenter < bestVDist) { + bestVDist = dCenter + bestVSnap = { edge: v, offset: width_mm / 2 } + } + // Check right edge + const dRight = Math.abs(myRight - v) + if (dRight < bestVDist) { + bestVDist = dRight + bestVSnap = { edge: v, offset: width_mm } + } + } + + if (bestVSnap) { + snappedX = bestVSnap.edge - bestVSnap.offset + guides.push({ type: 'vertical', position_mm: bestVSnap.edge }) + } + + // Element edges to check (Y axis) + const myTop = proposedY_mm + const myMiddle = proposedY_mm + height_mm / 2 + const myBottom = proposedY_mm + height_mm + + // Find closest horizontal snap + let bestHDist = SNAP_THRESHOLD_MM + let bestHSnap: { edge: number; offset: number } | null = null + + for (const h of cachedEdges.horizontals) { + const dTop = Math.abs(myTop - h) + if (dTop < bestHDist) { + bestHDist = dTop + bestHSnap = { edge: h, offset: 0 } + } + const dMiddle = Math.abs(myMiddle - h) + if (dMiddle < bestHDist) { + bestHDist = dMiddle + bestHSnap = { edge: h, offset: height_mm / 2 } + } + const dBottom = Math.abs(myBottom - h) + if (dBottom < bestHDist) { + bestHDist = dBottom + bestHSnap = { edge: h, offset: height_mm } + } + } + + if (bestHSnap) { + snappedY = bestHSnap.edge - bestHSnap.offset + guides.push({ type: 'horizontal', position_mm: bestHSnap.edge }) + } + + activeGuides.value = guides + return { snappedX_mm: snappedX, snappedY_mm: snappedY, guides } + } + + /** Calculate snap for resize edge */ + function calculateResizeSnap( + edge: 'left' | 'right' | 'top' | 'bottom', + proposedValue_mm: number + ): number { + if (!cachedEdges) return proposedValue_mm + + const targets = (edge === 'left' || edge === 'right') + ? cachedEdges.verticals + : cachedEdges.horizontals + + const guides: SnapGuide[] = [] + let snapped = proposedValue_mm + + let bestDist = SNAP_THRESHOLD_MM + for (const t of targets) { + const d = Math.abs(proposedValue_mm - t) + if (d < bestDist) { + bestDist = d + snapped = t + } + } + + if (snapped !== proposedValue_mm) { + guides.push({ + type: (edge === 'left' || edge === 'right') ? 'vertical' : 'horizontal', + position_mm: snapped, + }) + } + + activeGuides.value = guides + return snapped + } + + function clearGuides() { + activeGuides.value = [] + cachedEdges = null + } + + return { + activeGuides, + collectEdges, + calculateSnap, + calculateResizeSnap, + clearGuides, + } +} diff --git a/frontend/src/composables/useTypstCompiler.ts b/frontend/src/composables/useTypstCompiler.ts deleted file mode 100644 index 38b7746..0000000 --- a/frontend/src/composables/useTypstCompiler.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { ref, watch, type Ref } from 'vue' -import type { ElementLayout } from '../core/template-to-typst' -import type { Template } from '../core/types' - -export function useTypstCompiler( - template: Ref