* 🐛 Fix DTCG token import discriminator and group-level $type inheritance
Closes#8342.
The DTCG Community Group Final Report (W3C, 2025-10-28) specifies:
"The presence of a $value property definitively identifies an object
as a token."
"A token's type can be specified by the optional $type property [...]
Furthermore, the $type property on a group applies to all tokens
nested within that group."
Two bugs in `common/src/app/common/types/tokens_lib.cljc` violate the
spec and silently break import of any third-party DTCG file that uses
group-level type inheritance:
1. `flatten-nested-tokens-json` used `(not (contains? v "$type"))` as
the group-vs-token discriminator. A group node carrying only a
`$type` (to set a default for child tokens) was misidentified as a
token, then immediately discarded because it had no `$value`.
2. `schema:dtcg-node` declared both `$type` and `$value` as required,
so even after the discriminator was fixed any leaf token that
relied on group-level type inheritance failed `dtcg-node?`
validation and never reached the parser.
The combined effect: importing a spec-compliant DTCG file that
expressed types at the group level produced a TokensLib with no
tokens at all, because every leaf was discarded as "unknown type".
Penpot-exported files were unaffected because Penpot always emits
both `$type` and `$value` on every token and never attaches `$type`
to a group, so the existing tests covered only the inline-type
shape.
- `schema:dtcg-node`: mark `$type` optional.
- `flatten-nested-tokens-json`: use `$value` as the discriminator
(anything without `$value` is a group), accept an optional
`inherited-type` accumulator that carries the nearest enclosing
group `$type` down through recursion, and resolve a token's type
from its own `$type` first, falling back to the inherited type.
A token's own `$type` always wins over the inherited one (per
spec).
Added `parse-dtcg-group-type-inheritance` covering both cases:
- group `$type` is inherited by tokens that don't declare their own
(`colors.red`, `colors.blue`, `space.small`)
- token `$type` overrides the inherited group `$type`
(`colors.danger`, `space.large`)
Existing DTCG round-trip tests continue to pass because they all
declare `$type` at the token level, which the new code still honours.
CHANGES.md entry added under the 2.17.0 Bugs-fixed section.
* 📚 Do not update CHANGES.md
We are changing the procedures to not update the changelog on each PR. Instead, we use github tracking to check what issues come in a release, and update the changelog automatically in a batch.
Signed-off-by: Andrés Moya <hirunatan@hammo.org>
---------
Signed-off-by: Andrés Moya <hirunatan@hammo.org>
Co-authored-by: MilosM348 <milos.milic001@outlook.com>
Render owned organizations in the delete-account modal with the same
org-avatar* component used across the dashboard, so logo and avatar
background are shown consistently and initials are extracted via
d/get-initials instead of a raw first-character substring.
Extends the get-owned-organizations-summary endpoint and the underlying
nitrate API schema to carry :avatar-bg-url and :logo-id, deriving
:custom-photo from logo-id with the public uri, matching the pattern
already used by set-team-org-api.
* ⚡ Improve performance and fix orphan detection in validate-file
- Add `*ref-shape-cache*` dynamic var to memoize `find-ref-shape`
lookups per page, avoiding repeated O(depth) ancestor walks.
- Add `*children-sets*` pre-computed maps for O(1) parent-child
containment checks, replacing linear `some` scans.
- Short-circuit `inside-component-main?` when the shape context
already implies a main component.
- Use single-pass reduce with early exit for duplicate detection
(children, swap slots) instead of count/distinct or frequencies.
- Guard `check-missing-slot` to skip expensive `find-near-match`
when the shape already has a swap slot.
- Refactor variant-set validation to use `run!` with direct `get`.
- Refactor `check-ref-cycles` to use a single `reduce-kv` pass.
- Fix `get-orphan-shapes`: the original `map` pipeline produced
nils so orphan shapes were never validated; rewrite with
`reduce-kv` for correct results.
- Add `validate-file-affected!` for change-scoped validation,
replacing full file validation in `process-changes-and-validate`
to only validate pages and components touched by the changes.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* ✨ Improved validation
---------
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
Do not show the library sync popup when the only differences are global x/y changes on library components. We now generate the actual sync changes and only notify if there are real redo-changes to apply.
Run cll/generate-sync-file-changes for candidate libraries and filter out those with empty :redo-changes. The expensive check is deferred via rx/timer 0 so it runs asynchronously and does not block the UI.
Why: Position-only changes are normalized during sync (via reposition-shape) and never propagate to copies; showing the popup in that case was a false positive.
Performance: The check is deferred to the next tick to avoid UI stutter on large files with many libraries.
Pass invitation-token through login-from-token event so it reaches
the logged-in state. Fix component render syntax (:& -> :>) for the
verify-token route. Remove redundant navigation that re-visited
verify-token after login. Fix missing dependency in effect hook
to re-run when token changes.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* 🐛 Token remap preserves child component sync after renaming a token group
* 📚 Do not update CHANGES.md
We are changing the procedures to not update the changelog on each PR. Instead, we use github tracking to check what issues come in a release, and update the changelog automatically in a batch.
Signed-off-by: Andrés Moya <andres.moya@kaleidos.net>
---------
Signed-off-by: Andrés Moya <andres.moya@kaleidos.net>
Co-authored-by: Andrés Moya <andres.moya@kaleidos.net>
* 🐛 Fix sharp angles in text-to-path due to wrong quad/conic degree elevation
* 🐛 Preserve even-odd fill type through Skia path conversions
* 🐛 Fix wrong quadratic-to-cubic degree elevation in push_bezier
* 🐛 Skip zero-length degenerate close segments in path_to_beziers
* 🐛 Replace BTreeMap for Vec for bool calculation
* 🐛 Fix even_odd missing when creating Path