Skip to content

Commit 2c8c00b

Browse files
committed
feat: add is_custm(str: string): boolean helper
1 parent 757909c commit 2c8c00b

File tree

4 files changed

+111
-0
lines changed

4 files changed

+111
-0
lines changed

API.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- `parse_selector`
55
- `parse_atrule_prelude`
66
- `walk`
7+
- `is_custom`
78
- `tokenize`
89

910
---
@@ -799,6 +800,49 @@ traverse(ast, {
799800

800801
---
801802

803+
## `is_custom(str)`
804+
805+
Check if a string is a CSS custom property (starts with `--`).
806+
807+
### Signature
808+
809+
```typescript
810+
function is_custom(str: string): boolean
811+
```
812+
813+
### Parameters
814+
815+
- **`str`** (`string`) - The string to check
816+
817+
### Returns
818+
819+
`boolean` - `true` if the string starts with `--` (custom property), `false` otherwise
820+
821+
### Examples
822+
823+
```typescript
824+
import { parse, is_custom } from '@projectwallace/css-parser'
825+
826+
const ast = parse(':root { --primary: blue; color: red; }')
827+
const block = ast.first_child.block
828+
829+
for (const decl of block.children) {
830+
if (is_custom(decl.name)) {
831+
console.log('Custom property:', decl.name) // Logs: "--primary"
832+
} else {
833+
console.log('Standard property:', decl.name) // Logs: "color"
834+
}
835+
}
836+
837+
// Direct usage
838+
is_custom('--primary-color') // true
839+
is_custom('--my-var') // true
840+
is_custom('color') // false
841+
is_custom('-webkit-transform') // false (vendor prefix, not custom)
842+
```
843+
844+
---
845+
802846
## `tokenize(source, skip_comments?)`
803847

804848
Tokenize CSS source code into a stream of tokens.

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export { parse_declaration } from './parse-declaration'
88
export { parse_value } from './parse-value'
99
export { tokenize } from './tokenize'
1010
export { walk, traverse, SKIP, BREAK } from './walk'
11+
export { is_custom } from './string-utils'
1112

1213
// Advanced/class-based API
1314
export { type ParserOptions } from './parse'

src/string-utils.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
str_starts_with,
66
str_index_of,
77
is_vendor_prefixed,
8+
is_custom,
89
CHAR_SPACE,
910
CHAR_TAB,
1011
CHAR_NEWLINE,
@@ -350,6 +351,52 @@ describe('string-utils', () => {
350351
expect(is_vendor_prefixed(source, 6, 20)).toBe(true) // "-webkit-suffix"
351352
})
352353
})
354+
355+
describe('is_custom', () => {
356+
it('should detect custom property with --', () => {
357+
expect(is_custom('--primary-color')).toBe(true)
358+
})
359+
360+
it('should detect another custom property', () => {
361+
expect(is_custom('--my-var')).toBe(true)
362+
})
363+
364+
it('should detect shortest valid custom property', () => {
365+
expect(is_custom('--x')).toBe(true)
366+
})
367+
368+
it('should not detect exactly two hyphens', () => {
369+
expect(is_custom('--')).toBe(false)
370+
})
371+
372+
it('should not detect vendor prefix as custom', () => {
373+
expect(is_custom('-webkit-transform')).toBe(false)
374+
})
375+
376+
it('should not detect -moz- vendor prefix as custom', () => {
377+
expect(is_custom('-moz-appearance')).toBe(false)
378+
})
379+
380+
it('should not detect standard property with hyphen as custom', () => {
381+
expect(is_custom('border-radius')).toBe(false)
382+
})
383+
384+
it('should not detect standard property as custom', () => {
385+
expect(is_custom('color')).toBe(false)
386+
})
387+
388+
it('should not detect single hyphen as custom', () => {
389+
expect(is_custom('-')).toBe(false)
390+
})
391+
392+
it('should not detect empty string as custom', () => {
393+
expect(is_custom('')).toBe(false)
394+
})
395+
396+
it('should not detect single character as custom', () => {
397+
expect(is_custom('a')).toBe(false)
398+
})
399+
})
353400
})
354401

355402
describe('str_index_of', () => {

src/string-utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,22 @@ export function is_vendor_prefixed(source: string, start?: number, end?: number)
199199
}
200200
return false
201201
}
202+
203+
/**
204+
* Check if a string is a CSS custom property (starts with --)
205+
*
206+
* @param str - The string to check
207+
* @returns true if the string starts with -- (custom property)
208+
*
209+
* Examples:
210+
* - `--primary-color` → true
211+
* - `--my-var` → true
212+
* - `-webkit-transform` → false (vendor prefix, not custom)
213+
* - `border-radius` → false (standard property)
214+
* - `color` → false
215+
*/
216+
export function is_custom(str: string): boolean {
217+
// Must start with two hyphens and have at least one character after
218+
if (str.length < 3) return false
219+
return str.charCodeAt(0) === CHAR_MINUS_HYPHEN && str.charCodeAt(1) === CHAR_MINUS_HYPHEN
220+
}

0 commit comments

Comments
 (0)