@maccesar/titools 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +27 -61
  2. package/lib/cleanup.js +29 -0
  3. package/lib/commands/agents.js +8 -7
  4. package/lib/commands/skills.js +118 -23
  5. package/lib/config.js +13 -15
  6. package/lib/installer.js +5 -3
  7. package/lib/utils.js +36 -0
  8. package/package.json +1 -1
  9. package/skills/alloy-guides/SKILL.md +188 -0
  10. package/skills/alloy-guides/references/CLI_TASKS.md +233 -0
  11. package/skills/alloy-guides/references/CONCEPTS.md +171 -0
  12. package/skills/alloy-guides/references/CONTROLLERS.md +279 -0
  13. package/skills/alloy-guides/references/MODELS.md +742 -0
  14. package/skills/alloy-guides/references/MODELS_ADVANCED.md +482 -0
  15. package/skills/alloy-guides/references/PURGETSS.md +57 -0
  16. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +235 -0
  17. package/skills/alloy-guides/references/VIEWS_STYLES.md +375 -0
  18. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +102 -0
  19. package/skills/alloy-guides/references/VIEWS_XML.md +581 -0
  20. package/skills/alloy-guides/references/WIDGETS.md +160 -0
  21. package/skills/alloy-howtos/SKILL.md +179 -0
  22. package/skills/alloy-howtos/references/best_practices.md +121 -0
  23. package/skills/alloy-howtos/references/cli_reference.md +230 -0
  24. package/skills/alloy-howtos/references/config_files.md +158 -0
  25. package/skills/alloy-howtos/references/custom_tags.md +148 -0
  26. package/skills/alloy-howtos/references/debugging_troubleshooting.md +78 -0
  27. package/skills/alloy-howtos/references/samples.md +156 -0
  28. package/skills/purgetss/SKILL.md +184 -181
  29. package/skills/purgetss/references/EXAMPLES.md +8 -6
  30. package/skills/purgetss/references/app-branding.md +5 -0
  31. package/skills/purgetss/references/apply-directive.md +1 -1
  32. package/skills/purgetss/references/class-categories.md +1 -1
  33. package/skills/purgetss/references/class-index-properties.md +618 -0
  34. package/skills/purgetss/references/class-index.md +4 -610
  35. package/skills/purgetss/references/cli-commands.md +41 -410
  36. package/skills/purgetss/references/custom-fonts.md +292 -0
  37. package/skills/purgetss/references/custom-rules.md +1 -1
  38. package/skills/purgetss/references/customization-deep-dive.md +64 -1
  39. package/skills/purgetss/references/icon-fonts.md +208 -118
  40. package/skills/purgetss/references/installation-setup.md +4 -4
  41. package/skills/purgetss/references/migration-guide.md +53 -1
  42. package/skills/purgetss/references/multi-density-images.md +53 -2
  43. package/skills/purgetss/references/svg-pipeline.md +249 -0
  44. package/skills/purgetss/references/tikit-components.md +2 -2
  45. package/skills/purgetss/references/titanium-resets.md +2 -2
  46. package/skills/purgetss/references/ui-ux-design.md +7 -5
  47. package/skills/purgetss/references/version-history.md +71 -82
  48. package/skills/ti-api/SKILL.md +128 -0
  49. package/skills/ti-api/references/api-android.md +675 -0
  50. package/skills/ti-api/references/api-app-platform.md +636 -0
  51. package/skills/ti-api/references/api-core.md +764 -0
  52. package/skills/ti-api/references/api-data-network.md +641 -0
  53. package/skills/ti-api/references/api-media.md +655 -0
  54. package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
  55. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
  56. package/skills/ti-api/references/api-modules-map.md +632 -0
  57. package/skills/ti-api/references/api-modules-nfc.md +725 -0
  58. package/skills/ti-api/references/api-modules-social-misc.md +526 -0
  59. package/skills/ti-api/references/api-services.md +700 -0
  60. package/skills/ti-api/references/api-ui-android.md +499 -0
  61. package/skills/ti-api/references/api-ui-extras.md +702 -0
  62. package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
  63. package/skills/ti-api/references/api-ui-ios.md +756 -0
  64. package/skills/ti-api/references/api-ui-lists.md +581 -0
  65. package/skills/ti-api/references/api-ui-text-input.md +607 -0
  66. package/skills/ti-api/references/api-ui-views.md +572 -0
  67. package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
  68. package/skills/ti-api/references/api-xml-global.md +743 -0
  69. package/skills/ti-guides/SKILL.md +82 -0
  70. package/skills/ti-guides/references/advanced-data-and-images.md +155 -0
  71. package/skills/ti-guides/references/android-manifest.md +97 -0
  72. package/skills/ti-guides/references/app-distribution.md +373 -0
  73. package/skills/ti-guides/references/application-frameworks.md +366 -0
  74. package/skills/ti-guides/references/cli-reference.md +700 -0
  75. package/skills/ti-guides/references/coding-best-practices.md +150 -0
  76. package/skills/ti-guides/references/commonjs-advanced.md +279 -0
  77. package/skills/ti-guides/references/hello-world.md +99 -0
  78. package/skills/ti-guides/references/hyperloop-native-access.md +458 -0
  79. package/skills/ti-guides/references/javascript-primer.md +402 -0
  80. package/skills/ti-guides/references/reserved-words.md +36 -0
  81. package/skills/ti-guides/references/resources.md +172 -0
  82. package/skills/ti-guides/references/style-and-conventions.md +104 -0
  83. package/skills/ti-guides/references/tiapp-config.md +655 -0
  84. package/skills/ti-howtos/SKILL.md +131 -0
  85. package/skills/ti-howtos/references/android-platform-deep-dives.md +609 -0
  86. package/skills/ti-howtos/references/automation-fastlane-appium.md +96 -0
  87. package/skills/ti-howtos/references/buffer-codec-streams.md +162 -0
  88. package/skills/ti-howtos/references/cross-platform-development.md +358 -0
  89. package/skills/ti-howtos/references/debugging-profiling.md +473 -0
  90. package/skills/ti-howtos/references/extending-titanium.md +684 -0
  91. package/skills/ti-howtos/references/google-maps-v2.md +172 -0
  92. package/skills/ti-howtos/references/ios-map-kit.md +149 -0
  93. package/skills/ti-howtos/references/ios-platform-deep-dives.md +595 -0
  94. package/skills/ti-howtos/references/local-data-sources.md +310 -0
  95. package/skills/ti-howtos/references/location-and-maps.md +267 -0
  96. package/skills/ti-howtos/references/media-apis.md +268 -0
  97. package/skills/ti-howtos/references/notification-services.md +539 -0
  98. package/skills/ti-howtos/references/remote-data-sources.md +339 -0
  99. package/skills/ti-howtos/references/tutorials.md +552 -0
  100. package/skills/ti-howtos/references/using-modules.md +182 -0
  101. package/skills/ti-howtos/references/web-content-integration.md +288 -0
  102. package/skills/ti-howtos/references/webpack-build-pipeline.md +125 -0
