@maccesar/titools 3.1.0 → 3.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maccesar/titools",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "Titanium SDK skills and agents for AI coding assistants (Claude Code, Gemini CLI, Codex CLI)",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: purgetss
3
- description: "Titanium PurgeTSS utility-first styling toolkit. Use when styling, reviewing, analyzing, or examining Titanium UI with utility classes, configuring config.cjs, creating dynamic components with $.UI.create(), building animations, using grid layouts, setting up icon fonts, or working with TSS styles. AUTO-DETECT: If purgetss/ folder or purgetss/config.cjs exists, this project uses PurgeTSS — invoke this skill BEFORE writing ANY styling code. All styling MUST use PurgeTSS utility classes in XML, NOT custom TSS. PurgeTSS classes look like Tailwind but are NOT Tailwind — verify every class exists before using it. Never use padding on Views (use margins on children), never use flexbox classes, never write manual TSS when a utility class exists."
3
+ description: "Use when working with PurgeTSS, Titanium's utility-first styling toolkit styling, reviewing, analyzing, or examining Titanium UI with utility classes, configuring config.cjs, creating dynamic components with $.UI.create(), building animations, grid layouts, icon fonts, or TSS styles. AUTO-DETECT: If purgetss/ folder or purgetss/config.cjs exists, invoke BEFORE writing ANY styling code. PurgeTSS classes look like Tailwind but are NOT Tailwind — verify every class exists. Never use padding on Views (use margins on children), never use flexbox classes, never write manual TSS when a utility class exists."
4
4
  argument-hint: "[class-name]"
5
5
  allowed-tools: Read, Grep, Glob, Edit, Write, Bash(purgetss *), Bash(node *)
6
6
  ---
@@ -9,6 +9,46 @@ allowed-tools: Read, Grep, Glob, Edit, Write, Bash(purgetss *), Bash(node *)
9
9
 
10
10
  Utility-first styling toolkit for Titanium/Alloy mobile apps.
11
11
 
12
+ ## Required workflow (read before responding)
13
+
14
+ The SKILL.md alone is an **index** of references. The detail you need
15
+ to give accurate answers lives in the reference files. **Reading this
16
+ SKILL.md is not enough.**
17
+
18
+ ### Step 1 — Open the relevant reference files
19
+
20
+ | Task involves | Required reading |
21
+ |---|---|
22
+ | Choosing utility classes | [references/class-index.md](references/class-index.md) |
23
+ | Layout (horizontal/vertical/composite, grid) | [references/grid-layout.md](references/grid-layout.md), [references/ui-ux-design.md](references/ui-ux-design.md) |
24
+ | Dynamic components in controllers | [references/dynamic-component-creation.md](references/dynamic-component-creation.md) |
25
+ | Custom values / arbitrary syntax | [references/arbitrary-values.md](references/arbitrary-values.md) |
26
+ | Platform-specific styles (`ios:`, `android:`) | [references/platform-modifiers.md](references/platform-modifiers.md) |
27
+ | Dark/Light mode | [references/semantic-colors.md](references/semantic-colors.md), [references/appearance-module.md](references/appearance-module.md) |
28
+ | Apply directive / class extraction | [references/apply-directive.md](references/apply-directive.md) |
29
+ | Animations | [references/animation-system.md](references/animation-system.md) |
30
+
31
+ ### Step 2 — Output contract
32
+
33
+ Every utility class you suggest and every styling pattern you describe
34
+ MUST be backed by a citation in the form:
35
+
36
+ `[source: references/<file>.md]`
37
+
38
+ Example: *"Use `wh-12` to set width and height to 48px [source: references/class-index.md]"*
39
+
40
+ ### Step 3 — If you must answer from memory
41
+
42
+ If you write a claim without having read the reference that backs it,
43
+ prepend `FROM_MEMORY (unverified):` to that claim. Do not hide it.
44
+
45
+ ### Banned behaviors
46
+
47
+ - ❌ Writing utility classes "from memory" without citing any reference
48
+ - ❌ Confusing PurgeTSS classes with Tailwind — they share naming but differ
49
+ - ❌ Marking the answer complete without listing which reference files you read
50
+ - ❌ Suggesting a class without first verifying it exists in `class-index.md`
51
+
12
52
  ## Project Detection
13
53
 
14
54
  > **️ℹ️ AUTO-DETECTS PURGETSS PROJECTS**
@@ -112,62 +152,6 @@ purgetss create 'MyApp' -d -v fa
112
152
  # -v: Copy icon fonts (fa, mi, ms, f7)
