@rolandjlevy/css-ghost 1.1.1 → 1.1.3
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/README.md +44 -259
- package/package.json +3 -2
- package/src/parser.js +3 -3
package/README.md
CHANGED
|
@@ -6,42 +6,47 @@ Find and remove unused CSS selectors and orphaned CSS custom properties — sele
|
|
|
6
6
|
|
|
7
7
|
Scans one or more directories for style files, extracts every class selector defined, then cross-references them against usages in your component files. Anything defined but never used is reported as an orphan — with its line number and the actual CSS printed inline.
|
|
8
8
|
|
|
9
|
-
**Supported style files:**
|
|
9
|
+
**Supported style files:** `.css`, `.module.css`, `.scss`, `.sass`, `.less`, `.js`/`.ts` using `StyleSheet.create({})` / `makeStyles({})` (MUI), `.css.ts`/`.css.js` using `style()` or `styleVariants()` (vanilla-extract)
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- `.js` / `.ts` files using `StyleSheet.create({})`, `makeStyles({})` (MUI), or named style objects
|
|
13
|
-
- `.css.ts` / `.css.js` files using `style()` or `styleVariants()` (vanilla-extract)
|
|
11
|
+
**Detected usage patterns:** `className="foo"`, `className={styles.foo}`, `styles['foo']`, ternary patterns, `cx()` / `clsx()` / `classnames()` (strings, objects and arrays), `classes.foo` (MUI), vanilla-extract named imports
|
|
14
12
|
|
|
15
|
-
**
|
|
13
|
+
**Dynamic class detection:** Patterns where the class name can't be resolved statically — `styles[variable]` or template literals with `${}` — are flagged with a ⚠️ warning instead of being reported as orphans.
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
- `className={styles.foo}`
|
|
19
|
-
- `styles['foo']`
|
|
20
|
-
- `styles[condition ? 'foo' : 'bar']` — both branches extracted
|
|
21
|
-
- `cx('foo')`, `clsx('foo')`, `classnames('foo')`
|
|
22
|
-
- `cx({ active: isOn, disabled: true })` — object keys extracted
|
|
23
|
-
- `cx(['foo', condition && 'bar'])` — array string literals extracted
|
|
24
|
-
- `classes.foo` — MUI `makeStyles` / `useStyles` convention
|
|
25
|
-
- `import { foo } from './styles.css'` — vanilla-extract named imports
|
|
15
|
+
## How is this different from PurgeCSS?
|
|
26
16
|
|
|
27
|
-
**
|
|
28
|
-
Patterns where the class name is truly unknowable at parse time — `styles[variable]` or template literals containing `${}` — are flagged with a ⚠️ warning. All statically resolvable patterns (string literals, ternaries, object keys) are analysed without warnings.
|
|
17
|
+
[PurgeCSS](https://www.npmjs.com/package/purgecss) is a **build-time bundler** — it hooks into webpack, PostCSS, or Gulp to strip unused CSS from your production output. It's designed for removing large framework utility classes (Bootstrap, Tailwind) that you never use.
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
css-ghost can generate a plain English summary of your orphaned selectors using a free [OpenRouter](https://openrouter.ai) API key. Run the setup wizard once:
|
|
19
|
+
css-ghost is a **source code auditor** — it finds dead selectors in your actual codebase, with no build step and no config file required. Just point it at a folder:
|
|
33
20
|
|
|
34
21
|
```bash
|
|
35
|
-
css-ghost
|
|
22
|
+
npx @rolandjlevy/css-ghost ./src
|
|
36
23
|
```
|
|
37
24
|
|
|
38
|
-
|
|
25
|
+
| | PurgeCSS | css-ghost |
|
|
26
|
+
| --------------------------- | ----------------------------- | ---------------- |
|
|
27
|
+
| Works on source files | ❌ Build output only | ✅ |
|
|
28
|
+
| Zero config, no build step | ❌ Requires webpack / PostCSS | ✅ |
|
|
29
|
+
| CSS custom property orphans | ❌ | ✅ |
|
|
30
|
+
| Git history per orphan | ❌ | ✅ |
|
|
31
|
+
| Pre-commit hook | ❌ | ✅ |
|
|
32
|
+
| Deletes dead code for you | ❌ | ✅ |
|
|
33
|
+
| MUI / vanilla-extract aware | ❌ | ✅ |
|
|
34
|
+
| Safe with dynamic classes | ❌ Silently removes them | ✅ Flags with ⚠️ |
|
|
35
|
+
|
|
36
|
+
The two tools are complementary: PurgeCSS for trimming framework output at build time; css-ghost for auditing your own hand-written CSS throughout development.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## To enable AI features
|
|
41
|
+
|
|
42
|
+
Run the setup wizard once to save your free [OpenRouter](https://openrouter.ai) API key ([openrouter.ai/keys](https://openrouter.ai/keys)), then pass `--ai` to any scan:
|
|
39
43
|
|
|
40
44
|
```bash
|
|
45
|
+
css-ghost --setup
|
|
41
46
|
css-ghost ./src --ai
|
|
42
47
|
```
|
|
43
48
|
|
|
44
|
-
The AI summary appears in both the terminal output and the markdown report. The core scan always runs without a key
|
|
49
|
+
The AI summary appears in both the terminal output and the markdown report. The core scan always runs without a key.
|
|
45
50
|
|
|
46
51
|
## Install
|
|
47
52
|
|
|
@@ -77,44 +82,18 @@ css-ghost [directory] [directory2] ... [options]
|
|
|
77
82
|
|
|
78
83
|
## CSS variable orphan detection
|
|
79
84
|
|
|
80
|
-
css-ghost also catches **orphaned CSS custom properties** — variables defined with `--my-token: value` but never consumed
|
|
81
|
-
|
|
82
|
-
Usages are detected across all file types: CSS, SCSS, JS, TS, JSX, TSX, Vue, Svelte, HTML. A variable defined in `variables.css` and used in a React component is correctly seen as _used_.
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
🔮 --colour-danger-hover (line 8)
|
|
86
|
-
--colour-danger-hover: #dc2626;
|
|
87
|
-
|
|
88
|
-
🔮 --spacing-xl (line 26)
|
|
89
|
-
--spacing-xl: 64px;
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Orphaned variables appear under a separate **🔮 Orphaned CSS variables** section in both the terminal output and the markdown report.
|
|
93
|
-
|
|
94
|
-
---
|
|
85
|
+
css-ghost also catches **orphaned CSS custom properties** — variables defined with `--my-token: value` but never consumed via `var(--my-token)` anywhere in the codebase. Usages are detected across all file types: CSS, SCSS, JS, TS, JSX, TSX, Vue, Svelte, HTML. Orphaned variables appear under a **🔮 Orphaned CSS variables** section in both the terminal output and the markdown report.
|
|
95
86
|
|
|
96
87
|
## Ghost trail — git history for orphans
|
|
97
88
|
|
|
98
|
-
Pass `--ghost-trail` to fetch the last git commit that changed each orphan's occurrence count
|
|
89
|
+
Pass `--ghost-trail` to fetch the last git commit that changed each orphan's occurrence count:
|
|
99
90
|
|
|
100
91
|
```bash
|
|
101
92
|
css-ghost ./src --ghost-trail
|
|
102
93
|
```
|
|
103
94
|
|
|
104
|
-
```
|
|
105
|
-
👻 .iconRight (line 28)
|
|
106
|
-
🕵️ b5c6efb · Roland Levy · 3 weeks ago — "Refactor Button component"
|
|
107
|
-
.iconRight {
|
|
108
|
-
margin-left: 6px;
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
For CSS variables the search looks for `var(--name` across all file types.
|
|
113
|
-
|
|
114
95
|
> **Note:** ghost trail runs one `git log -S` per orphan in parallel. On large histories with many orphans it may take a few seconds.
|
|
115
96
|
|
|
116
|
-
---
|
|
117
|
-
|
|
118
97
|
## Pre-commit hook
|
|
119
98
|
|
|
120
99
|
Install a hook that blocks commits when orphaned selectors are present:
|
|
@@ -123,254 +102,60 @@ Install a hook that blocks commits when orphaned selectors are present:
|
|
|
123
102
|
css-ghost --install-hook ./src
|
|
124
103
|
```
|
|
125
104
|
|
|
126
|
-
This writes `.git/hooks/pre-commit` (executable, `chmod 755`)
|
|
127
|
-
|
|
128
|
-
```sh
|
|
129
|
-
#!/bin/sh
|
|
130
|
-
echo "👻 css-ghost — checking for orphaned CSS selectors..."
|
|
131
|
-
npx --yes @rolandjlevy/css-ghost ./src --strict --output /tmp/css-ghost-hook-report.md
|
|
132
|
-
|
|
133
|
-
if [ $? -ne 0 ]; then
|
|
134
|
-
echo "❌ Commit blocked: orphaned CSS selectors found"
|
|
135
|
-
echo " Run 'css-ghost ./src --delete' to remove them"
|
|
136
|
-
echo " Or skip: git commit --no-verify"
|
|
137
|
-
exit 1
|
|
138
|
-
fi
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Pass multiple directories to the hook installer the same way you would to a normal scan:
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
css-ghost --install-hook ./src ./components ./pages
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
To uninstall: `rm .git/hooks/pre-commit`
|
|
105
|
+
This writes `.git/hooks/pre-commit` (executable, `chmod 755`). Pass multiple directories the same way you would to a normal scan. To uninstall: `rm .git/hooks/pre-commit`
|
|
148
106
|
|
|
149
107
|
### `--strict` flag
|
|
150
108
|
|
|
151
|
-
|
|
109
|
+
Exit with code 1 when any orphans are found — the mechanism the hook depends on, also useful in CI:
|
|
152
110
|
|
|
153
111
|
```bash
|
|
154
|
-
# In CI: fail the build if orphans exist
|
|
155
112
|
css-ghost ./src --strict
|
|
156
113
|
```
|
|
157
114
|
|
|
158
|
-
---
|
|
159
|
-
|
|
160
115
|
## Interactive folder picker
|
|
161
116
|
|
|
162
|
-
Run `css-ghost` with no arguments
|
|
163
|
-
|
|
164
|
-
```
|
|
165
|
-
📂 Directory picker — navigate into a folder, then press [a] to add it
|
|
166
|
-
|
|
167
|
-
📍 /home/user/my-project
|
|
168
|
-
|
|
169
|
-
📁 components
|
|
170
|
-
▶ 📁 src
|
|
171
|
-
📁 styles
|
|
172
|
-
|
|
173
|
-
✅ Added to scan:
|
|
174
|
-
/home/user/my-project/src
|
|
175
|
-
|
|
176
|
-
[↑↓/jk] navigate [↵/→] enter [←] parent [a] add current dir [d] done [^C] quit
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
| Key | Action |
|
|
180
|
-
| ---------------------- | --------------------------------------- |
|
|
181
|
-
| `↑` / `↓` or `k` / `j` | Move up and down the folder list |
|
|
182
|
-
| `↵` or `→` | Enter the highlighted folder |
|
|
183
|
-
| `←` or Backspace | Go up to the parent folder |
|
|
184
|
-
| `a` | Add the current folder to the scan list |
|
|
185
|
-
| `d` | Done — start the scan |
|
|
186
|
-
| `Ctrl+C` | Quit without scanning |
|
|
187
|
-
|
|
188
|
-
You can add **multiple folders** before pressing `d` — just navigate to each one and press `a`. If you press `d` without adding anything, the folder you're currently browsing is used.
|
|
117
|
+
Run `css-ghost` with no arguments to open an arrow-key picker. Navigate with `↑↓`, enter with `↵`, press `a` to add the current folder to the scan list, `d` to start the scan. Add multiple folders before pressing `d`.
|
|
189
118
|
|
|
190
119
|
## Deleting orphans
|
|
191
120
|
|
|
192
|
-
Pass `--delete` after a scan to remove every flagged selector directly from its source file:
|
|
193
|
-
|
|
194
121
|
```bash
|
|
195
|
-
css-ghost ./src --delete
|
|
122
|
+
css-ghost ./src --delete # prints report, then asks for confirmation
|
|
123
|
+
css-ghost ./src --delete --yes # skip the prompt (CI / scripts)
|
|
196
124
|
```
|
|
197
125
|
|
|
198
|
-
css-ghost prints the full report first, then lists what will be deleted and asks for confirmation before touching anything. Pass `--yes` to skip the prompt (useful in CI or scripts):
|
|
199
|
-
|
|
200
|
-
```bash
|
|
201
|
-
css-ghost ./src --delete --yes
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
Works across all supported file types — `.css`, `.scss`, `.less`, MUI `makeStyles`, and vanilla-extract exports.
|
|
205
|
-
|
|
206
126
|
> **Tip:** commit or stash your work before running `--delete`. There is no undo.
|
|
207
127
|
|
|
208
128
|
## Examples
|
|
209
129
|
|
|
210
130
|
```bash
|
|
211
|
-
#
|
|
212
|
-
css-ghost
|
|
213
|
-
|
|
214
|
-
#
|
|
215
|
-
css-ghost ./src
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
css-ghost ./src
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
css-ghost ./src --strict
|
|
222
|
-
|
|
223
|
-
# Install a pre-commit hook that scans ./src
|
|
224
|
-
css-ghost --install-hook ./src
|
|
225
|
-
|
|
226
|
-
# Scan and delete all orphans (with confirmation prompt)
|
|
227
|
-
css-ghost ./src --delete
|
|
228
|
-
|
|
229
|
-
# Scan and delete without prompting
|
|
230
|
-
css-ghost ./src --delete --yes
|
|
231
|
-
|
|
232
|
-
# Scan multiple directories
|
|
233
|
-
css-ghost ./src ./components ./pages
|
|
234
|
-
|
|
235
|
-
# With AI summary
|
|
236
|
-
css-ghost ./src --ai
|
|
237
|
-
|
|
238
|
-
# Write report to a custom path
|
|
239
|
-
css-ghost ./src --output ./reports/css-audit.md
|
|
131
|
+
css-ghost # interactive folder picker
|
|
132
|
+
css-ghost ./src # scan a folder
|
|
133
|
+
css-ghost ./src --ghost-trail # show git history per orphan
|
|
134
|
+
css-ghost ./src --strict # CI: exit 1 on any orphan
|
|
135
|
+
css-ghost --install-hook ./src # install pre-commit hook
|
|
136
|
+
css-ghost ./src --delete # remove orphans (with prompt)
|
|
137
|
+
css-ghost ./src --delete --yes # remove without prompting
|
|
138
|
+
css-ghost ./src ./components ./pages # scan multiple directories
|
|
139
|
+
css-ghost ./src --ai # with AI summary
|
|
140
|
+
css-ghost ./src --output ./reports/audit.md
|
|
240
141
|
```
|
|
241
142
|
|
|
242
|
-
## CLI output
|
|
243
|
-
|
|
244
|
-
Running `css-ghost ./src` prints a live summary to your terminal:
|
|
245
|
-
|
|
246
|
-
```
|
|
247
|
-
✅ Report written to orphan-report.md
|
|
248
|
-
📊 3 orphaned selectors across 1 file
|
|
249
|
-
|
|
250
|
-
📄 src/components/Button/Button.module.css
|
|
251
|
-
👻 .iconLeft (line 4)
|
|
252
|
-
.iconLeft {
|
|
253
|
-
margin-right: 6px;
|
|
254
|
-
flex-shrink: 0;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
👻 .loadingSpinner (line 12)
|
|
258
|
-
.loadingSpinner {
|
|
259
|
-
animation: spin 0.8s linear infinite;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
👻 .disabled (line 18)
|
|
263
|
-
.disabled {
|
|
264
|
-
opacity: 0.4;
|
|
265
|
-
pointer-events: none;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
📁 1 style file scanned
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
Each orphan shows:
|
|
272
|
-
|
|
273
|
-
- the selector name and the **exact line number** where it's defined
|
|
274
|
-
- the **full CSS rule** so you can see what it does before deciding to delete it
|
|
275
|
-
|
|
276
|
-
## Markdown report
|
|
277
|
-
|
|
278
|
-
A full report is also written to `orphan-report.md` (or your `--output` path):
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
### 👻 Orphaned selectors
|
|
283
|
-
|
|
284
|
-
#### `.iconLeft` — line 4
|
|
285
|
-
|
|
286
|
-
```css
|
|
287
|
-
.iconLeft {
|
|
288
|
-
margin-right: 6px;
|
|
289
|
-
flex-shrink: 0;
|
|
290
|
-
}
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
#### `.loadingSpinner` — line 12
|
|
294
|
-
|
|
295
|
-
```css
|
|
296
|
-
.loadingSpinner {
|
|
297
|
-
animation: spin 0.8s linear infinite;
|
|
298
|
-
}
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
143
|
## Using with npm scripts
|
|
304
144
|
|
|
305
|
-
If you're working inside the project itself, add a `scan` script to `package.json`:
|
|
306
|
-
|
|
307
145
|
```json
|
|
308
146
|
"scripts": {
|
|
309
147
|
"scan": "css-ghost ./src"
|
|
310
148
|
}
|
|
311
149
|
```
|
|
312
150
|
|
|
313
|
-
Then run:
|
|
314
|
-
|
|
315
151
|
```bash
|
|
316
|
-
npm run scan
|
|
317
|
-
|
|
318
|
-
# Pass extra args with --
|
|
319
152
|
npm run scan -- --output ./reports/audit.md
|
|
320
153
|
```
|
|
321
154
|
|
|
322
|
-
## Troubleshooting
|
|
323
|
-
|
|
324
|
-
### `css-ghost: command not found` after global install
|
|
325
|
-
|
|
326
|
-
Your npm global bin directory may not be on your PATH. Run:
|
|
327
|
-
|
|
328
|
-
```bash
|
|
329
|
-
npm bin -g
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
Then add that path to your shell config (`~/.zshrc`, `~/.bashrc`, etc.):
|
|
333
|
-
|
|
334
|
-
```bash
|
|
335
|
-
export PATH="$(npm bin -g):$PATH"
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
Reload with `source ~/.zshrc`. This is a one-time fix — it won't be needed again after that.
|
|
339
|
-
|
|
340
|
-
> This is common when Node was installed via the official installer rather than nvm or Homebrew.
|
|
341
|
-
|
|
342
155
|
## Dependencies
|
|
343
156
|
|
|
344
157
|
One runtime dependency: [`picocolors`](https://github.com/alexeyraspopov/picocolors) for terminal colours. Everything else uses Node.js built-ins (`fs`, `path`, `readline`).
|
|
345
158
|
|
|
346
|
-
## Origin — built with OpenRouter free models via Claude Code
|
|
347
|
-
|
|
348
|
-
This tool was created as a test project to explore [using OpenRouter's free model tier with Claude Code](https://www.mindstudio.ai/blog/open-router-free-models-claude-code-cost-reduction) as a way to cut AI development costs.
|
|
349
|
-
|
|
350
|
-
Claude Code normally calls Anthropic's API directly. By overriding two environment variables you can route it through OpenRouter's free tier instead — meaning you can run agentic coding sessions at no cost.
|
|
351
|
-
|
|
352
|
-
If you've already run `css-ghost --setup`, you have an OpenRouter key. You can also export it as an environment variable — css-ghost picks it up automatically, so you don't even need `--setup`:
|
|
353
|
-
|
|
354
|
-
```bash
|
|
355
|
-
export OPENROUTER_API_KEY="sk-or-v1-YOUR_KEY"
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
And you can reuse the same key with Claude Code by adding these aliases to your `~/.zshrc`:
|
|
359
|
-
|
|
360
|
-
```bash
|
|
361
|
-
alias claude-free='ANTHROPIC_BASE_URL="https://openrouter.ai/api/v1" \
|
|
362
|
-
ANTHROPIC_API_KEY="$OPENROUTER_API_KEY" \
|
|
363
|
-
claude --model "nvidia/nemotron-3.5-lightning:free"'
|
|
364
|
-
|
|
365
|
-
alias claude-r1='ANTHROPIC_BASE_URL="https://openrouter.ai/api/v1" \
|
|
366
|
-
ANTHROPIC_API_KEY="$OPENROUTER_API_KEY" \
|
|
367
|
-
claude --model "qwen/qwen3.8-27b:free"'
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
Then `source ~/.zshrc`. Use `claude-free` or `claude-r1` in place of `claude` to start a free session.
|
|
371
|
-
|
|
372
|
-
> **Note:** Free model availability changes frequently. Browse current options at [openrouter.ai/models](https://openrouter.ai/models?q=free) — filter by `:free`.
|
|
373
|
-
|
|
374
159
|
## License
|
|
375
160
|
|
|
376
161
|
[MIT](./LICENSE)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rolandjlevy/css-ghost",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Find and remove unused CSS selectors and orphaned CSS custom properties — a CLI linter and auditor for React, Vue, Svelte, SCSS, and CSS Modules",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"vue",
|
|
37
37
|
"svelte",
|
|
38
38
|
"scss",
|
|
39
|
-
"css-modules"
|
|
39
|
+
"css-modules",
|
|
40
|
+
"purgecss"
|
|
40
41
|
],
|
|
41
42
|
"author": "Roland Levy",
|
|
42
43
|
"license": "MIT",
|
package/src/parser.js
CHANGED
|
@@ -259,14 +259,14 @@ export function extractUsages(content) {
|
|
|
259
259
|
used.add(m[1]);
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
// styles['foo'] or styles["foo"]
|
|
263
|
-
const bracketStringRegex = /styles?\[['"]([a-zA-Z_$][a-zA-Z0-9_
|
|
262
|
+
// styles['foo'] or styles["foo"] — includes hyphenated names (e.g. styles['btn-primary'])
|
|
263
|
+
const bracketStringRegex = /styles?\[['"]([a-zA-Z_$][a-zA-Z0-9_$-]*)['"]]/g;
|
|
264
264
|
while ((m = bracketStringRegex.exec(content)) !== null) {
|
|
265
265
|
used.add(m[1]);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
// styles[condition ? 'foo' : 'bar'] — ternary with string literals: extract both branches
|
|
269
|
-
const ternaryBracketRegex = /styles?\[\s*[^?]+\?\s*['"]([a-zA-Z_$][a-zA-Z0-9_
|
|
269
|
+
const ternaryBracketRegex = /styles?\[\s*[^?]+\?\s*['"]([a-zA-Z_$][a-zA-Z0-9_$-]*)["']\s*:\s*['"]([a-zA-Z_$][a-zA-Z0-9_$-]*)["']\s*\]/g;
|
|
270
270
|
while ((m = ternaryBracketRegex.exec(content)) !== null) {
|
|
271
271
|
used.add(m[1]);
|
|
272
272
|
used.add(m[2]);
|