@@ -0,0 +1,249 @@
1
+ # SVG-Aware Compile-Time Image Pipeline
2
+
3
+ Added in PurgeTSS v7.11.0 (refined in v7.11.1), the SVG pipeline runs as a **post-step of `purgetss`** — after the regular purge finishes and `app.tss` is finalized. It scans your views and controllers for SVG references, resolves each SVG's display size from the utility classes on the same node, and generates the matching multi-density PNGs. You do **not** call `purgetss images` separately or declare dimensions anywhere else. The cascade of `w-*` / `h-*` classes in your XML decides the size.
4
+
5
+ For the standalone `purgetss images` command (all files under `purgetss/images/`, CLI flags, format conversion), see [Multi-density images](./multi-density-images.md).
6
+
7
+ > **INFO — At a glance**
8
+ >
9
+ > Drop an SVG into `purgetss/images/`, reference it from a view as `image="/images/<sub>/<name>.svg"` with a numeric `w-*` or `h-*` class, and run `purgetss`. The pipeline emits 8 density variants (5 Android + 3 iPhone PNGs). Titanium loads the generated `.png` at runtime even though your XML still says `.svg`. The SVG attribute in your source is never rewritten.
10
+
11
+ ## Why this exists
12
+
13
+ Titanium doesn't load `.svg` files natively in `Ti.UI.ImageView`. Without help you have two options, both manual:
14
+
15
+ 1. Hand-rasterize every SVG into `app/assets/{iphone,android}/images/.../*.png` for every density. Tedious, easy to get wrong, and easy to forget when you swap a logo.
16
+ 2. Run `purgetss images` manually after every SVG edit. Better, but still manual, and you have to know the dimensions in advance.
17
+
18
+ The SVG pipeline removes both chores: you reference the `.svg` from a view, size it with the same utility classes you use everywhere else, and `purgetss` generates the PNGs on the next run.
19
+
20
+ ## The runtime trick
21
+
22
+ When a view requests `image="/foo.svg"` and Titanium cannot use that file as SVG, the image loader falls back to a `.png` with the same basename in the platform assets folder. If PurgeTSS writes `foo.png` plus `@2x`, `@3x`, and the Android densities, the view loads correctly even though the XML still references `.svg`. The pipeline never touches the `.svg` string in your source.
23
+
24
+ ## How it works (the short version)
25
+
26
+ ```text
27
+ purgetss
28
+ ├─ regular purge → writes app.tss with .w-32, .h-auto, .w-(300), etc.
29
+ └─ SVG post-step:
30
+ 1. Parse app.tss → class → props map
31
+ 2. Scan views (.xml) and controllers (.js) for SVG references
32
+ 3. For each SVG, resolve width/height by applying its classes against app.tss
33
+ 4. Sync images.files in config.cjs (autoSync ON)
34
+ 5. Generate PNGs with Sharp, using a hash-based cache to skip unchanged files
35
+ ```
36
+
37
+ The pipeline only touches SVGs you actually reference from views or controllers. Files that sit in `purgetss/images/` but are not referenced anywhere are ignored by the pipeline (the standalone `purgetss images` command still processes them).
38
+
39
+ ## What gets detected
40
+
41
+ **XML views:** any node attribute ending in `.svg` is captured along with its `class=""` attribute:
42
+
43
+ ```xml
44
+ <ImageView class="w-32 h-auto" image="/images/logos/logo.svg" />
45
+ <ImageView class="w-(300) bg-red-500" image="/images/banners/hero.svg" />
46
+ <View backgroundImage="/images/textures/grain.svg" class="wh-screen" />
47
+ ```
48
+
49
+ Both `image` and `backgroundImage` (and any other attribute whose value ends in `.svg`) are picked up.
50
+
51
+ **Controllers:** objects passed to `$.UI.create(...)` (or similar) that mix `image: '...svg'` and `classes: '...'` are captured by an AST walker:
52
+
53
+ ```javascript
54
+ $.UI.create('ImageView', {
55
+ image: '/images/logos/logo.svg',
56
+ classes: 'w-(300) bg-red-500'
57
+ })
58
+ ```
59
+
60
+ ### Static-scanner limitation
61
+
62
+ The scanner sees **literal string values only**, not computed paths. Dynamically composed paths are not detected:
63
+
64
+ ```javascript
65
+ // NOT detected — path is concatenated at runtime
66
+ image: '/images/' + variant + '.svg'
67
+ ```
68
+
69
+ For dynamic references, pin the dimensions manually under `images.files` (see [Manual pinning](#manual-pinning-for-undetected-references)) so the pipeline still generates the PNGs.
70
+
71
+ ## How dimensions get resolved
72
+
73
+ For each SVG reference, the cascade of classes is applied against `app.tss` in declaration order (later-wins, matching Alloy semantics). The pipeline pulls the final `width` and `height` numbers:
74
+
75
+ | Class on the view | What `app.tss` resolves | What the pipeline pins |
76
+ | ------------------------------ | ---------------------------------- | -------------------------------------------------------------- |
77
+ | `class="w-32"` | `width: 128` | `widthDp = 128` |
78
+ | `class="w-40 h-12"` | `width: 160`, `height: 48` | `widthDp = 160`, `heightDp = 48` |
79
+ | `class="w-(300)"` | `width: 300` (arbitrary value) | `widthDp = 300` |
80
+ | `class="h-44"` (no `w-*`) | `height: 176` | `heightDp = 176`; width derived from viewBox at generation time |
81
+ | `class="w-32 h-auto"` | `width: 128`, `height: Ti.UI.SIZE` | `widthDp = 128`; height derived from viewBox |
82
+ | `class="w-full"` (non-numeric) | `width: Ti.UI.FILL` | skipped with a warning; no usable dim |
83
+
84
+ Note the spacing convention: PurgeTSS multiplies the Tailwind-style numeric scale, so `w-32` resolves to `width: 128` (128 dp), not 32.
85
+
86
+ ### Auto-derived dimensions stay out of config
87
+
88
+ If you used `h-auto` (or no `h-*`), the height field does **not** appear in the `images.files` entry. The generator re-derives it from the SVG's `viewBox` on every run. The same applies to width when only `h-*` is pinned. This keeps stale values out of `config.cjs` — the unpinned side stays `null` and is always recomputed from the current viewBox.
89
+
90
+ ## Multiple references to the same SVG
91
+
92
+ If two views reference the same SVG with different classes, the pipeline takes the **max of each dimension across all references**. The generated PNGs are then sharp enough for the largest use:
93
+
94
+ ```xml
95
+ <!-- view A -->
96
+ <ImageView class="w-32" image="/images/logos/logo.svg" />
97
+ <!-- view B -->
98
+ <ImageView class="w-(800)" image="/images/logos/logo.svg" />
99
+ ```
100
+
101
+ Resolved: `widthDp = 800`. The generated PNGs cover both views; the smaller one just downsamples at runtime.
102
+
103
+ ## How `config.cjs` is synced (autoSync ON)
104
+
105
+ After resolving dimensions, the pipeline upserts an entry in `images.files`:
106
+
107
+ ```javascript title="./purgetss/config.cjs"
108
+ images: {
109
+ autoSync: true,
110
+ files: [
111
+ { filename: 'images/logos/logo.svg', width: 176 }
112
+ ]
113
+ }
114
+ ```
115
+
116
+ ### The current run wins (v7.11.1 cascade policy)
117
+
118
+ Policy in plain terms: **the current run's cascade wins.** If you change `w-32` to `w-40`, the entry updates to `width: 160`. If you bump back to `w-32`, it updates back to `128`. On every run, the entry mirrors what the views ask for.
119
+
120
+ This is **not** a high-water mark. The old (pre-7.11.1) policy used `max(existing, derived)`, which froze sizes when you shrank a class — for example `h-52` → `h-16` kept the 208 dp height cemented in config. The 7.11.1 policy follows the cascade, so shrinks propagate correctly. Manual pinning is still available via `autoSync: false`.
121
+
122
+ ### Symmetric width/height cascade (v7.11.1)
123
+
124
+ `deriveDimensions` accepts width-only, height-only, or both. The unpinned side stays `null` in `images.files`, and `gen-scales` derives it from the SVG viewBox on every run — no more stale auto-derived heights cemented in config. For a height-only source, `gen-scales` computes the width from the inverse aspect ratio.
125
+
126
+ ### No gratuitous rewrites (v7.11.1)
127
+
128
+ If a run is byte-identical to the previous one (no inserts, no updates — `inserted === 0 && updated === 0`), `config.cjs` is **not** rewritten. Its `mtime` does not change, so downstream `utilities.tss` rebuilds are not triggered for nothing.
129
+
130
+ ### Manual mode: `autoSync: false`
131
+
132
+ ```javascript title="./purgetss/config.cjs"
133
+ images: {
134
+ autoSync: false,
135
+ files: [
136
+ { filename: 'images/logos/logo.svg', width: 1024 }
137
+ ]
138
+ }
139
+ ```
140
+
141
+ With `autoSync: false`:
142
+
143
+ - The pipeline still derives dimensions and generates PNGs, using the values you wrote in `images.files` — or the cascade fallback for files not listed.
144
+ - `config.cjs` is **never** written. Those entries are yours to maintain.
145
+
146
+ Use this when you want to pin sizes by hand and not have PurgeTSS overwrite your work.
147
+
148
+ ## Force-PNG output
149
+
150
+ The SVG pipeline **always emits `.png`**, regardless of `images.format`. This is deliberate:
151
+
152
+ 1. Titanium's `image="/foo.svg"` fallback resolves to `.png` only. `.webp`, `.jpeg`, and `.avif` are not picked up through the `.svg` reference.
153
+ 2. Having a sibling `.webp` (or any non-`.png`) next to `.png` on disk for the same basename **breaks the fallback entirely**. Titanium then shows nothing.
154
+
155
+ So even if you set `format: 'webp'` (which is honored by `purgetss images` for raster sources and unlisted SVGs), the post-purge pipeline emits `.png` for every SVG it processes. The `--debug` output line reads `png (forced; ignores format: webp)`.
156
+
157
+ If you genuinely want a `.webp` of an SVG, reference it as `image="/.../foo.webp"` in your XML, not as `.svg`. The standalone `purgetss images` command will then generate `.webp` for that file. See the [WebP and SVG warning](./multi-density-images.md) in the multi-density reference.
158
+
159
+ ## The PNG cache
160
+
161
+ PurgeTSS keeps a cache at `purgetss/.cache/svg-images.json`:
162
+
163
+ ```json
164
+ {
165
+ "logos/logo.svg": {
166
+ "svgHash": "<sha1>",
167
+ "widthDp": 176,
168
+ "heightDp": null,
169
+ "targets": [
170
+ "app/assets/android/images/res-mdpi/logos/logo.png",
171
+ "app/assets/iphone/images/logos/logo@2x.png",
172
+ "..."
173
+ ]
174
+ }
175
+ }
176
+ ```
177
+
178
+ A cached entry is reused, and Sharp is **not** invoked, when all of these hold:
179
+
180
+ - The SVG's bytes haven't changed (SHA-1 match).
181
+ - `widthDp` resolved is the same as cached.
182
+ - `heightDp` resolved is the same as cached.
183
+ - Every target PNG path matches and exists on disk.
184
+
185
+ Otherwise, PurgeTSS regenerates the image. If you `git clean`, delete a PNG by hand, or change a class in XML/JS, the next run regenerates only the affected SVGs. Unaffected entries stay cached.
186
+
187
+ > **Add `purgetss/.cache/` to `.gitignore`.** It is a per-machine artifact.
188
+
189
+ ## Manual pinning for undetected references
190
+
191
+ When the static scanner cannot see a reference (dynamic/concatenated paths) or a view has no resolvable `w-*` / `h-*` class, pin the entry by hand so the pipeline still generates the PNGs:
192
+
193
+ ```javascript title="./purgetss/config.cjs"
194
+ images: {
195
+ files: [
196
+ { filename: 'images/<sub>/<name>.svg', width: 256 }
197
+ ]
198
+ }
199
+ ```
200
+
201
+ ## Standalone command vs post-purge pipeline
202
+
203
+ | Aspect | `purgetss` (post-purge SVG pipeline) | `purgetss images` (standalone) |
204
+ | ----------------------- | ------------------------------------ | ------------------------------------------------- |
205
+ | What it processes | Only SVGs referenced from XML/JS | All files under `purgetss/images/` |
206
+ | Source of dimensions | Class cascade in `app.tss` | CLI `--width` > `images.files` > viewBox / source |
207
+ | Touches `images.files`? | Yes (autoSync ON) | No; only reads it as overrides |
208
+ | Output format for SVGs | Always PNG | PNG for SVGs in `files`; `format` otherwise |
209
+ | When to run | Automatic on every `purgetss` | Manual, after raster source edits |
210
+
211
+ Both share the same `images.files` array and the same generation engine (`gen-scales`). They do not fight each other: the pipeline edits `images.files`; the standalone command reads it as overrides. Run either, or both.
212
+
213
+ ## Troubleshooting
214
+
215
+ ### "no class resolved width or height to a number; skipping"
216
+
217
+ The SVG is referenced from a view with no resolvable `w-*` or `h-*` class (just `w-full`, `w-screen`, `bg-*`, etc.). Add a numeric `w-*` or `h-*` utility, or pin the size manually in `images.files`:
218
+
219
+ ```javascript
220
+ files: [
221
+ { filename: 'images/<sub>/<name>.svg', width: 256 }
222
+ ]
223
+ ```
224
+
225
+ ### My change to a class didn't update the PNG
226
+
227
+ Check that the class actually exists in `app.tss` after purging. The Tailwind-style spacing scale skips numbers like `h-50`; only `h-48`, `h-52`, `h-56` are emitted by default. Add custom values under `theme.extend.spacing` if you need them, or use arbitrary values: `h-(50)`, `h-(200px)`, `h-(12.5rem)`.
228
+
229
+ If the class is correct but the image didn't refresh on device, it might be the Titanium simulator's image cache. Do a clean build.
230
+
231
+ ### The pipeline didn't detect my SVG reference
232
+
233
+ The static scanner sees literal string values, not computed paths. Concatenated strings (`'/images/' + variant + '.svg'`) are not detected. Pin the entry in `images.files` manually so the pipeline still generates the PNGs.
234
+
235
+ ### `<ImageView image="/.../foo.svg" />` shows nothing
236
+
237
+ Two common causes:
238
+
239
+ 1. There is no `.png` next to the `.svg`. Titanium falls back from `.svg` references to `.png` siblings; if the pipeline hasn't generated them yet, the fallback can't fire. Run `purgetss` (or `purgetss images`) and verify the `.png` exists under `app/assets/iphone/images/` and `app/assets/android/images/res-*/`.
240
+ 2. Both `.png` and `.webp` (or another non-png) sit next to each other for the same basename. That breaks the fallback entirely. Delete the non-`.png` siblings, or let the force-PNG pipeline own the SVG.
241
+
242
+ ### I want to opt out for a specific run
243
+
244
+ Switch `autoSync: false` and manage the `images.files` entries yourself, or delete the SVG cache entry. The pipeline still derives dimensions and generates the PNGs so views keep working, but it does not write to `config.cjs`.
245
+
246
+ ## See also
247
+
248
+ - [Multi-density images](./multi-density-images.md) — the standalone `purgetss images` command, `--width`, format conversion, and `images.files` overrides.
249
+ - [PurgeTSS Configuration Deep Dive](./customization-deep-dive.md) — the `images:` config block and the config syntax validator.
@@ -316,7 +316,7 @@ Colors: `black`, `dark`, `light`, and `white` themes that affect background and
316
316
 
317
317
  Use this for code examples. Set `copy="true"` to add a copy button.
318
318
 
319
- **Pro tip — recommended monospace fonts:** For best results, install a monospaced font (like Fira Code or JetBrains Mono) and configure `font-mono` in your PurgeTSS config. (Source: official tikit docs, `tikit.md` line ~390.)
319
+ **Pro tip — recommended monospace fonts:** For best results, install a monospaced font (like Fira Code or JetBrains Mono) and configure `font-mono` in your PurgeTSS config. (Source: the official tikit docs.)
320
320
 
321
321
  **Localization:** The copy button uses `L('copy', 'Copy')` for its title and `L('code_copied', 'Code copied!')` for the confirmation message. Add these keys to your `strings.xml` files for translation.
322
322
 
@@ -512,4 +512,4 @@ You can mix and match icons from different libraries throughout your app.
512
512
 
513
513
  ## License
514
514
 
515
- TiKit UI Components is open source under the MIT License (Copyright 2023-2025 Cesar Estrada).
515
+ TiKit UI Components is open source under the MIT License (Copyright (c) 2023-2025 César Estrada).
@@ -30,7 +30,7 @@ The most important reset is for the `View` element. By default, `View` is set to
30
30
  - Grow to accommodate explicit dimensions (`w-64`, `h-32`, etc.)
31
31
  - Expand to fill margins (`m-4`, `mx-2`, `mt-6 mb-4`, etc.)
32
32
 
33
- > **See also**: the "Explicit SIZE vs native undefined" callout under [Community-Discovered Patterns](#community-discovered-patterns) explains when to use `h-auto`, `w-auto`, and `wh-auto` to prevent unwanted stretching.
33
+ > **See also**: [Width/Height Inheritance](#widthheight-inheritance) explains when to use `h-auto`, `w-auto`, and `wh-auto` to prevent unwanted stretching.
34
34
 
35
35
  ### Practical Examples
36
36
 
@@ -264,7 +264,7 @@ This generates classes for ALL color properties:
264
264
  When PurgeTSS generates your `app.tss`, these resets appear first:
265
265
 
266
266
  ```tss
267
- /* PurgeTSS v7.6.0 */
267
+ /* PurgeTSS v7.11.1 */
268
268
  /* Created by César Estrada */
269
269
  /* https://purgetss.com */
270
270
 
@@ -75,7 +75,8 @@ The catalog below collects real-world UI patterns verified against Titanium's co
75
75
  ```xml
76
76
  <View class="horizontal border-b border-gray-200 bg-white">
77
77
  <View class="ml-4 my-4 rounded-full-12 bg-blue-500">
78
- <Label class="center text-lg font-bold text-white" text="JD" />
78
+ <!-- A child with no top/left centers itself in a composite parent -->
79
+ <Label class="text-lg font-bold text-white" text="JD" />
79
80
  </View>
80
81
 
81
82
  <View class="vertical ml-3 my-4">
@@ -93,7 +94,7 @@ The catalog below collects real-world UI patterns verified against Titanium's co
93
94
  <ItemTemplate name="cardTemplate" class="h-20">
94
95
  <View bindId="container" class="horizontal mx-4 my-2 rounded-lg bg-white shadow-lg">
95
96
  <View bindId="iconWrap" class="ml-4 my-4 rounded-full-10 bg-blue-100">
96
- <Label bindId="icon" class="center fas fa-home text-blue-500" />
97
+ <Label bindId="icon" class="fas fa-home text-blue-500" />
97
98
  </View>
98
99
 
99
100
  <View class="vertical ml-3 my-4">
@@ -190,8 +191,9 @@ For an icon-with-text pair, use a horizontal `View` containing an icon `Label` a
190
191
 
191
192
  ```xml
192
193
  <View class="h-14 w-screen bg-white border-b border-gray-200">
193
- <Label class="left-4 center text-lg font-bold text-gray-800" text="Dashboard" />
194
- <Label class="right-4 center fas fa-bars text-gray-700" />
194
+ <!-- Omitting top/bottom lets each child center vertically in the composite bar -->
195
+ <Label class="left-4 text-lg font-bold text-gray-800" text="Dashboard" />
196
+ <Label class="right-4 fas fa-bars text-gray-700" />
195
197
  </View>
196
198
  ```
197
199
 
@@ -267,7 +269,7 @@ For an icon-with-text pair, use a horizontal `View` containing an icon `Label` a
267
269
  <Window class="bg-gray-100">
268
270
  <View class="vertical h-screen w-screen">
269
271
  <View class="h-14 w-screen border-b border-gray-200 bg-white">
270
- <Label class="left-4 center text-xl font-bold text-gray-800" text="Screen Title" />
272
+ <Label class="left-4 text-xl font-bold text-gray-800" text="Screen Title" />
271
273
  </View>
272
274
 
273
275
  <ScrollView class="vertical content-w-screen content-h-auto">
@@ -1,82 +1,71 @@
1
- # PurgeTSS — Version History
2
-
3
- Release-by-release feature additions and behavior changes. The current behavior of PurgeTSS is documented in the main `SKILL.md` and its reference files; this page is the historical record.
4
-
5
- ## What's New in v7.10.2
6
-
7
- - **Pre-7.7.0 brand config auto-migration.** Configs written before v7.7.0 (the `brand:` regroup) now auto-migrate in memory on every run. The legacy flat layout (`brand.padding: <number>`, `brand.iosPadding`, `brand.bgColor`, `brand.darkBgColor`, top-level `brand.notification` / `brand.splash`) used to crash auto-purge with `TypeError: Cannot create property 'ios' on number '15'`. `getConfigFile()` now normalizes legacy keys to the grouped layout (`brand.padding.{ios, androidLegacy, androidAdaptive}`, `brand.android.*`, `brand.ios.darkBackground`, `brand.colors.background`) before applying defaults. When both legacy and new keys coexist, the new key wins. A one-time deprecation notice per session lists the migrated keys. See [App Icons & Branding → Upgrading from pre-7.7.0 configs](app-branding.md).
8
- - **Internal logger fix.** `logger.warning` and `logger.success` are now defined. Across `brand`, `images`, `cleanup-legacy`, and `svg-utils`, ~30 callsites of `logger.warning` and ~10 of `logger.success` referenced methods that did not exist on the logger object — any opt-in command path that hit one used to throw `TypeError: logger.warning is not a function`. The auto-purge entry point most users hit did not reach those callsites, so the bug stayed latent until commands like `purgetss brand` or `purgetss images` were run.
9
-
10
- ## What's New in v7.10.1
11
-
12
- - **"Tailwind" framing dropped from copy that did not document a functional integration.** The Class Syntax Error block now reports `'Square brackets "[ ]" are not supported'` instead of `'Tailwind-style brackets "[ ]" are not supported'`. The promotional `<Label>` injected into new projects by `purgetss create` changed from `"Tailwind-inspired utility classes for Titanium/Alloy"` to `"Utility-first styling for Titanium/Alloy"`.
13
- - **Functional integrations stay.** The `tailwindcss@3` dependency installed by `install-dependencies` (drives both the `defaultColors` / `defaultTheme` palette base AND the VSCode IntelliSense extension) still ships. The `--tailwind` flag on `purgetss shades` and the recommended `Tailwind CSS IntelliSense` / `Tailwind Raw Reorder (v4)` VSCode extensions are unchanged.
14
-
15
- ## What's New in v7.10.0
16
-
17
- - **`purgetss images` got three CLI-only flags.**
18
- - `--opacity <n>` (integer `0-100`) multiplies the alpha channel of every generated density by `n/100` useful for placeholder or default ImageView images that render at reduced opacity (loading states, watermarks). With `--format jpeg`, the JPEG flatten-on-white step composites the semi-transparent image onto white instead of producing transparent JPEGs (JPEG has no alpha).
19
- - `--padding <n>` (integer `0-40`) shrinks the rendered image inside each density canvas by symmetric percentage borders, preserving canvas size with transparent fill useful for breathing room around an unpadded logo.
20
- - `--output <relpath>` overrides the basename and subpath relative to each platform's `images/` root, so a logo from `purgetss/brand/` can be written as `images/logos/loading.png` across all densities in a single command.
21
- - The three flags combine naturally for "transparent placeholder with padding under a custom path". See [Multi-Density Images](multi-density-images.md).
22
- - **`purgetss brand` now generates `MarketplaceArtworkFeature.png` (1024×500 Google Play Feature Graphic)** alongside the existing iTunesConnect and MarketplaceArtwork submission assets. Auto-discovers `purgetss/brand/logo-feature.{svg,png}` or reuses the master logo if not provided. Default vertical padding is `12%`; override with `--feature-graphic-padding <n>` (range `0-40`), config `brand.padding.featureGraphic`, or CLI `--feature-logo <path>` for a dedicated source. Submission artwork only — written to project root for upload to the Play Console, not bundled into the APK. See [App Icons & Branding](app-branding.md).
23
- - **Arbitrary nesting depth in `config.cjs` `theme` objects.** Property emission now walks nested values recursively instead of stopping at level 2, so `theme.extend.colors.brand.primary.500` flattens to `brand-primary-500` instead of being silently dropped. Same for `backgroundGradient` and `backgroundSelectedGradient`. Default modifier keys (`default`, `global`, `DEFAULT`) collapse without contributing to the suffix. See [Arbitrary Values](arbitrary-values.md).
24
- - **Fix:** `apply:` now resolves built-in icon font classes (`fas`, `fab`, `fa-*`, `mi-*`, `ms-*`, `f7-*`) from `dist/` for projects that don't run `build-fonts`. Previously those classes were silently dropped from generated rules — `apply: 'fas fa-times-circle wh-12 ...'` produced everything except the FontAwesome family and the icon glyph. See [Apply Directive → Use icon font classes](apply-directive.md).
25
- - **Fix:** `borderRadius: [...]` arrays no longer get truncated when combined with other utilities in an `apply:` string. The post-merge dedup step (from v7.9.0) tracked depth on `{}` only, so `borderRadius: [0, 0, 0, 16]` (emitted by directional `rounded-{t,b,l,r,tl,tr,bl,br}-*` utilities) was split on its internal commas. The depth tracker now respects `[]` alongside `{}`.
26
- - **Fix:** `brand --padding <n>` shortcut now applies to BOTH Android paddings as the help text always promised. Previously the shortcut only fed `androidAdaptivePadding` while `androidLegacyPadding` fell through to its own config value, so `purgetss brand --padding 17` actually produced `androidAdaptive=17, androidLegacy=10`.
27
-
28
- ## What's New in v7.9.0
29
-
30
- - Opacity modifier on semantic colors `bg-surface/65` syntax now works for any class mapped through `theme.extend.colors`. PurgeTSS auto-derives `<originalKey>_<alphaPercent>` entries in `semantic.colors.json` per mode (light/dark). See [Semantic Colors → Opacity modifier auto-derivation](semantic-colors.md#opacity-modifier-auto-derivation). **Native rebuild required** — Liveview hot-reload alone does not refresh `semantic.colors.json`
31
- - `theme.Window` / `theme.View` / `theme.ImageView` presets now use **replace mode** — they no longer carry framework defaults (white background, `Ti.UI.SIZE`, iOS `hires: true`). This fixes gradient ghosting where a preset Window with `bg-gradient-*` apply was being covered by the implicit `backgroundColor: '#FFFFFF'`. Use `theme.extend.Window` / `theme.extend.View` / `theme.extend.ImageView` when you want **extend mode** (merge with defaults). See [Apply Directive → Extend mode vs replace mode](apply-directive.md#extend-mode-vs-replace-mode)
32
- - Glossary path renamed: `purgetss/experimental/tailwind-classes/` `purgetss/glossary/tailwind-classes/`
33
-
34
- ## What's New in v7.8.0
35
-
36
- - `purgetss images --width <n>` — pin SVG output to a specific base width; PurgeTSS derives per-density assets from the multiplier scale (×1 / ×1.5 / ×2 / ×3 / ×4). Range `[1, 8192]`. CLI-only (no `images:` config equivalent — width is per-asset). See [Multi-Density Images → Pinning the output width with --width](multi-density-images.md#pinning-the-output-width-with---width)
37
- - Class syntax pre-validation the build now emits a `Class Syntax Error` block (file path + line + `Fix:` suggestion) for 5 detected patterns: inverted negative sign (`top-(-10)` → `-top-(10)`), Tailwind brackets (`top-[10px]` `top-(10px)`), empty parens (`wh-()`), whitespace inside parens (`wh-( 200 )` → `wh-(200)`), redundant `px` unit (`top-(10px)` `top-(10)`). See [Arbitrary Values → Class syntax pre-validation](arbitrary-values.md#class-syntax-pre-validation)
38
- - Parser fix for negative values inside parentheses `top-(-10)` is now correctly flagged as inverted-negative-sign instead of silently misparsed
39
-
40
- ## What's New in v7.7.0
41
-
42
- - `brand:` config restructured flat keys replaced by purpose-based groups: `brand.logos`, `brand.padding`, `brand.android`, `brand.ios`, `brand.colors`
43
- - Separate Android brand inputs `logos.androidLauncher` / `--icon-logo` for Android launcher icons; `logos.androidSplash` / `--splash-logo` for Android 12+ splash artwork. Drop `logo-icon.*` and `logo-splash.*` into `purgetss/brand/`
44
- - `--android-adaptive-padding` (default `19%`) and `--android-legacy-padding` (default `10%`) replace the single `--padding`. The shortcut `--padding` now sets both Android paddings to the same value for one run
45
- - Legacy Android splash fallback regenerated — `app/assets/android/default.png` (Alloy) or `Resources/android/default.png` (Classic). `cleanup-legacy` no longer removes `default.png`
46
- - New official doc: [Values and Units](values-and-units.md) explains `ti.ui.defaultunit` interpretation of PurgeTSS unitless values
47
-
48
- ## What's New in v7.6.x
49
-
50
- - `brand` command — complete Titanium branding set (launcher icons, adaptive, iOS 18+ Dark/Tinted, marketplace) from logos in `./purgetss/brand/` (v7.6.0)
51
- - `images` command — multi-density UI images (Android res-*dpi + iPhone @1x/@2x/@3x) from `./purgetss/images/` (v7.6.0)
52
- - `semantic` command — Titanium semantic colors for Light/Dark mode (palette mode + single mode) (v7.6.0)
53
- - `brand:` and `images:` config sections auto-injected into older configs (v7.6.0)
54
- - Percentages as strings (`'15%'`) for self-documenting clarity in brand/images configs (v7.6.0)
55
- - Confirmation prompt for destructive writes in `brand` / `images` (`y` / `N` / `a`); auto-skipped on non-TTY, with `-y`, or `PURGETSS_YES=1` (v7.6.1)
56
- - `semantic` command works in Classic projects writes to `Resources/semantic.colors.json` (v7.6.2)
57
-
58
- ## What's New in v7.5.3
59
-
60
- - Appearance module Light/Dark/System mode switching with persistence
61
- - Default font family classes (`font-sans`, `font-serif`, `font-mono`) generated automatically with platform-appropriate values
62
- - XML validation — detects illegal `--` inside XML comments during pre-validation
63
-
64
- ## What's New in v7.5.0
65
-
66
- - `extend` support for Window, View, and ImageView in `config.cjs`
67
- - Shorthand `apply` directive normalization
68
- - Apply directive property deduplication
69
- - Automatic platform resolution in apply directives
70
- - Updated Font Awesome to 7.2.0
71
- - Fixed: `extend.Window` was silently ignored
72
- - Fixed: Array-type properties (`extendEdges`, `mediaTypes`) bracket notation
73
-
74
- ## What's New in v7.4.0
75
-
76
- - 9 new Animation methods: `transition`, `pulse`, `sequence`, `swap`, `shake`, `snapTo`, `reorder`, `undraggable`, `detectCollisions` (module now has 15 methods total)
77
- - Snap behavior classes: `snap-back`, `snap-center`, `snap-magnet`
78
- - `keep-z-index` utility class
79
- - Enriched callback event object with `action`, `state`, `id`, `targetId`, `index`, `total`, `getTarget()`
80
- - Delta-based drag for views with rotate/scale transforms
81
- - Position normalization for draggable views
82
- - Property inheritance from Animation object for all new methods
1
+ # PurgeTSS — Version History (agent summary)
2
+
3
+ Terse, agent-facing summary of changes that affect how the skill suggests utilities, configures `config.cjs`, or invokes commands. **Not** a full changelog.
4
+
5
+ **Canonical source:** <https://purgetss.com/changelog> (full release notes, internal fixes, parser changes, dependency bumps).
6
+
7
+ When in doubt about whether a class, flag, or config key exists in the user's installed version, consult the canonical changelog or grep `./purgetss/styles/utilities.tss` in the project.
8
+
9
+ ---
10
+
11
+ ## v7.11.1
12
+ - Symmetric width/height cascade in the SVG image pipeline: a class can pin width-only, height-only, or both; the unpinned side stays `null` in `images.files` and is re-derived from the SVG viewBox on every run (no stale auto-derived dimensions frozen in config).
13
+ - `syncConfigImages` mirrors the **current** run instead of taking `max()` across past runs shrinking a class (e.g. `h-52` `h-16`) now propagates to `config.cjs`. Pin manually with `images.autoSync: false`.
14
+ - Fix: `purgetss images` respects `--yes` for overwrite confirmations (prompt no longer reappears).
15
+ - Fix: SVGs listed in `images.files` always emit `.png` regardless of `images.format` (Titanium's `.svg → .png`-only runtime fallback). Raster files and SVGs not in `images.files` still honor `format`.
16
+
17
+ ## v7.11.0
18
+ - SVG-aware compile-time image pipeline runs as a `purgetss` post-step. When XML/controllers reference `image="/images/x.svg"` (or `backgroundImage`) alongside utility classes that resolve to numeric width/height (`w-32`, `w-(300)`, `h-auto`), purge compiles the SVG into the 8 Titanium density PNGs (5 Android + 3 iPhone) using dimensions resolved from `app.tss`. Titanium loads the generated `.png` at runtime; the `.svg` attribute in your source is never rewritten. Cache: `purgetss/.cache/svg-images.json` (add to `.gitignore`). See [multi-density-images.md](multi-density-images.md).
19
+ - `images.files` array in `config.cjs` — per-file width/height override: `[{ filename: 'images/logos/logo.png', width: 128, height: 52 }]`. CLI `--width` still wins over entries. SVGs detected by the pipeline populate entries automatically (subject to `images.autoSync`); hand-added raster entries survive untouched.
20
+ - `images.autoSync` boolean (default `true`) opt-out for devs managing `images.files` by hand. When `false`, purge still computes dimensions and generates PNGs but never writes back to `config.cjs`.
21
+ - `config.cjs` syntax validator emits a formatted `Config Syntax Error` block (file, JSON path, context, issue, fix snippet) for type mismatches in known fields, currently `theme.fontFamily.*` — must be a **string** — replacing cryptic crashes like `rule.startsWith is not a function`.
22
+
23
+ ## v7.10.2
24
+ - Pre-v7.7.0 `brand:` configs (flat layout: `brand.padding: <number>`, `brand.iosPadding`, `brand.bgColor`, top-level `brand.notification`/`brand.splash`) auto-migrate to the grouped layout in memory. A one-time per-session notice lists the migrated keys.
25
+
26
+ ## v7.10.1
27
+ - "Tailwind" framing dropped from non-functional copy (Class Syntax Error message, `purgetss create` injected Label). Functional integrations (`tailwindcss@3` dep, `shades --tailwind`, VSCode IntelliSense extension) still ship.
28
+
29
+ ## v7.10.0
30
+ - `purgetss images` gains `--opacity <0-100>`, `--padding <0-40>`, `--output <relpath>`. CLI-only (no `config.cjs` equivalent). See [multi-density-images.md](multi-density-images.md).
31
+ - `purgetss brand` generates `MarketplaceArtworkFeature.png` (1024×500 Google Play Feature Graphic). Override via `--feature-logo <path>` or `--feature-graphic-padding <n>` (default 12%). See [app-branding.md](app-branding.md).
32
+ - `theme` objects in `config.cjs` walk recursively at any depth — `theme.extend.colors.brand.primary.500` flattens to class `bg-brand-primary-500`. Default modifier keys (`default`, `global`, `DEFAULT`) collapse. Same for `backgroundGradient` / `backgroundSelectedGradient`. See [arbitrary-values.md](arbitrary-values.md).
33
+ - Fix: `apply:` now resolves built-in icon font classes (`fas`, `fab`, `fa-*`, `mi-*`, `ms-*`, `f7-*`) from `dist/` even without `build-fonts`.
34
+ - Fix: `brand --padding <n>` shortcut applies to BOTH Android paddings.
35
+
36
+ ## v7.9.0
37
+ - Opacity modifiers work on semantic colors: `bg-surface/65` auto-derives `surface_65` in `semantic.colors.json` with light/dark + alpha. **Native rebuild required** (Liveview alone does not refresh `semantic.colors.json`). See [semantic-colors.md](semantic-colors.md).
38
+ - `theme.Window` / `theme.View` / `theme.ImageView` at top level = **replace mode** (no framework defaults). Use `theme.extend.Window` for **extend mode** (merge with defaults). See [apply-directive.md](apply-directive.md).
39
+ - **Breaking:** glossary path renamed `purgetss/experimental/tailwind-classes/` → `purgetss/glossary/tailwind-classes/`. No transition shim.
40
+
41
+ ## v7.8.0
42
+ - `purgetss images --width <n>` pins Android `mdpi` / iPhone `@1x` to `<n>` pixels for SVG sources with disproportionate viewBoxes (Affinity, Illustrator). CLI-only.
43
+ - Class syntax pre-validation emits `Class Syntax Error` blocks for 5 patterns: inverted negative (`top-(-10)` `-top-(10)`), brackets (`top-[10px]` `top-(10px)`), empty parens (`wh-()`), whitespace in parens, redundant `px` unit. Generic unknown classes still flow into `// Unused or unsupported classes`.
44
+
45
+ ## v7.7.0
46
+ - `brand:` config restructured into grouped sections: `brand.logos`, `brand.padding`, `brand.android`, `brand.ios`, `brand.colors`. Old projects keep working; new configs use grouped form. See [app-branding.md](app-branding.md).
47
+ - Separate Android brand inputs: `logos.androidLauncher` / `--icon-logo` and `logos.androidSplash` / `--splash-logo`.
48
+ - Android splash fallback `default.png` regenerated (Alloy: `app/assets/android/`, Classic: `Resources/android/`). `cleanup-legacy` preserves it.
49
+ - New ref: [values-and-units.md](values-and-units.md) — `ti.ui.defaultunit` interpretation of unitless PurgeTSS values.
50
+
51
+ ## v7.6.x
52
+ - `purgetss brand` (v7.6.0)full Titanium branding set from `purgetss/brand/` logos. See [app-branding.md](app-branding.md).
53
+ - `purgetss images` (v7.6.0) multi-density UI images (Android `res-*` + iPhone `@1x`/`@2x`/`@3x`). See [multi-density-images.md](multi-density-images.md).
54
+ - `purgetss semantic` (v7.6.0) — Titanium semantic colors for Light/Dark, palette mode or `--single` purpose-based. Classic projects supported since v7.6.2. See [semantic-colors.md](semantic-colors.md).
55
+ - `brand:` and `images:` config sections auto-injected. Percentages may be quoted strings (`'15%'`) or plain numbers.
56
+ - `brand` / `images` ask `[y/N/a]` before overwriting (skip with `-y`, `PURGETSS_YES=1`, or non-TTY) (v7.6.1).
57
+
58
+ ## v7.5.3
59
+ - `Appearance` module — Light/Dark/System mode switching with persistence (`init()`, `set()`, `get()`, `toggle()`). See [appearance-module.md](appearance-module.md).
60
+ - Default font family classes (`font-sans`, `font-serif`, `font-mono`) auto-generated with platform-appropriate values.
61
+
62
+ ## v7.5.0
63
+ - `theme.extend.Window` / `theme.extend.View` / `theme.extend.ImageView` — customize Ti element defaults.
64
+ - Shorthand `apply:` directive — `{ apply: '...' }` auto-normalizes; `default:` wrapper optional.
65
+ - Apply directive property deduplication — applied values win over static defaults.
66
+ - Automatic platform resolution inside `ios:` / `android:` blocks.
67
+
68
+ ## v7.4.0
69
+ - Animation module: 9 new methods (`transition`, `pulse`, `sequence`, `swap`, `shake`, `snapTo`, `reorder`, `undraggable`, `detectCollisions`). 15 methods total. See [animation-system.md](animation-system.md).
70
+ - New utility classes: `snap-back`, `snap-center`, `snap-magnet`, `keep-z-index`.
71
+ - Delta-based drag for transformed views; property inheritance from Animation object.