also looking at this
chore(deps): update actions/checkout action to v7
#34
11 files
+74
-15
| @@ -119,7 +119,7 @@ jobs: | ||
| 119 | 119 | if: ${{ needs.determine-jobs.outputs.run_check == 'true' || needs.determine-jobs.outputs.run_update == 'true' || needs.determine-jobs.outputs.run_dashboard == 'true' }} |
| 120 | 120 | steps: |
| 121 | 121 | - name: Checkout repository |
| 122 | uses: actions/checkout@v6 | |
| 122 | uses: actions/checkout@v7 | |
| 123 | 123 | with: |
| 124 | 124 | token: ${{ secrets.GITHUB_TOKEN }} |
| 125 | 125 | fetch-depth: 0 # Fetch full history for rebasing |
| @@ -156,7 +156,7 @@ jobs: | ||
| 156 | 156 | |
| 157 | 157 | steps: |
| 158 | 158 | - name: Checkout repository |
| 159 | uses: actions/checkout@v6 | |
| 159 | uses: actions/checkout@v7 | |
| 160 | 160 | with: |
| 161 | 161 | token: ${{ secrets.GITHUB_TOKEN }} |
| 162 | 162 | fetch-depth: 0 |
| @@ -237,7 +237,7 @@ jobs: | ||
| 237 | 237 | |
| 238 | 238 | steps: |
| 239 | 239 | - name: Checkout repository |
| 240 | uses: actions/checkout@v6 | |
| 240 | uses: actions/checkout@v7 | |
| 241 | 241 | with: |
| 242 | 242 | token: ${{ secrets.GITHUB_TOKEN }} |
| 243 | 243 | fetch-depth: 0 |
| @@ -346,7 +346,7 @@ jobs: | ||
| 346 | 346 | |
| 347 | 347 | steps: |
| 348 | 348 | - name: Checkout repository |
| 349 | uses: actions/checkout@v6 | |
| 349 | uses: actions/checkout@v7 | |
| 350 | 350 | with: |
| 351 | 351 | token: ${{ secrets.GITHUB_TOKEN }} |
| 352 | 352 | |
| @@ -18,7 +18,7 @@ jobs: | ||
| 18 | 18 | runs-on: ubuntu-latest |
| 19 | 19 | |
| 20 | 20 | steps: |
| 21 | - uses: actions/checkout@v6 | |
| 21 | - uses: actions/checkout@v7 | |
| 22 | 22 | |
| 23 | 23 | - name: Install Bun |
| 24 | 24 | uses: oven-sh/setup-bun@v2 |
| @@ -41,7 +41,7 @@ jobs: | ||
| 41 | 41 | runs-on: ubuntu-latest |
| 42 | 42 | |
| 43 | 43 | steps: |
| 44 | - uses: actions/checkout@v6 | |
| 44 | - uses: actions/checkout@v7 | |
| 45 | 45 | |
| 46 | 46 | - name: Install Bun |
| 47 | 47 | uses: oven-sh/setup-bun@v2 |
| @@ -64,7 +64,7 @@ jobs: | ||
| 64 | 64 | runs-on: ubuntu-latest |
| 65 | 65 | |
| 66 | 66 | steps: |
| 67 | - uses: actions/checkout@v6 | |
| 67 | - uses: actions/checkout@v7 | |
| 68 | 68 | |
| 69 | 69 | - name: Install Bun |
| 70 | 70 | uses: oven-sh/setup-bun@v2 |
| @@ -88,7 +88,7 @@ jobs: | ||
| 88 | 88 | runs-on: ubuntu-latest |
| 89 | 89 | |
| 90 | 90 | steps: |
| 91 | - uses: actions/checkout@v6 | |
| 91 | - uses: actions/checkout@v7 | |
| 92 | 92 | with: |
| 93 | 93 | fetch-depth: 0 |
| 94 | 94 | |
| @@ -1,3 +1,17 @@ | ||
| 1 | [Compare changes](https://github.com/stacksjs/ts-css/compare/v0.3.19...v0.3.20) | |
| 2 | ||
| 3 | ## 🐛 Bug Fixes | |
| 4 | ||
| 5 | - **engine**: read an icon class named by any markup attribute, not only class ([617955b](https://github.com/stacksjs/ts-css/commit/617955b)) _(by Chris Breuer <chrisbreuer93@gmail.com>)_ | |
| 6 | ||
| 7 | ## 🔧 Chores | |
| 8 | ||
| 9 | - release v0.3.20 ([6920a97](https://github.com/stacksjs/ts-css/commit/6920a97)) _(by Chris Breuer <chrisbreuer93@gmail.com>)_ | |
| 10 | ||
| 11 | ## Contributors | |
| 12 | ||
| 13 | - _Chris Breuer <chrisbreuer93@gmail.com>_ | |
| 14 | ||
| 1 | 15 | [Compare changes](https://github.com/stacksjs/ts-css/compare/v0.3.18...v0.3.19) |
| 2 | 16 | |
| 3 | 17 | ## 🐛 Bug Fixes |
bun.lockmodified+2-2
| @@ -11,7 +11,7 @@ | ||
| 11 | 11 | }, |
| 12 | 12 | "packages/toolkit": { |
| 13 | 13 | "name": "@stacksjs/ts-css", |
| 14 | "version": "0.3.19", | |
| 14 | "version": "0.3.20", | |
| 15 | 15 | "bin": { |
| 16 | 16 | "ts-css": "./dist/bin/cli.js", |
| 17 | 17 | "cssx": "./dist/bin/cssx.js", |
| @@ -34,7 +34,7 @@ | ||
| 34 | 34 | }, |
| 35 | 35 | "packages/vscode": { |
| 36 | 36 | "name": "@ts-css/vscode", |
| 37 | "version": "0.3.19", | |
| 37 | "version": "0.3.20", | |
| 38 | 38 | }, |
| 39 | 39 | }, |
| 40 | 40 | "overrides": { |
| @@ -2,7 +2,7 @@ | ||
| 2 | 2 | "name": "@ts-css/core", |
| 3 | 3 | "type": "module", |
| 4 | 4 | "sideEffects": false, |
| 5 | "version": "0.3.19", | |
| 5 | "version": "0.3.20", | |
| 6 | 6 | "description": "A blazingly fast utility-first CSS engine with a StyleX-style typed API. Tailwind-compatible utilities, zero runtime.", |
| 7 | 7 | "author": "Chris Breuer <chris@stacksjs.org>", |
| 8 | 8 | "license": "MIT", |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | { |
| 2 | 2 | "name": "@stacksjs/ts-css", |
| 3 | 3 | "type": "module", |
| 4 | "version": "0.3.19", | |
| 4 | "version": "0.3.20", | |
| 5 | 5 | "description": "Pure-TypeScript CSS toolkit and utility-first CSS engine for Bun/Node — parser, walker, generator, selector engine, minifier, and a Tailwind-compatible utility engine. Zero runtime deps.", |
| 6 | 6 | "author": "Chris Breuer <chris@stacksjs.org>", |
| 7 | 7 | "license": "MIT", |
| @@ -2267,6 +2267,14 @@ function extractCodeStringCandidates(content: string, bracketConfig?: BracketSyn | ||
| 2267 | 2267 | // payloads as code strings creates phantom utility classes and can make |
| 2268 | 2268 | // a classless fragment emit an entire preflight stylesheet. |
| 2269 | 2269 | if (markupAttribute) { |
| 2270 | // The one thing a prop value is allowed to name is an icon. A | |
| 2271 | // component takes its glyph as an attribute (`<EmptyState icon="i-...">`), | |
| 2272 | // and a rule that exists nowhere else on the page was never generated: | |
| 2273 | // the icon rendered as an empty box. An icon token cannot be a CSRF | |
| 2274 | // token, URL or v-html payload, and the generator only emits it when the | |
| 2275 | // icon exists, so reading it creates no phantom rule. | |
| 2276 | for (const token of literal.match(ICON_TOKEN) ?? []) | |
| 2277 | tokens.add(token) | |
| 2270 | 2278 | i = j |
| 2271 | 2279 | continue |
| 2272 | 2280 | } |
| @@ -2337,6 +2345,12 @@ function regexLiteralEnd(content: string, start: number): number { | ||
| 2337 | 2345 | return -1 |
| 2338 | 2346 | } |
| 2339 | 2347 | |
| 2348 | /** | |
| 2349 | * `i-<collection>-<name>`, however it is spelled inside a markup attribute: | |
| 2350 | * bare (`icon="i-lucide-x"`) or quoted inside a binding (`:icon="'i-lucide-x'"`). | |
| 2351 | */ | |
| 2352 | const ICON_TOKEN = /(?<![\w-])i-[a-z0-9]+(?:-[a-z0-9]+)+(?![\w-])/gi | |
| 2353 | ||
| 2340 | 2354 | function isMarkupAttributeString(content: string, quoteIndex: number): boolean { |
| 2341 | 2355 | const tagStart = content.lastIndexOf('<', quoteIndex) |
| 2342 | 2356 | const tagEnd = content.lastIndexOf('>', quoteIndex) |
| @@ -246,3 +246,34 @@ describe('code-string extraction past comments and regexes', () => { | ||
| 246 | 246 | expect(classes.has('gap-3')).toBe(true) |
| 247 | 247 | }) |
| 248 | 248 | }) |
| 249 | ||
| 250 | describe('icons named by a component prop', () => { | |
| 251 | it('takes an icon class out of any attribute, not only class', () => { | |
| 252 | const classes = extractClasses(`<MoreMenu icon="i-hugeicons-settings-02"><EmptyState icon="i-hugeicons-note-01" text="Nothing"/></MoreMenu>`) | |
| 253 | ||
| 254 | expect(classes.has('i-hugeicons-settings-02')).toBe(true) | |
| 255 | expect(classes.has('i-hugeicons-note-01')).toBe(true) | |
| 256 | }) | |
| 257 | ||
| 258 | it('takes one quoted inside a binding', () => { | |
| 259 | const classes = extractClasses(`<Row :icon="done ? 'i-hugeicons-tick-02' : 'i-hugeicons-circle'" />`) | |
| 260 | ||
| 261 | expect(classes.has('i-hugeicons-tick-02')).toBe(true) | |
| 262 | expect(classes.has('i-hugeicons-circle')).toBe(true) | |
| 263 | }) | |
| 264 | ||
| 265 | it('still ignores every other attribute value', () => { | |
| 266 | const classes = extractClasses(`<a href="/p/ab-cd-ef" data-token="abc-123-xyz" title="bg-red-500 shadow-lg">x</a>`) | |
| 267 | ||
| 268 | expect(classes.has('ab-cd-ef')).toBe(false) | |
| 269 | expect(classes.has('abc-123-xyz')).toBe(false) | |
| 270 | expect(classes.has('bg-red-500')).toBe(false) | |
| 271 | }) | |
| 272 | ||
| 273 | it('does not take a word that merely contains i-', () => { | |
| 274 | const classes = extractClasses(`<a title="semi-colon wi-fi pi-day">x</a>`) | |
| 275 | ||
| 276 | expect(classes.has('i-colon')).toBe(false) | |
| 277 | expect(classes.has('fi')).toBe(false) | |
| 278 | }) | |
| 279 | }) | |