113
153
  ```
114
154
 
115
- ## What's New in v7.9.0
116
-
117
- - 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](references/semantic-colors.md#opacity-modifier-auto-derivation). **Native rebuild required** — Liveview hot-reload alone does not refresh `semantic.colors.json`
118
- - `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](references/apply-directive.md#extend-mode-vs-replace-mode)
119
- - Glossary path renamed: `purgetss/experimental/tailwind-classes/` → `purgetss/glossary/tailwind-classes/`
120
-
121
- ## What's New in v7.8.0
122
-
123
- - `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](references/multi-density-images.md#pinning-the-output-width-with---width)
124
- - 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](references/arbitrary-values.md#class-syntax-pre-validation)
125
- - Parser fix for negative values inside parentheses — `top-(-10)` is now correctly flagged as inverted-negative-sign instead of silently misparsed
126
-
127
- ## What's New in v7.7.0
128
-
129
- - `brand:` config restructured — flat keys replaced by purpose-based groups: `brand.logos`, `brand.padding`, `brand.android`, `brand.ios`, `brand.colors`
130
- - 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/`
131
- - `--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
132
- - Legacy Android splash fallback regenerated — `app/assets/android/default.png` (Alloy) or `Resources/android/default.png` (Classic). `cleanup-legacy` no longer removes `default.png`
133
- - New official doc: [Values and Units](references/values-and-units.md) — explains `ti.ui.defaultunit` interpretation of PurgeTSS unitless values
134
-
135
- ## What's New in v7.6.x
136
-
137
- - `brand` command — complete Titanium branding set (launcher icons, adaptive, iOS 18+ Dark/Tinted, marketplace) from logos in `./purgetss/brand/` (v7.6.0)
138
- - `images` command — multi-density UI images (Android res-*dpi + iPhone @1x/@2x/@3x) from `./purgetss/images/` (v7.6.0)
139
- - `semantic` command — Titanium semantic colors for Light/Dark mode (palette mode + single mode) (v7.6.0)
140
- - `brand:` and `images:` config sections auto-injected into older configs (v7.6.0)
141
- - Percentages as strings (`'15%'`) for self-documenting clarity in brand/images configs (v7.6.0)
142
- - 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)
143
- - `semantic` command works in Classic projects — writes to `Resources/semantic.colors.json` (v7.6.2)
144
-
145
- ## What's New in v7.5.3
146
-
147
- - Appearance module — Light/Dark/System mode switching with persistence
148
- - Default font family classes (`font-sans`, `font-serif`, `font-mono`) generated automatically with platform-appropriate values
149
- - XML validation — detects illegal `--` inside XML comments during pre-validation
150
-
151
- ## What's New in v7.5.0
152
-
153
- - `extend` support for Window, View, and ImageView in `config.cjs`
154
- - Shorthand `apply` directive normalization
155
- - Apply directive property deduplication
156
- - Automatic platform resolution in apply directives
157
- - Updated Font Awesome to 7.2.0
158
- - Fixed: `extend.Window` was silently ignored
159
- - Fixed: Array-type properties (`extendEdges`, `mediaTypes`) bracket notation
160
-
161
- ## What's New in v7.4.0
162
-
163
- - 9 new Animation methods: `transition`, `pulse`, `sequence`, `swap`, `shake`, `snapTo`, `reorder`, `undraggable`, `detectCollisions` (module now has 15 methods total)
164
- - Snap behavior classes: `snap-back`, `snap-center`, `snap-magnet`
165
- - `keep-z-index` utility class
166
- - Enriched callback event object with `action`, `state`, `id`, `targetId`, `index`, `total`, `getTarget()`
167
- - Delta-based drag for views with rotate/scale transforms
168
- - Position normalization for draggable views
169
- - Property inheritance from Animation object for all new methods
170
-
171
155
  > **💡 NEW PROJECT: Clean Up Default app.tss**
172
156
  > For new projects created with `purgetss create`, the default `app/styles/app.tss` contains a large commented template.
173
157
  >
@@ -460,6 +444,9 @@ purgetss create 'MyApp' -d -v fa
460
444
  > - [Animation System](references/animation-system.md) - 15 methods including collision detection, transitions, and sequential animations
461
445
  > - [Animation Advanced](references/animation-advanced.md) - Property inheritance, utility classes, implementation rules, complex UI example
462
446
  >
447
+ > ### Release Notes
448
+ > - [Version History](references/version-history.md) - Release-by-release feature additions and behavior changes (v7.4.0 → v7.9.0)
449
+ >
463
450
  > **💡 TEXT FONTS (Google Fonts, Roboto, etc.)**
464
451
  > For text fonts, see [CLI Commands → build-fonts](references/cli-commands.md#purgetss-build-fonts-alias-bf).
465
452
  >
@@ -272,7 +272,7 @@ alloy compile
272
272
 
273
273
  ### Square Brackets for Arbitrary Values
274
274
 
275
- **❌ WRONG (Using square brackets like Tailwind CSS):**
275
+ **❌ WRONG (Square brackets are not supported):**
276
276
  ```xml
277
277
  <View class="w-[100px] bg-[#ff0000]" />
278
278
  ```
@@ -284,6 +284,13 @@ alloy compile
284
284
 
285
285
  **PurgeTSS syntax for arbitrary values uses `()` not `[]`.**
286
286
 
287
+ > **🚨 v7.8.0+ HARD-FAILS THE BUILD ON SQUARE BRACKETS**
288
+ > Since v7.8.0, the build stops with a structured `Class Syntax Error` block (file path + line number + `Fix:` suggestion) the moment it spots `top-[10px]`, `wh-[12]`, or any other square-bracket utility. Pre-v7.8.0, those classes silently dropped into the `// Unused or unsupported classes` block of `app.tss` — easy to miss. Now they're loud and actionable.
289
+ >
290
+ > v7.10.1 reworded the error message from `'Tailwind-style brackets "[ ]" are not supported'` to `'Square brackets "[ ]" are not supported'`. Same enforcement, less framing.
291
+ >
292
+ > See [Arbitrary Values → Class syntax pre-validation](arbitrary-values.md#class-syntax-pre-validation) for the full list of patterns the pre-validator catches (5 total, including inverted negative sign and whitespace inside parentheses).
293
+
287
294
  **Examples:**
288
295
  - `w-(100px)` - Custom width
289
296
  - `bg-(#ff0000)` - Custom background color
@@ -1,6 +1,6 @@
1
1
  # App Icons & Branding
2
2
 
3
- The `purgetss brand` command (introduced in PurgeTSS v7.6.0, restructured in v7.7.0) generates the complete Titanium branding set from a single SVG or PNG logo — with optional Android-specific overrides when you need them: launcher icons across every Android density, the adaptive-icon trio (foreground + background + monochrome), iOS 18+ Dark and Tinted variants, marketplace artwork, and optional notification/splash icons. Alloy and Classic layouts are auto-detected.
3
+ The `purgetss brand` command (introduced in PurgeTSS v7.6.0, restructured in v7.7.0, extended in v7.10.0 with the Google Play Feature Graphic) generates the complete Titanium branding set from a single SVG or PNG logo — with optional Android-specific overrides when you need them: launcher icons across every Android density, the adaptive-icon trio (foreground + background + monochrome), iOS 18+ Dark and Tinted variants, marketplace artwork (including the 1024×500 Feature Graphic for Google Play), and optional notification/splash icons. Alloy and Classic layouts are auto-detected.
4
4
 
5
5
  For the terse flag reference, see the [`brand` command reference](./cli-commands.md#brand-command). For sibling UI assets, see [Multi-Density Images](./multi-density-images.md).
6
6
 
@@ -45,7 +45,8 @@ purgetss/brand/
45
45
  ├── logo-mono.svg optional — monochrome layer + notifications
46
46
  ├── logo-dark.svg optional — iOS 18+ dark variant
47
47
  ├── logo-splash.svg optional — Android 12+ splash icon override
48
- └── logo-tinted.svg optional — iOS 18+ tinted variant
48
+ ├── logo-tinted.svg optional — iOS 18+ tinted variant
49
+ └── logo-feature.svg optional — Google Play Feature Graphic (1024×500) override
49
50
  ```
50
51
 
51
52
  Only `logo.svg` (or `logo.png`) is required. Everything else is **opt-in refinement**:
@@ -58,6 +59,7 @@ Only `logo.svg` (or `logo.png`) is required. Everything else is **opt-in refinem
58
59
  | `logo-splash.svg` / `.png` | Optional | Android 12+ `splash_icon.png` artwork (only used when `--splash` / `android.splash: true`). | Falls back to the launcher artwork. |
59
60
  | `logo-dark.svg` / `.png` | Optional | iOS 18+ Dark appearance variant. | Main logo on a transparent background (Apple HIG default). |
60
61
  | `logo-tinted.svg` / `.png` | Optional | iOS 18+ Tinted appearance variant. | Grayscale of the main logo on black. |
62
+ | `logo-feature.svg` / `.png` | Optional | Google Play Feature Graphic (1024×500). Use when the Play Store banner should differ from the main app icon (e.g. logo + tagline lockup that fills the wider rectangular canvas). | Main logo is centered inside the banner with configured vertical padding. |
61
63
 
62
64
  Provide a dedicated `logo-icon` when the main logo is a horizontal wordmark, a vertical lockup, or anything else that looks fine in a 1024×1024 branding canvas but feels cramped inside an Android launcher mask.
63
65
 
@@ -67,6 +69,8 @@ Provide a dedicated `logo-splash` when the Android 12+ splash should use a diffe
67
69
 
68
70
  Provide a dedicated `logo-dark` when dark-mode brand guidelines use a different lockup or color treatment; provide `logo-tinted` when you want a pre-simplified silhouette that tints better than a naive grayscale of the colored version.
69
71
 
72
+ Provide a dedicated `logo-feature` when the Google Play Feature Graphic (1024×500) should use a different composition than the main app icon — for example a logo-plus-tagline lockup or a wider artwork that takes advantage of the rectangular canvas instead of being constrained to the centered square.
73
+
70
74
  > **INFO**
71
75
  >
72
76
  > Prefer SVG for the master
@@ -87,7 +91,8 @@ brand: {
87
91
  logos: {
88
92
  primary: './docs/snap-logo.svg',
89
93
  androidLauncher: './docs/snap-app-icon.svg',
90
- monochrome: './docs/snap-logo-mono.svg'
94
+ monochrome: './docs/snap-logo-mono.svg',
95
+ featureGraphic: './docs/snap-feature.svg' // optional — Google Play Feature Graphic
91
96
  }
92
97
  }
93
98
  ```
@@ -110,9 +115,10 @@ brand: {
110
115
  // iosTinted: './docs/logo-tinted.svg'
111
116
  },
112
117
  padding: {
113
- ios: '4%', // iOS aesthetic padding. Range 2-8%. No launcher mask.
114
- androidLegacy: '10%', // legacy ic_launcher.png padding %
115
- androidAdaptive: '19%' // adaptive icon safe-zone %. Spec floor 19.44%.
118
+ ios: '4%', // iOS aesthetic padding. Range 2-8%. No launcher mask.
119
+ androidLegacy: '10%', // legacy ic_launcher.png padding %
120
+ androidAdaptive: '19%', // adaptive icon safe-zone %. Spec floor 19.44%.
121
+ featureGraphic: '12%' // vertical padding for MarketplaceArtworkFeature.png (1024×500)
116
122
  },
117
123
  android: {
118
124
  splash: false, // also generate splash_icon.png × 5
@@ -145,6 +151,7 @@ All `logos.*` keys are optional path overrides. If you omit them, PurgeTSS auto-
145
151
  | `logos.monochrome` | `purgetss/brand/logo-mono.svg` | Android themed icons + notification icons. |
146
152
  | `logos.iosDark` | `purgetss/brand/logo-dark.svg` | iOS dark variant. |
147
153
  | `logos.iosTinted` | `purgetss/brand/logo-tinted.svg` | iOS tinted variant. |
154
+ | `logos.featureGraphic` | `purgetss/brand/logo-feature.svg` | Google Play Feature Graphic source (1024×500 rectangular canvas). |
148
155
 
149
156
  ### `brand.padding`
150
157
 
@@ -155,6 +162,7 @@ All padding values accept either numbers or percentage strings like `'19%'`.
155
162
  | `padding.ios` | `'4%'` | Visual inset for `DefaultIcon-ios.png`, `DefaultIcon-Dark.png`, `DefaultIcon-Tinted.png`, marketplace artwork. |
156
163
  | `padding.androidLegacy` | `'10%'` | Visual inset for legacy `ic_launcher.png`. |
157
164
  | `padding.androidAdaptive` | `'19%'` | Visual inset for adaptive Android foreground (`ic_launcher_foreground.png`). Adjust this first when icons look cropped inside launcher masks. |
165
+ | `padding.featureGraphic` | `'12%'` | Vertical padding (top + bottom) for `MarketplaceArtworkFeature.png` (1024×500 Google Play banner). The logo is rendered as a square block of side `500 - 2 × pad` centered horizontally and vertically. Lower it for a more impactful banner; raise it if the logo looks cramped against the top or bottom edge on smaller Play Store crops. |
158
166
 
159
167
  ### `brand.android`
160
168
 
@@ -185,6 +193,35 @@ If omitted, PurgeTSS behaves as if `ios.dark = true`, `ios.tinted = true`, `ios.
185
193
  | --- | --- | --- |
186
194
  | `confirmOverwrites` | `true` | When `false`, the `[y/N/a]` prompt is skipped. |
187
195
 
196
+ ### Upgrading from pre-7.7.0 configs
197
+
198
+ In v7.7.0, the `brand:` block was reorganized into grouped subsections (`logos`, `padding`, `android`, `ios`, `colors`). Since **v7.10.2**, if your `config.cjs` still uses the original flat layout, PurgeTSS auto-migrates it **in memory on every run** — your old config keeps working without any change on disk.
199
+
200
+ | Pre-7.7.0 flat key | Current grouped key |
201
+ | --- | --- |
202
+ | `brand.padding: <number\|string>` (single value) | `brand.padding.androidLegacy` **and** `brand.padding.androidAdaptive` (same value applied to both) |
203
+ | `brand.iosPadding` | `brand.padding.ios` |
204
+ | `brand.bgColor` | `brand.colors.background` |
205
+ | `brand.darkBgColor` | `brand.ios.darkBackground` |
206
+ | `brand.notification` | `brand.android.notification` |
207
+ | `brand.splash` | `brand.android.splash` |
208
+
209
+ If both legacy and grouped keys are present for the same property, the **grouped key wins**.
210
+
211
+ On first encounter per session, PurgeTSS prints a one-time deprecation notice listing the legacy keys it migrated:
212
+
213
+ ```text
214
+ ::PurgeTSS:: Legacy brand: schema detected in purgetss/config.cjs — auto-migrated in memory:
215
+ • brand.padding: 15 → brand.padding.androidLegacy + brand.padding.androidAdaptive
216
+ • brand.iosPadding → brand.padding.ios
217
+ • brand.bgColor → brand.colors.background
218
+ Update purgetss/config.cjs to the new grouped schema to silence this warning.
219
+ ```
220
+
221
+ The notice is suppressed once you update the file to the grouped layout. Auto-migration is purely transitional and may be removed in a future major version, so a one-time update to your `config.cjs` is recommended.
222
+
223
+ Prior to v7.10.2, projects on the flat layout crashed auto-purge with `TypeError: Cannot create property 'ios' on number '15'` because `brand.padding` was a number rather than an object. v7.10.2 normalizes the shape before defaults are applied.
224
+
188
225
  ## Overwrite confirmation
189
226
 
190
227
  `brand` writes directly into the project, so it asks before overwriting anything:
@@ -224,6 +261,7 @@ The output is automatically routed to the right directory for your project layou
224
261
  ├── DefaultIcon-Tinted.png ← 1024×1024, iOS 18+ tinted (grayscale on black)
225
262
  ├── iTunesConnect.png ← 1024×1024, App Store submission
226
263
  ├── MarketplaceArtwork.png ← 512×512, Google Play submission
264
+ ├── MarketplaceArtworkFeature.png ← 1024×500, Google Play Feature Graphic (v7.10.0)
227
265
  └── app/
228
266
  └── assets/android/
229
267
  ├── default.png ← legacy Titanium Android splash fallback (v7.7.0)
@@ -243,6 +281,7 @@ The output is automatically routed to the right directory for your project layou
243
281
  ```text
244
282
  <project>/
245
283
  ├── DefaultIcon.png DefaultIcon-ios.png ... ← same root-level files as Alloy
284
+ ├── MarketplaceArtworkFeature.png ← 1024×500, Google Play Feature Graphic (v7.10.0)
246
285
  ├── Resources/
247
286
  │ └── android/default.png ← legacy Titanium Android splash fallback (v7.7.0)
248
287
  └── platform/
@@ -343,9 +382,46 @@ purgetss brand --no-dark --no-tinted
343
382
  >
344
383
  > Until that PR lands, after your first iOS build you may need to add the two PNGs manually into `build/iphone/Assets.xcassets/AppIcon.appiconset/` in Xcode (via the "Appearance" column in the asset catalog editor). Once #14122 merges, the command becomes fully end-to-end.
345
384
 
385
+ ## Google Play Feature Graphic (v7.10.0)
386
+
387
+ Since v7.10.0, `purgetss brand` also generates `MarketplaceArtworkFeature.png` — the **1024×500** banner that Google Play shows above the app description on the Play Store listing. It's submission artwork only: the file is written to the project root for upload via Play Console; it is **not** bundled into the APK.
388
+
389
+ ### How the source is chosen
390
+
391
+ PurgeTSS resolves the Feature Graphic source in this order (first match wins):
392
+
393
+ 1. CLI `--feature-logo <path>` for the current run.
394
+ 2. `brand.logos.featureGraphic` in `config.cjs`.
395
+ 3. Auto-discovered `purgetss/brand/logo-feature.{svg,png}`.
396
+ 4. The main logo (centered inside the 1024×500 canvas with the configured vertical padding).
397
+
398
+ ```bash
399
+ purgetss brand --feature-logo ./docs/feature.svg
400
+ ```
401
+
402
+ Drop a dedicated logo when you want a logo + tagline lockup or a wider artwork that takes advantage of the rectangular canvas. Otherwise the main `logo.svg` is centered as a square block — fine for most apps.
403
+
404
+ ### Padding
405
+
406
+ The default vertical padding is `12%` (top + bottom). Override per run with `--feature-graphic-padding <n>` (integer `0-40`), or persist it in `brand.padding.featureGraphic`:
407
+
408
+ ```bash
409
+ purgetss brand --feature-graphic-padding 8
410
+ ```
411
+
412
+ ```javascript
413
+ brand: {
414
+ padding: {
415
+ featureGraphic: '8%'
416
+ }
417
+ }
418
+ ```
419
+
420
+ The logo is rendered as a square block of side `500 - 2 × pad` and centered horizontally on the 1024-wide canvas. Lower the padding for a more impactful banner; raise it if the logo looks cramped against the top or bottom edge on smaller Play Store crops.
421
+
346
422
  ## Brand color
347
423
 
348
- The `--bg-color` flag (or `brand.bgColor` in config) controls three things at once:
424
+ The `--bg-color` flag (or `brand.colors.background` in config) controls three things at once:
349
425
 
350
426
  1. The **Android adaptive background layer**: a solid color that fills the full 108dp canvas behind your logo.
351
427
  2. The **iOS alpha flatten** for `DefaultIcon-ios.png`. Apple rejects transparent App Store icons, so the logo is flattened on this color.
@@ -510,10 +586,11 @@ All 5 Android densities, marketplace artwork, and iOS variants regenerate in one
510
586
  | Flag | Purpose |
511
587
  | --- | --- |
512
588
  | `--bg-color <hex>` | Background color for Android adaptive + iOS/marketplace flatten. |
513
- | `--padding <n>` | Shortcut: sets BOTH Android paddings to the same value for one run. |
589
+ | `--padding <n>` | Shortcut: sets BOTH Android paddings to the same value for one run. Fixed in v7.10.0 — previously only fed `androidAdaptivePadding`, leaving `androidLegacyPadding` at its own config value. |
514
590
  | `--android-adaptive-padding <n>` | Adaptive icon safe-zone % (default `19`). |
515
591
  | `--android-legacy-padding <n>` | Legacy `ic_launcher.png` padding % (default `10`). |
516
592
  | `--ios-padding <n>` | iOS aesthetic padding % (range `2–8`, default `4`). |
593
+ | `--feature-graphic-padding <n>` | (v7.10.0) Vertical padding for `MarketplaceArtworkFeature.png` (range `0-40`, default `12`). |
517
594
 
518
595
  **Optional asset types**
519
596
 
@@ -532,6 +609,7 @@ All 5 Android densities, marketplace artwork, and iOS variants regenerate in one
532
609
  | `--dark-bg-color <hex>` | Opaque dark bg for `DefaultIcon-Dark.png` (default: transparent per Apple HIG). |
533
610
  | `--splash-logo <path>` | Override `purgetss/brand/logo-splash.{svg,png}` for Android 12+ splash artwork. |
534
611
  | `--tinted-logo <path>` | Override `purgetss/brand/logo-tinted.{svg,png}`. |
612
+ | `--feature-logo <path>` | (v7.10.0) Override `purgetss/brand/logo-feature.{svg,png}` for the Google Play Feature Graphic. |
535
613
  | `--no-dark` | Skip `DefaultIcon-Dark.png`. |
536
614
  | `--no-tinted` | Skip `DefaultIcon-Tinted.png`. |
537
615
 
@@ -552,14 +630,16 @@ All 5 Android densities, marketplace artwork, and iOS variants regenerate in one
552
630
  ### Examples
553
631
 
554
632
  ```bash
555
- purgetss brand # uses purgetss/brand/logo.svg + config
556
- purgetss brand --bg-color "#0B1326" # override bg color
557
- purgetss brand --icon-logo ./docs/app-icon.svg # dedicated square Android launcher mark
558
- purgetss brand --splash --splash-logo ./docs/splash.svg # custom Android 12+ splash artwork
559
- purgetss brand --notification --splash # add notification + splash
560
- purgetss brand --no-tinted # skip iOS 18+ tinted variant
561
- purgetss brand --dry-run # preview without writing
562
- purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
633
+ purgetss brand # uses purgetss/brand/logo.svg + config
634
+ purgetss brand --bg-color "#0B1326" # override bg color
635
+ purgetss brand --icon-logo ./docs/app-icon.svg # dedicated square Android launcher mark
636
+ purgetss brand --splash --splash-logo ./docs/splash.svg # custom Android 12+ splash artwork
637
+ purgetss brand --feature-logo ./docs/feature.svg # custom Google Play Feature Graphic (v7.10.0)
638
+ purgetss brand --feature-graphic-padding 8 # tighter Feature Graphic padding (v7.10.0)
639
+ purgetss brand --notification --splash # add notification + splash
640
+ purgetss brand --no-tinted # skip iOS 18+ tinted variant
641
+ purgetss brand --dry-run # preview without writing
642
+ purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
563
643
  ```
564
644
 
565
645
  ## Community-Discovered Patterns
@@ -68,6 +68,31 @@ theme: {
68
68
  '.btn-primary': { backgroundColor: '#22c55e', borderColor: '#bbf7d0', color: '#dcfce7', textColor: '#dcfce7' }
69
69
  ```
70
70
 
71
+ ## Use Icon Font Classes (v7.10.0)
72
+
73
+ Since v7.10.0, icon fonts bundled with PurgeTSS — FontAwesome (`fas`, `fab`, `fa-*`), Material Icons (`mi-*`), Material Symbols (`ms-*`), and Framework7 (`f7-*`) — can be referenced inside `apply` **without running `build-fonts` first**. The directive resolves these classes against the bundled `dist/*.tss` files, so the font family and the glyph are merged into the generated rule alongside the rest of the utilities.
74
+
75
+ `./purgetss/config.cjs`
76
+ ```javascript
77
+ module.exports = {
78
+ theme: {
79
+ '.close-button': {
80
+ apply: 'fas fa-times-circle wh-12 text-gray-700'
81
+ }
82
+ }
83
+ };
84
+ ```
85
+
86
+ `./purgetss/styles/utilities.tss`
87
+ ```tss
88
+ '.close-button': { color: '#374151', textColor: '#374151', width: 48, height: 48, font: { fontFamily: 'FontAwesome7Free-Solid' }, text: '', title: '' }
89
+ ```
90
+
91
+ The same lookup runs for `mi-*`, `ms-*`, and `f7-*` classes. If the project ships its own `purgetss/styles/fontawesome.tss` (for example, FontAwesome Pro or Beta), that file takes precedence over the bundled default — matching the precedence order used when the same icon class appears directly in XML.
92
+
93
+ > **PRE-v7.10.0 BEHAVIOR**
94
+ > Before v7.10.0, those icon font classes were silently dropped from `apply`-generated rules. `apply: 'fas fa-times-circle wh-12 ...'` produced every utility **except** the FontAwesome family and the icon glyph. If a project worked around this by running `build-fonts` first, that workaround is no longer required.
95
+
71
96
  ## Use Arbitrary Values
72
97
 
73
98
  You can use [Arbitrary Values](./arbitrary-values.md) to define your custom classes.
@@ -261,7 +286,7 @@ Use the explicit `default:` wrapper when you also need platform blocks (`ios:`,
261
286
  >
262
287
  > If you previously used `theme.Window` (no `extend`) and depended on the white background or the iOS `hires: true` / `Ti.UI.SIZE` defaults still being there, you will need to either move that config under `theme.extend.Window` (extend mode) or add the previously-implicit utilities back into your `apply` string.
263
288
 
264
- PurgeTSS follows the Tailwind convention for the three Ti Elements that ship with framework defaults — `Window`, `View`, and `ImageView`:
289
+ The three Ti Elements that ship with framework defaults — `Window`, `View`, and `ImageView` — support two declaration modes depending on where they are placed in `config.cjs`:
265
290
 
266
291
  - **Extend mode** — `theme.extend.Window`, `theme.extend.View`, `theme.extend.ImageView`. Your customization **merges** with the framework defaults. The white Window `backgroundColor`, `Ti.UI.SIZE` width/height on `View`, and iOS `hires: true` on `ImageView` stay in place unless you override them with `apply`. Use this when you want to add to the defaults, not replace them.
267
292
  - **Replace mode** — `theme.Window`, `theme.View`, `theme.ImageView` (top level, no `extend`). Your config **replaces** the framework defaults entirely. The white Window background is omitted, the `Ti.UI.SIZE` width/height on `View` is omitted, and the iOS `hires: true` on `ImageView` is omitted. Your `apply` becomes the source of truth for that Ti Element.
@@ -5,7 +5,7 @@ When you need a one-off value that is not in the defaults, use arbitrary values
5
5
  > **INFO**
6
6
  > To generate an arbitrary style, use parentheses notation with almost any default utility class.
7
7
  >
8
- > You cannot use square bracket notation like in Tailwind because Titanium handles platform and conditional statements in `.tss` files differently.
8
+ > Square bracket notation (`[10px]`) is **not supported** because Titanium handles platform and conditional statements in `.tss` files differently. Use parentheses (`(10px)`) instead.
9
9
 
10
10
  ## Class syntax pre-validation
11
11
 
@@ -35,7 +35,7 @@ The validator catches five narrow, actionable mistakes:
35
35
  | Pattern | Offending input | Suggested fix | Notes |
36
36
  | ----------------------------- | --------------- | ------------- | ---------------------------------------------------------------- |
37
37
  | Inverted negative sign | `top-(-10)` | `-top-(10)` | The `-` prefix goes before the rule, not inside the value |
38
- | Tailwind-style brackets | `top-[10px]` | `top-(10px)` | PurgeTSS uses parentheses, not square brackets, for arbitrary values |
38
+ | Square-bracket notation | `top-[10px]` | `top-(10px)` | PurgeTSS uses parentheses, not square brackets, for arbitrary values (v7.10.1 reworded the error from `Tailwind-style brackets "[ ]"` to `Square brackets "[ ]" are not supported`) |
39
39
  | Empty parentheses | `wh-()` | (flagged, no auto-fix) | Add a value such as `wh-(10)` |
40
40
  | Whitespace inside parentheses | `wh-( 200 )` | `wh-(200)` | No spaces allowed between `(`, the value, and `)` |
41
41
  | Redundant `px` unit | `top-(10px)` | `top-(10)` | PurgeTSS treats unit-less arbitrary values as pixels |
@@ -48,6 +48,76 @@ The pre-validator only fires on the five patterns above. Any other unknown class
48
48
 
49
49
  Before v7.8.0, an inverted negative such as `top-(-10)` could be silently misparsed by the arbitrary-value pipeline (the `-` inside the parentheses confused the token matcher, producing wrong or missing TSS output without any warning). v7.8.0 hardens that path: the parser now correctly recognizes `top-(-10)` as authored, classifies it as an inverted-negative-sign error, and surfaces the `Class Syntax Error` block with the `-top-(10)` fix instead of producing silent garbage.
50
50
 
51
+ ## Arbitrary nesting depth in `theme` objects (v7.10.0)
52
+
53
+ Since v7.10.0, property emission walks nested `theme.*` values **recursively** instead of stopping at level 2, so deeply nested color families, gradients, and background gradients now flatten into class suffixes without being silently dropped.
54
+
55
+ Before v7.10.0:
56
+
57
+ ```javascript
58
+ // pre-v7.10.0 — only colors.brand was reached; .primary.500 was silently dropped
59
+ theme: {
60
+ extend: {
61
+ colors: {
62
+ brand: {
63
+ primary: { 500: '#3b82f6', 700: '#1d4ed8' }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ The classes `bg-brand-primary-500`, `text-brand-primary-700`, etc. were **not** generated.
71
+
72
+ From v7.10.0 onward:
73
+
74
+ ```javascript
75
+ // v7.10.0+ — recursive walk emits the full path
76
+ theme: {
77
+ extend: {
78
+ colors: {
79
+ brand: {
80
+ primary: { 500: '#3b82f6', 700: '#1d4ed8' }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ ```tss
88
+ /* utilities.tss */
89
+ '.bg-brand-primary-500': { backgroundColor: '#3b82f6' }
90
+ '.bg-brand-primary-700': { backgroundColor: '#1d4ed8' }
91
+ '.text-brand-primary-500': { color: '#3b82f6', textColor: '#3b82f6' }
92
+ /* ...and every other color property */
93
+ ```
94
+
95
+ The same recursive emission applies to `backgroundGradient` and `backgroundSelectedGradient` definitions inside `theme.extend`.
96
+
97
+ ### Default modifier keys collapse silently
98
+
99
+ Three special keys — `default`, `global`, `DEFAULT` — collapse without contributing to the class-name suffix. That lets you keep a default variant alongside named variants without polluting the class name:
100
+
101
+ ```javascript
102
+ theme: {
103
+ extend: {
104
+ colors: {
105
+ surface: {
106
+ DEFAULT: '#f9fafb', // emits .bg-surface (no suffix)
107
+ muted: '#e5e7eb' // emits .bg-surface-muted
108
+ }
109
+ }
110
+ }
111
+ }
112
+ ```
113
+
114
+ ```tss
115
+ '.bg-surface': { backgroundColor: '#f9fafb' }
116
+ '.bg-surface-muted': { backgroundColor: '#e5e7eb' }
117
+ ```
118
+
119
+ If you have a project that previously kept color shades only at depth ≤ 2 to avoid the silent-drop behavior, you can now restructure them by domain without paying for nesting.
120
+
51
121
  ## Color Properties
52
122
 
53
123
  You can set arbitrary color values for all available color properties using `hex`, `rgb`, or `rgba` values, directly in XML files or in `config.cjs`.
@@ -151,7 +151,7 @@ Complete inventory of all class prefixes organized by functional category. For n
151
151
  | `touch` | `touch-enabled`, `touch-enabled-false` | Boolean |
152
152
  | `clip` | `clip-enabled`, `clip-enabled-false` | Boolean (iOS) |
153
153
  | `interactive-dismiss` | `interactive-dismiss-mode-enabled`, `*-false` | Boolean (iOS) |
154
- | `large-title` | `large-title-enabled`, `large-title-enabled-false` | Boolean (iOS). Must pair with `extend-edges-all` and `auto-adjust-scroll-view-insets` when using ScrollView — see [apply-directive.md](apply-directive.md) Community-Discovered Patterns |
154
+ | `large-title` | `large-title-enabled`, `large-title-enabled-false` | Boolean (iOS). Must pair with `extend-edges-all` and `auto-adjust-scroll-view-insets` when using ScrollView — full pattern, global-defaults recipe, TabGroup behavior, and the `content-w-screen` / `content-h-auto` ScrollView pairing live in [`ios-large-titles.md`](ios-large-titles.md). |
155
155
  | `overlay` | `overlay-enabled`, `overlay-enabled-false` | Boolean (iOS) |
156
156
  | `toolbar` | `toolbar-enabled`, `toolbar-enabled-false` | Boolean |
157
157
  | `submit` | `submit-enabled`, `submit-enabled-false` | Boolean |
@@ -221,10 +221,11 @@ purgetss brand path/to/logo.svg # positional logo path override
221
221
  | Flag | Purpose |
222
222
  | --- | --- |
223
223
  | `--bg-color <hex>` | Background color for Android adaptive + iOS/marketplace flatten. |
224
- | `--padding <n>` | Shortcut: sets BOTH Android paddings to the same value for one run. |
224
+ | `--padding <n>` | Shortcut: sets BOTH Android paddings to the same value for one run. Fixed in v7.10.0 — previously only fed `androidAdaptivePadding`, leaving `androidLegacyPadding` at its own config value. |
225
225
  | `--android-adaptive-padding <n>` | Adaptive icon safe-zone % (default `19`). |
226
226
  | `--android-legacy-padding <n>` | Legacy `ic_launcher.png` padding % (default `10`). |
227
227
  | `--ios-padding <n>` | iOS aesthetic padding % (range `2-8`, default `4`). |
228
+ | `--feature-graphic-padding <n>` | (v7.10.0) Vertical padding for `MarketplaceArtworkFeature.png` (range `0-40`, default `12`). |
228
229
 
229
230
  **Optional asset types**
230
231
 
@@ -243,6 +244,7 @@ purgetss brand path/to/logo.svg # positional logo path override
243
244
  | `--dark-bg-color <hex>` | Opaque dark bg for `DefaultIcon-Dark.png` (default: transparent per Apple HIG). |
244
245
  | `--splash-logo <path>` | Override `purgetss/brand/logo-splash.{svg,png}` for Android 12+ splash artwork. |
245
246
  | `--tinted-logo <path>` | Override `purgetss/brand/logo-tinted.{svg,png}`. |
247
+ | `--feature-logo <path>` | (v7.10.0) Override `purgetss/brand/logo-feature.{svg,png}` for the Google Play Feature Graphic (1024×500). |
246
248
  | `--no-dark` | Skip `DefaultIcon-Dark.png`. |
247
249
  | `--no-tinted` | Skip `DefaultIcon-Tinted.png`. |
248
250
 
@@ -277,12 +279,14 @@ brand: {
277
279
  // androidSplash: './docs/splash.svg',
278
280
  // monochrome: './docs/logo-mono.svg',
279
281
  // iosDark: './docs/logo-dark.svg',
280
- // iosTinted: './docs/logo-tinted.svg'
282
+ // iosTinted: './docs/logo-tinted.svg',
283
+ // featureGraphic: './docs/logo-feature.svg' // Google Play 1024×500 banner (v7.10.0)
281
284
  },
282
285
  padding: {
283
- ios: '4%', // iOS aesthetic padding. Range 2-8%.
284
- androidLegacy: '10%', // legacy ic_launcher.png padding %
285
- androidAdaptive: '19%' // adaptive icon safe-zone %. Spec floor 19.44%.
286
+ ios: '4%', // iOS aesthetic padding. Range 2-8%.
287
+ androidLegacy: '10%', // legacy ic_launcher.png padding %
288
+ androidAdaptive: '19%', // adaptive icon safe-zone %. Spec floor 19.44%.
289
+ featureGraphic: '12%' // MarketplaceArtworkFeature.png vertical padding (v7.10.0)
286
290
  },
287
291
  android: {
288
292
  splash: false, // also generate splash_icon.png × 5
@@ -309,14 +313,16 @@ The recommended workflow is convention-first: drop files in `purgetss/brand/`, l
309
313
  ### Examples
310
314
 
311
315
  ```bash
312
- purgetss brand # uses purgetss/brand/logo.svg + config
313
- purgetss brand --bg-color "#0B1326" # override bg color
314
- purgetss brand --icon-logo ./docs/app-icon.svg # dedicated square Android launcher mark
315
- purgetss brand --splash --splash-logo ./docs/splash.svg # custom Android 12+ splash artwork
316
- purgetss brand --notification --splash # add notification + splash
317
- purgetss brand --no-tinted # skip iOS 18+ tinted variant
318
- purgetss brand --dry-run # preview without writing
319
- purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
316
+ purgetss brand # uses purgetss/brand/logo.svg + config
317
+ purgetss brand --bg-color "#0B1326" # override bg color
318
+ purgetss brand --icon-logo ./docs/app-icon.svg # dedicated square Android launcher mark
319
+ purgetss brand --splash --splash-logo ./docs/splash.svg # custom Android 12+ splash artwork
320
+ purgetss brand --feature-logo ./docs/feature.svg # custom Google Play Feature Graphic (v7.10.0)
321
+ purgetss brand --feature-graphic-padding 8 # tighter Feature Graphic padding (v7.10.0)
322
+ purgetss brand --notification --splash # add notification + splash
323
+ purgetss brand --no-tinted # skip iOS 18+ tinted variant
324
+ purgetss brand --dry-run # preview without writing
325
+ purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
320
326
  ```
321
327
 
322
328
  ### Android output groups
@@ -349,6 +355,9 @@ purgetss images background/ # re-process one subfolder
349
355
  | `--format <ext>` | Convert all outputs to `webp`, `jpeg`, `png`, `avif`, `gif`, or `tiff`. Default: keep source format. |
350
356
  | `--quality <n>` | Quality `0-100` for lossy formats. Default `85`. |
351
357
  | `--width <n>` | (v7.8.0) Pin Android `mdpi` (= iPhone `@1x`) to `<n>` pixels wide. Larger scales derive as ×1.5, ×2, ×3, ×4 from that base; height stays proportional to the source's aspect ratio. Integer in `[1, 8192]`. |
358
+ | `--opacity <n>` | (v7.10.0) Multiply alpha of every density by `n/100`. Integer in `[0, 100]`. With `--format jpeg`, alpha flattens on white. |
359
+ | `--padding <n>` | (v7.10.0) Shrink the rendered image inside each density canvas by `n%` symmetric borders. Integer in `[0, 40]`. |
360
+ | `--output <relpath>` | (v7.10.0) Override the basename and subpath relative to each platform's `images/` root. |
352
361
  | `--dry-run` | Preview without writing any files. |
353
362
  | `--project <path>` | Project root (defaults to cwd). |
354
363
  | `-y, --yes` | Skip the overwrite confirmation prompt. |
@@ -364,6 +373,16 @@ Use `--width <n>` for SVG sources from vector editors with disproportionate view
364
373
 
365
374
  When you pass an SVG without `--width`, the command prints a one-time hint and falls back to the legacy 4× behavior. This is CLI-only; there is no matching `images:` config property because the right width is per-asset.
366
375
 
376
+ ### When to use `--opacity`, `--padding`, `--output` (v7.10.0)
377
+
378
+ The three v7.10.0 flags are designed for **placeholder / default ImageView** workflows where the source asset is a brand or logo you want to re-render at reduced opacity and/or with extra breathing room — without editing the source file itself.
379
+
380
+ - `--opacity` is a runtime alpha multiplier. JPEG flattens the result on white; PNG/WebP/AVIF keep alpha.
381
+ - `--padding` shrinks the rendered image inside each density canvas, keeping the canvas dimensions and filling the difference with transparent pixels.
382
+ - `--output` retargets the basename and subpath, useful when the source lives outside `purgetss/images/` (e.g. `purgetss/brand/`).
383
+
384
+ All three are **CLI-only by design** — no `config.cjs` equivalent — because they describe per-asset render decisions, not project-wide settings.
385
+
367
386
  ### Config block
368
387
 
369
388
  Defaults live under `images:` in `purgetss/config.cjs`:
@@ -387,6 +406,11 @@ purgetss images background/ # re-process one subfolde
387
406
  purgetss images --android # only Android densities
388
407
  purgetss images --format webp --quality 90 # convert all outputs to WebP
389
408
  purgetss images logo.svg --width 256 # pin SVG output to 256 px @1x/mdpi
409
+ purgetss images logo.svg --opacity 50 --format png # 50% alpha placeholder (v7.10.0)
410
+ purgetss images logo.svg --padding 15 --format png # add 15% breathing room (v7.10.0)
411
+ purgetss images purgetss/brand/logo.svg \
412
+ --opacity 30 --padding 15 \
413
+ --output 'logos/default-image' --format png # placeholder under custom path (v7.10.0)
390
414
  purgetss images --dry-run # preview
391
415
  ```
392
416
 
@@ -37,9 +37,10 @@ module.exports = {
37
37
  brand: {
38
38
  logos: {}, // empty = auto-discovers from purgetss/brand/
39
39
  padding: {
40
- ios: '4%', // iOS aesthetic padding. Range 2-8%.
41
- androidLegacy: '10%', // legacy ic_launcher.png padding %
42
- androidAdaptive: '19%' // adaptive icon safe-zone %. Spec floor 19.44%.
40
+ ios: '4%', // iOS aesthetic padding. Range 2-8%.
41
+ androidLegacy: '10%', // legacy ic_launcher.png padding %
42
+ androidAdaptive: '19%', // adaptive icon safe-zone %. Spec floor 19.44%.
43
+ featureGraphic: '12%' // MarketplaceArtworkFeature.png vertical padding (v7.10.0)
43
44
  },
44
45
  android: {
45
46
  splash: false, // also generate splash_icon.png × 5
@@ -59,6 +60,8 @@ module.exports = {
59
60
  quality: 85, // JPEG/WebP/AVIF quality (0-100)
60
61
  format: null, // null = keep original; 'webp' | 'jpeg' | 'png' to convert every image
61
62
  confirmOverwrites: true // prompt before overwriting files (set false to skip)
63
+ // Note: --width (v7.8.0) and --opacity / --padding / --output (v7.10.0) are CLI-only
64
+ // by design — those decisions are per-asset, not project-wide.
62
65
  },
63
66
  theme: {
64
67
  extend: {}
@@ -78,12 +81,15 @@ The config file has four main sections: `purge`, `brand`, `images`, and `theme`.
78
81
 
79
82
  For `brand`, the structure is grouped by purpose (introduced in v7.7.0, refined since):
80
83
 
81
- - `logos`: optional path overrides when you do not want to rely on `purgetss/brand/` auto-discovery
82
- - `padding`: visual sizing for iOS, Android legacy, and Android adaptive icons
84
+ - `logos`: optional path overrides when you do not want to rely on `purgetss/brand/` auto-discovery — including `featureGraphic` for the Google Play 1024×500 banner (v7.10.0)
85
+ - `padding`: visual sizing for iOS, Android legacy, Android adaptive icons, and the Feature Graphic banner (v7.10.0)
83
86
  - `android`: Android-only optional outputs such as `splash_icon.png` and notification icons
84
87
  - `ios`: iOS-only variant toggles (`dark`, `tinted`) and the optional `darkBackground` color
85
88
  - `colors`: shared color settings such as the adaptive background and iOS flatten color
86
89
 
90
+ > **INFO — Pre-7.7.0 flat configs auto-migrate**
91
+ > Since v7.10.2, projects on the flat `brand:` schema (`brand.padding: <number>`, `brand.iosPadding`, `brand.bgColor`, etc.) auto-migrate in memory on every run. The grouped key always wins when both forms coexist, and a one-time deprecation notice lists the migrated keys. Update `config.cjs` to the grouped schema to silence the notice. See [App Icons & Branding → Upgrading from pre-7.7.0 configs](./app-branding.md#upgrading-from-pre-7-7-0-configs).
92
+
87
93
  For the property-by-property reference, see [Configurable Properties](./configurable-properties.md).
88
94
 
89
95
  ### Overriding logo paths
@@ -94,12 +100,13 @@ By default, PurgeTSS auto-discovers logo files from `purgetss/brand/`. If you wa
94
100
  module.exports = {
95
101
  brand: {
96
102
  logos: {
97
- primary: './my-logos/main.svg', // overrides auto-discovered logo.svg
98
- androidLauncher: './my-logos/icon.svg', // overrides auto-discovered logo-icon.svg
99
- androidSplash: './my-logos/splash.svg', // overrides auto-discovered logo-splash.svg
100
- monochrome: './my-logos/mono.svg', // overrides auto-discovered logo-mono.svg
101
- iosDark: './my-logos/dark.svg', // overrides auto-discovered logo-dark.svg
102
- iosTinted: './my-logos/tinted.svg' // overrides auto-discovered logo-tinted.svg
103
+ primary: './my-logos/main.svg', // overrides auto-discovered logo.svg
104
+ androidLauncher: './my-logos/icon.svg', // overrides auto-discovered logo-icon.svg
105
+ androidSplash: './my-logos/splash.svg', // overrides auto-discovered logo-splash.svg
106
+ monochrome: './my-logos/mono.svg', // overrides auto-discovered logo-mono.svg
107
+ iosDark: './my-logos/dark.svg', // overrides auto-discovered logo-dark.svg
108
+ iosTinted: './my-logos/tinted.svg', // overrides auto-discovered logo-tinted.svg
109
+ featureGraphic: './my-logos/feature.svg' // overrides auto-discovered logo-feature.svg (v7.10.0)
103
110
  }
104
111
  }
105
112
  };
@@ -46,7 +46,6 @@ $.UI.create('ComponentType', {
46
46
  function createThemeCard(themeName, themeTitle, imagePath) {
47
47
  return $.UI.create('View', {
48
48
  // View properties
49
- valor: themeName,
50
49
  title: themeTitle, // Add title for TTS support
51
50
 
52
51
  // PurgeTSS utility classes
@@ -1,11 +1,168 @@
1
1
  # Migration Guide
2
2
 
3
- This guide mirrors the official PurgeTSS changelog (see the project `README.md` / `docs/index.md`). It walks through the upgrade-relevant changes from v7.2.6 through v7.6.0, flags breaking changes, and links each section to the reference files that cover the new surface area in depth.
3
+ This guide mirrors the official PurgeTSS changelog (see the project `README.md` / `docs/index.md`). It walks through the upgrade-relevant changes from v7.2.6 through v7.10.x, flags breaking changes, and links each section to the reference files that cover the new surface area in depth.
4
4
 
5
5
  Changelog source of truth: [https://github.com/macCesar/purgeTSS](https://github.com/macCesar/purgeTSS).
6
6
 
7
7
  ---
8
8
 
9
+ ## Upgrade to v7.10.x
10
+
11
+ v7.10.0 through v7.10.2 are additive — **no breaking changes**. The notable shift is internal: configs written before v7.7.0 (the `brand:` regroup) now auto-migrate in memory on every run, so projects that never updated to the grouped `brand:` schema keep working without a `TypeError` crash. Full release notes in [`version-history.md`](./version-history.md).
12
+
13
+ ### Added in v7.10.0
14
+
15
+ - **`purgetss images --opacity / --padding / --output`** — three CLI-only flags aimed at placeholder / default ImageView workflows. `--opacity` multiplies alpha; `--padding` shrinks the rendered image inside each density canvas; `--output` retargets the basename and subpath. See [`multi-density-images.md`](./multi-density-images.md).
16
+ - **Google Play Feature Graphic in `brand`** — `purgetss brand` now generates `MarketplaceArtworkFeature.png` (1024×500). Auto-discovers `purgetss/brand/logo-feature.{svg,png}` or reuses the master logo. Tune with `--feature-graphic-padding <n>` (range `0-40`, default `12%`), `brand.padding.featureGraphic`, or `--feature-logo <path>`. See [`app-branding.md`](./app-branding.md).
17
+ - **Arbitrary nesting depth in `theme` objects** — property emission walks nested values recursively instead of stopping at level 2. `theme.extend.colors.brand.primary.500` now flattens to `brand-primary-500` instead of being silently dropped. Default keys (`default`, `global`, `DEFAULT`) collapse without contributing to the suffix. See [`arbitrary-values.md`](./arbitrary-values.md).
18
+ - **`apply:` resolves bundled icon fonts from `dist/`** — `apply: 'fas fa-times-circle wh-12 ...'` now merges the FontAwesome family and glyph automatically. Same lookup runs for `mi-*` (Material Icons), `ms-*` (Material Symbols), and `f7-*` (Framework7). Project-level `purgetss/styles/fontawesome.tss` still wins over the bundled default. See [`apply-directive.md`](./apply-directive.md).
19
+
20
+ ### Fixed in v7.10.0
21
+
22
+ - **`borderRadius` arrays inside `apply:`** — the post-merge dedup step now tracks depth on `[]` alongside `{}`, so directional rules like `rounded-{t,b,l,r,tl,tr,bl,br}-*` no longer get split on internal commas.
23
+ - **`brand --padding <n>` shortcut** — now applies to BOTH Android paddings (`androidAdaptivePadding` AND `androidLegacyPadding`) as the help text always promised. Previously only fed the adaptive one.
24
+
25
+ ### v7.10.1 — copy-only changes
26
+
27
+ - **"Tailwind" framing dropped** from copy that did not document a functional integration. Error block now reports `Square brackets "[ ]" are not supported` (previously `Tailwind-style brackets "[ ]"`). 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"`.
28
+ - **Functional integrations stay**: `tailwindcss@3` dependency installed by `install-dependencies` (drives the `defaultColors` / `defaultTheme` palette base AND the VSCode IntelliSense extension); `--tailwind` flag on `purgetss shades`; recommended `Tailwind CSS IntelliSense` and `Tailwind Raw Reorder (v4)` VSCode extensions.
29
+
30
+ ### v7.10.2 — pre-7.7.0 brand config auto-migration
31
+
32
+ If your project still uses the **flat** `brand:` config that predates v7.7.0, v7.10.2 normalizes it in memory on every run before defaults are applied. Without this, the build crashed with `TypeError: Cannot create property 'ios' on number '15'` because `brand.padding` was a number, not an object.
33
+
34
+ Mapping (see [`app-branding.md` → Upgrading from pre-7.7.0 configs](./app-branding.md#upgrading-from-pre-7-7-0-configs)):
35
+
36
+ | Pre-7.7.0 flat key | Current grouped key |
37
+ | --- | --- |
38
+ | `brand.padding: <number\|string>` | `brand.padding.androidLegacy` AND `brand.padding.androidAdaptive` (same value applied to both) |
39
+ | `brand.iosPadding` | `brand.padding.ios` |
40
+ | `brand.bgColor` | `brand.colors.background` |
41
+ | `brand.darkBgColor` | `brand.ios.darkBackground` |
42
+ | `brand.notification` | `brand.android.notification` |
43
+ | `brand.splash` | `brand.android.splash` |
44
+
45
+ The grouped key always wins when both forms coexist. A one-time deprecation notice per session lists which legacy keys were migrated. Auto-migration is transitional and may be removed in a future major version — update `config.cjs` to the grouped schema to silence the notice and stay future-proof.
46
+
47
+ ### What to review
48
+
49
+ - If you maintain a `brand:` block from pre-7.7.0, plan the one-time update to the grouped schema (`logos`, `padding`, `android`, `ios`, `colors`).
50
+ - If you previously skipped `apply:` with icon fonts because they were silently dropped, that workaround is no longer needed in v7.10.0.
51
+ - Deeply nested color families in `theme.extend.colors.*` that you flattened by hand to stay at depth ≤ 2 can be restructured by domain — the recursive emission now reaches every leaf.
52
+
53
+ ---
54
+
55
+ ## Upgrade to v7.9.0
56
+
57
+ v7.9.0 ships one **breaking** path rename plus a behavior change for `theme.Window` / `theme.View` / `theme.ImageView` that can surface as a regression if a project depended on the framework defaults being merged in.
58
+
59
+ ### Breaking — glossary output path renamed
60
+
61
+ The user-facing glossary output path moved from `purgetss/experimental/tailwind-classes/` to `purgetss/glossary/tailwind-classes/`. Tooling or CI that reads from the old path needs updating on upgrade — no transition shim was added on purpose. The `--glossary` flag and command surface are unchanged.
62
+
63
+ ### Headline behavior change — replace mode for top-level `theme.Window` / `View` / `ImageView`
64
+
65
+ Before v7.9.0, `theme.Window` (no `extend`) still merged with the framework defaults (white `backgroundColor`, `Ti.UI.SIZE` on `View`, iOS `hires: true` on `ImageView`), which produced gradient ghosting and similar overrides. v7.9.0 makes top-level configs behave as true **replace mode**.
66
+
67
+ If you previously wrote:
68
+
69
+ ```javascript
70
+ theme: {
71
+ Window: {
72
+ apply: 'bg-gradient-to-b from-blue-500 to-purple-600'
73
+ }
74
+ }
75
+ ```
76
+
77
+ …and **depended** on the implicit white background, the gradient now renders without that background underneath. Move the config under `theme.extend.Window` to keep the merged behavior, or add the previously-implicit utilities back into the `apply` string. See [`apply-directive.md` → Extend mode vs replace mode](./apply-directive.md#extend-mode-vs-replace-mode).
78
+
79
+ ### Added in v7.9.0
80
+
81
+ - **Opacity modifiers on semantic colors** — `bg-surface/65` now works for any class mapped through `theme.extend.colors`. PurgeTSS auto-derives `<originalKey>_<alphaPercent>` entries in `semantic.colors.json` per mode (light/dark). **Native rebuild required** — Liveview hot-reload alone does not refresh `semantic.colors.json`. See [`semantic-colors.md`](./semantic-colors.md#opacity-modifier-auto-derivation).
82
+
83
+ ### Fixed in v7.9.0
84
+
85
+ - Several fixes around semantic colors, gradients, and Ti Element defaults: tonal palette no longer inverts Light and Dark; gradient `from` / `to` color order is position-stable across `sort()`; `bg-gradient-to-X` direction is preserved when combined with `from-X to-Y` in the same `apply`; `theme.Window` / `theme.View` / `theme.ImageView` no longer ghost framework presets at the top level (see Headline behavior change above).
86
+
87
+ ---
88
+
89
+ ## Upgrade to v7.8.0
90
+
91
+ v7.8.0 introduces a structured `Class Syntax Error` block that **halts the build** when it detects known class-name mistakes — previously these flowed silently into the `// Unused or unsupported classes` block of `app.tss`.
92
+
93
+ ### Added — Class Syntax Error pre-validation
94
+
95
+ Five patterns are now caught and reported with file + line + suggested fix:
96
+
97
+ | Pattern | Offending input | Fix |
98
+ | --- | --- | --- |
99
+ | Inverted negative sign | `top-(-10)` | `-top-(10)` |
100
+ | Square-bracket notation | `top-[10px]` | `top-(10px)` |
101
+ | Empty parentheses | `wh-()` | (flagged, no auto-fix) |
102
+ | Whitespace inside parentheses | `wh-( 200 )` | `wh-(200)` |
103
+ | Redundant `px` unit | `top-(10px)` | `top-(10)` |
104
+
105
+ All offenders are reported in a single run. Generic unknown classes — typos, vendor utilities not enabled, custom classes not declared yet — continue to flow into `// Unused or unsupported classes`. See [`arbitrary-values.md` → Class syntax pre-validation](./arbitrary-values.md#class-syntax-pre-validation).
106
+
107
+ ### Added — `purgetss images --width <n>` (v7.8.0)
108
+
109
+ Pins Android `mdpi` (= iPhone `@1x`) to `<n>` pixels wide. Larger scales derive as ×1.5, ×2, ×3, ×4 from that base. Range `[1, 8192]`. Most useful for SVG sources from vector editors (Affinity, Illustrator) with disproportionate viewBoxes. CLI-only — width is per-asset, not a project-wide setting. See [`multi-density-images.md`](./multi-density-images.md#pinning-the-output-width-with---width).
110
+
111
+ ### Fixed in v7.8.0
112
+
113
+ - The arbitrary-value parser no longer crashes on negative values inside parentheses — `top-(-10)` is now recognized and reported as an inverted-negative-sign error instead of triggering a `Cannot read properties of null (reading 'pop')` exception.
114
+
115
+ ### What to review
116
+
117
+ - Run the build once on the upgraded version and address every `Class Syntax Error` it surfaces. The offender list is exhaustive in one pass.
118
+ - If a CI step depended on a malformed class quietly landing in the unused-classes block, it will now hard-fail — adjust the CI accordingly.
119
+
120
+ ---
121
+
122
+ ## Upgrade to v7.7.0
123
+
124
+ v7.7.0 cleans up the `brand:` config before stabilizing it. **Pre-7.10.2** projects on the flat schema crashed; from v7.10.2 onward the flat schema auto-migrates in memory (see Upgrade to v7.10.x). The recommended migration is still a one-time update to the grouped schema.
125
+
126
+ ### Restructure — grouped `brand:` config
127
+
128
+ Branding settings moved out of flat keys into purpose-based groups: `brand.logos`, `brand.padding`, `brand.android`, `brand.ios`, `brand.colors`.
129
+
130
+ ```javascript
131
+ // Pre-7.7.0 — flat
132
+ brand: {
133
+ padding: 15,
134
+ iosPadding: 4,
135
+ bgColor: '#FFFFFF',
136
+ notification: false,
137
+ splash: false
138
+ }
139
+
140
+ // v7.7.0+ — grouped
141
+ brand: {
142
+ padding: {
143
+ ios: '4%',
144
+ androidLegacy: '10%',
145
+ androidAdaptive: '19%'
146
+ },
147
+ android: {
148
+ notification: false,
149
+ splash: false
150
+ },
151
+ colors: {
152
+ background: '#FFFFFF'
153
+ }
154
+ }
155
+ ```
156
+
157
+ ### Added in v7.7.0
158
+
159
+ - **Separate Android brand inputs** — `logos.androidLauncher` / `--icon-logo` for the Android launcher icon; `logos.androidSplash` / `--splash-logo` for Android 12+ splash artwork. Drop `logo-icon.*` / `logo-splash.*` into `purgetss/brand/` for auto-discovery.
160
+ - **Independent Android paddings** — `--android-adaptive-padding` (default `19%`) and `--android-legacy-padding` (default `10%`) replace the single `--padding`. `--padding` is now a shortcut that sets both for one run (note: the shortcut bug where only `androidAdaptive` was applied was fixed in v7.10.0).
161
+ - **Android splash fallback regenerated** — `app/assets/android/default.png` (Alloy) or `Resources/android/default.png` (Classic). `cleanup-legacy` no longer removes `default.png`.
162
+ - **Values and Units doc** — new official reference explaining how `ti.ui.defaultunit` in `tiapp.xml` interprets PurgeTSS unitless values. See [`values-and-units.md`](./values-and-units.md).
163
+
164
+ ---
165
+
9
166
  ## Upgrade to v7.6.0
10
167
 
11
168
  v7.6.0 introduces three new CLI commands for app-asset generation plus two new `config.cjs` sections. None of the additions are breaking — existing projects continue to work untouched, and the new config sections are auto-injected on first run.
@@ -211,3 +368,7 @@ If you previously worked around this by inlining the gradient directly in TSS, r
211
368
  - After v7.5.0: diff generated `utilities.tss` to confirm property deduplication produces the expected output.
212
369
  - After v7.5.3: consider wiring `Appearance.init()` at app boot if you want runtime Light/Dark switching.
213
370
  - After v7.6.0: run `brand`, `images`, and `semantic` once in a scratch project before pointing them at production assets, so you can preview the output layout.
371
+ - After v7.7.0: migrate the `brand:` block in `config.cjs` to the grouped schema (`logos`, `padding`, `android`, `ios`, `colors`). v7.10.2 auto-migrates flat configs in memory, but the one-time update is recommended to silence the deprecation notice.
372
+ - After v7.8.0: run the build once and address every `Class Syntax Error` it surfaces. Update CI to handle the new hard-fail on malformed class names. Migrate any `top-[10px]` style square brackets to `top-(10px)` parentheses.
373
+ - After v7.9.0: search for any `purgetss/experimental/tailwind-classes/` references in tooling/CI and update to `purgetss/glossary/tailwind-classes/`. If a project used top-level `theme.Window` / `View` / `ImageView` and depended on framework defaults being merged in, decide between moving the config under `theme.extend.*` or adding the previously-implicit utilities to the `apply` string.
374
+ - After v7.10.0: deeply nested color families (`theme.extend.colors.brand.primary.500`) now emit recursively — restructure by domain if it improves readability. `apply:` with bundled icon fonts (`fas`, `mi-*`, `ms-*`, `f7-*`) no longer requires `build-fonts` first. The Google Play Feature Graphic ships automatically with `purgetss brand`.
@@ -304,6 +304,67 @@ purgetss images --format webp --quality 85
304
304
 
305
305
  Keep the default `format: null` when you need to stay in the same format as the source — for example PNG with alpha that shouldn't be flattened.
306
306
 
307
+ ## Reducing alpha across every density with `--opacity` (v7.10.0)
308
+
309
+ Since v7.10.0, `--opacity <n>` 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 behind content, "image is loading" overlays).
310
+
311
+ ```bash
312
+ purgetss images logo.svg --opacity 50 --format png
313
+ ```
314
+
315
+ - `--opacity` accepts integers in `[0, 100]`. Out-of-range values exit immediately without writing anything (`Invalid --opacity '150'. Must be an integer between 0 and 100.`).
316
+ - `--opacity 100` is a no-op — the compositing pass is skipped entirely.
317
+ - `--opacity 0` produces a fully transparent output (technically valid, visually empty).
318
+
319
+ ### Format interactions
320
+
321
+ - **PNG / WebP / AVIF:** alpha is preserved.
322
+ - **JPEG:** JPEG has no alpha. The existing flatten-on-white step composites the semi-transparent image onto white before writing, so `--opacity 50 --format jpeg` produces a 50%-faded version **on white**, not a transparent JPEG.
323
+
324
+ ## Adding breathing room with `--padding` (v7.10.0)
325
+
326
+ `--padding <n>` shrinks the rendered image inside each density canvas by `n%` symmetric borders. Useful when the source logo has no built-in padding and you want a placeholder with breathing room — without editing the source asset.
327
+
328
+ ```bash
329
+ purgetss images purgetss/brand/logo.png --padding 15 --format png
330
+ ```
331
+
332
+ Each density's output canvas keeps the same dimensions it would have without `--padding`, but the rendered image takes only `(1 − 2 × 0.15) = 70%` of that canvas (centered). The remaining 30% of the canvas (15% on each side) is transparent.
333
+
334
+ - `--padding` accepts integers in `[0, 40]`. Out-of-range or negative values are rejected (`Invalid --padding '50'. Must be an integer between 0 and 40.`).
335
+ - `--padding 0` is a no-op (skipped — no extend pass).
336
+
337
+ ### When *not* to use `--padding`
338
+
339
+ If your source logo already has the breathing room you want baked in, you don't need `--padding` — it compounds the existing padding. Use `--padding` when:
340
+
341
+ - the source is edge-to-edge (no built-in margin) and you want a centered placeholder
342
+ - you need a fast way to produce a "loose" variant of a logo without touching the source file
343
+
344
+ ## Renaming the output with `--output` (v7.10.0)
345
+
346
+ By default, the output basename comes from the source filename and the subfolder mirrors the source's location inside `purgetss/images/`. When you want a different output path — for example, sourcing a logo from `purgetss/brand/` and writing it as a placeholder under `images/logos/` — `--output <relpath>` overrides both:
347
+
348
+ ```bash
349
+ purgetss images purgetss/brand/logo.svg --output logos/default-image
350
+ ```
351
+
352
+ That writes `images/logos/default-image.png` (or `.jpg` / `.webp` depending on `--format`) across all densities, regardless of the source's location.
353
+
354
+ ### Combining `--opacity`, `--padding`, and `--output`
355
+
356
+ The three flags compose for the canonical "transparent placeholder with padding under a custom path" use case:
357
+
358
+ ```bash
359
+ purgetss images purgetss/brand/logo.svg \
360
+ --opacity 30 \
361
+ --padding 15 \
362
+ --output 'logos/default-image' \
363
+ --format png
364
+ ```
365
+
366
+ Produces a 30% opacity, 15%-padded version of the brand logo at `images/logos/default-image.png` for every Android density and iPhone scale — a one-command way to ship a default ImageView placeholder.
367
+
307
368
  ## Full pipeline alongside `build`
308
369
 
309
370
  The typical sequence when iterating on an app:
@@ -348,6 +409,9 @@ If you only tweaked CSS classes (no image changes), you don't need to re-run `pu
348
409
  | `--format <ext>` | Convert all outputs to: `webp`, `jpeg`, `png`, `avif`, `gif`, `tiff`. Default: keep source format. |
349
410
  | `--quality <n>` | Quality `0–100` for lossy formats. Default `85`. |
350
411
  | `--width <n>` | (v7.8.0) Pin `mdpi` / `@1x` output width to `n` pixels; `[1, 8192]`. Other densities derive from this base (×1.5 / ×2 / ×3 / ×4). Most useful for SVG sources with non-standard viewBoxes. CLI-only — no `config.cjs` equivalent because width is per-asset. |
412
+ | `--opacity <n>` | (v7.10.0) Multiply the alpha channel of every generated density by `n/100`. Range `[0, 100]`. Combine with `--format jpeg` and the alpha is flattened on white instead of producing a transparent JPEG. CLI-only. |
413
+ | `--padding <n>` | (v7.10.0) Shrink the rendered image inside each density canvas by `n%` symmetric borders. Range `[0, 40]`. CLI-only. |
414
+ | `--output <relpath>` | (v7.10.0) Override the basename and subpath relative to each platform's `images/` root. Lets a source from outside `purgetss/images/` (e.g. `purgetss/brand/`) write into a custom output folder like `images/logos/`. CLI-only. |
351
415
 
352
416
  **Project & output**
353
417
 
@@ -371,6 +435,11 @@ purgetss images background/pink-texture.png # re-process one file (sh
371
435
  purgetss images background/ # re-process one subfolder
372
436
  purgetss images --android # only Android densities
373
437
  purgetss images --format webp --quality 90 # convert all outputs to WebP
438
+ purgetss images --opacity 50 --format png # 50% alpha placeholder (v7.10.0)
439
+ purgetss images logo.svg --padding 15 --format png # add 15% breathing room (v7.10.0)
440
+ purgetss images purgetss/brand/logo.svg \
441
+ --opacity 30 --padding 15 \
442
+ --output 'logos/default-image' --format png # placeholder under custom path (v7.10.0)
374
443
  purgetss images --dry-run # preview
375
444
  ```
376
445
 
@@ -0,0 +1,82 @@
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,6 +1,6 @@
1
1
  ---
2
2
  name: ti-expert
3
- description: "Titanium SDK architecture and implementation expert. Use when designing, reviewing, analyzing, or examining Titanium project structure (Alloy or Classic), creating controllers/views/services, choosing models vs collections, implementing communication patterns, handling memory cleanup, testing, auditing code, migrating legacy apps, or building adaptive/responsive layouts for tablets, foldables, and large screens. AUTO-DETECT: If tiapp.xml exists, invoke this skill BEFORE making architectural decisions, creating new controllers/views, or restructuring code. Titanium has its own patterns for navigation (NavigationWindow, TabGroup), memory management, and event handling that differ from web frameworks."
3
+ description: "Use when designing, reviewing, analyzing, or examining Titanium SDK architecture and implementation (Alloy or Classic) creating controllers/views/services, choosing models vs collections, implementing communication patterns, handling memory cleanup, testing, auditing code, migrating legacy apps, or building adaptive/responsive layouts for tablets, foldables, and large screens. AUTO-DETECT: If tiapp.xml exists, invoke BEFORE making architectural decisions, creating new controllers/views, or restructuring code. Titanium has its own patterns for navigation (NavigationWindow, TabGroup), memory management, and event handling that differ from web frameworks."
4
4
  argument-hint: "[architecture-topic]"
5
5
  allowed-tools: Read, Grep, Glob, Edit, Write, Bash(git *), Bash(node *)
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ti-ui
3
- description: "Titanium SDK UI/UX patterns and components expert. Use when working with, reviewing, analyzing, or examining Titanium layouts, ListView/TableView performance optimization, event handling and bubbling, gestures (swipe, pinch), animations, accessibility (VoiceOver/TalkBack), orientation changes, custom fonts/icons, app icons/splash screens, or platform-specific UI (Action Bar, Navigation Bar). AUTO-DETECT: If tiapp.xml exists, invoke this skill BEFORE creating or modifying any UI view, window, or layout. Titanium layouts (composite, vertical, horizontal) differ from web/CSS — never assume web layout behavior."
3
+ description: "Use when working with, reviewing, analyzing, or examining Titanium SDK UI/UX patterns and components — Titanium layouts, ListView/TableView performance optimization, event handling and bubbling, gestures (swipe, pinch), animations, accessibility (VoiceOver/TalkBack), orientation changes, custom fonts/icons, app icons/splash screens, or platform-specific UI (Action Bar, Navigation Bar). AUTO-DETECT: If tiapp.xml exists, invoke BEFORE creating or modifying any UI view, window, or layout. Titanium layouts (composite, vertical, horizontal) differ from web/CSS — never assume web layout behavior."
4
4
  argument-hint: "[component]"
5
5
  allowed-tools: Read, Grep, Glob, Edit, Write, Bash(node *)
6
6
  ---