cssgrep 1.1.0 → 1.3.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/CHANGELOG.md +77 -1
- package/README.md +182 -7
- package/{index.js → cli.js} +593 -162
- package/completions/_cssgrep +10 -0
- package/completions/cssgrep.bash +2 -2
- package/completions/cssgrep.fish +10 -0
- package/index.d.ts +93 -0
- package/lib.js +403 -0
- package/man/cssgrep.1 +181 -12
- package/package.json +12 -9
package/man/cssgrep.1
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
.\" Man page for cssgrep. Keep the OPTIONS section in sync with the USAGE
|
|
2
|
-
.\" string in
|
|
3
|
-
.TH CSSGREP 1 "2026-07-
|
|
2
|
+
.\" string in cli.js.
|
|
3
|
+
.TH CSSGREP 1 "2026-07-07" "cssgrep 1.3.0" "User Commands"
|
|
4
4
|
.SH NAME
|
|
5
5
|
cssgrep \- search HTML by CSS selector, grep-style
|
|
6
6
|
.SH SYNOPSIS
|
|
@@ -13,6 +13,13 @@ cssgrep \- search HTML by CSS selector, grep-style
|
|
|
13
13
|
.B \-r
|
|
14
14
|
.IR dir ...
|
|
15
15
|
.br
|
|
16
|
+
.B cssgrep
|
|
17
|
+
.B \-e
|
|
18
|
+
.RI \(aq[ label =] sel \(aq
|
|
19
|
+
.RB [ \-e
|
|
20
|
+
\&...]
|
|
21
|
+
.RI [ file ...]
|
|
22
|
+
.br
|
|
16
23
|
.B cat
|
|
17
24
|
.I file.html
|
|
18
25
|
| \fBcssgrep\fR \fIselector\fR
|
|
@@ -33,9 +40,9 @@ Input is read from the
|
|
|
33
40
|
.I file
|
|
34
41
|
arguments, recursively from directories with
|
|
35
42
|
.BR \-r ,
|
|
36
|
-
or from standard input when no path is given. Binary
|
|
37
|
-
high ratio of control bytes in the first 8 KB)
|
|
38
|
-
standard error, suppressible with
|
|
43
|
+
or from standard input when no path is given. Binary input, including standard
|
|
44
|
+
input (a NUL byte or a high ratio of control bytes in the first 8 KB), is
|
|
45
|
+
skipped with a note on standard error, suppressible with
|
|
39
46
|
.B \-s
|
|
40
47
|
or
|
|
41
48
|
.BR \-q .
|
|
@@ -50,6 +57,31 @@ locator appears only with
|
|
|
50
57
|
.BR \-n .
|
|
51
58
|
.SH OPTIONS
|
|
52
59
|
.TP
|
|
60
|
+
.BR \-e ", " \-\-selector " [\fIlabel\fR=]\fIsel\fR"
|
|
61
|
+
Add a selector (repeatable). Matches from all
|
|
62
|
+
.B \-e
|
|
63
|
+
selectors merge into one document-order stream, each tagged
|
|
64
|
+
.RI [ label ]
|
|
65
|
+
in the output (and as a
|
|
66
|
+
.I label
|
|
67
|
+
field with
|
|
68
|
+
.BR \-\-json ).
|
|
69
|
+
An unlabeled selector is tagged with its own text. A label is an identifier
|
|
70
|
+
before a
|
|
71
|
+
.BR = ;
|
|
72
|
+
a
|
|
73
|
+
.B =
|
|
74
|
+
outside brackets is never valid CSS, so attribute selectors like
|
|
75
|
+
.I [href=x]
|
|
76
|
+
are never mistaken for labels.
|
|
77
|
+
.B \-m
|
|
78
|
+
and
|
|
79
|
+
.B \-M
|
|
80
|
+
cap the merged stream, and print modes apply to every selector alike. With
|
|
81
|
+
.BR \-e ,
|
|
82
|
+
every positional argument is a file path, as with
|
|
83
|
+
.BR "grep \-e" .
|
|
84
|
+
.TP
|
|
53
85
|
.BR \-r ", " \-\-recursive
|
|
54
86
|
Recurse into directory arguments (defaults to the current directory if none
|
|
55
87
|
are given).
|
|
@@ -91,10 +123,21 @@ one per line
|
|
|
91
123
|
comments and blank lines ignored), like a
|
|
92
124
|
.IR .gitignore .
|
|
93
125
|
.TP
|
|
126
|
+
.BR \-S ", " \-\-follow
|
|
127
|
+
Follow symbolic links while recursing with
|
|
128
|
+
.B \-r
|
|
129
|
+
(they are skipped by default). Each physical directory is visited once, so
|
|
130
|
+
symlink cycles are safe.
|
|
131
|
+
.TP
|
|
94
132
|
.BR \-n ", " \-\-line\-number
|
|
95
133
|
Prefix each match with its
|
|
96
134
|
.IR line : col
|
|
97
|
-
locator.
|
|
135
|
+
locator. The column counts bytes (what vim's
|
|
136
|
+
.B grepformat
|
|
137
|
+
.I %c
|
|
138
|
+
expects), pointing at the opening
|
|
139
|
+
.B <
|
|
140
|
+
of the matched tag. Excludes
|
|
98
141
|
.B \-c
|
|
99
142
|
and
|
|
100
143
|
.BR \-p .
|
|
@@ -107,14 +150,19 @@ locator is shown.
|
|
|
107
150
|
.BI \-\-attr " name"
|
|
108
151
|
Print the value of attribute
|
|
109
152
|
.I name
|
|
110
|
-
for each match (nodes without it are skipped
|
|
153
|
+
for each match (nodes without it are skipped; if every match is skipped the
|
|
154
|
+
exit status is 1). The name is matched case-insensitively.
|
|
111
155
|
.TP
|
|
112
156
|
.B \-\-text
|
|
113
157
|
Print the matched node's text content, whitespace collapsed.
|
|
114
158
|
.TP
|
|
115
159
|
.B \-\-json
|
|
116
160
|
Print one JSON object per match (NDJSON) with
|
|
117
|
-
.IR file ", " line ", " col ", " html ", " text
|
|
161
|
+
.IR file ", " line ", " col ", " html ", " text
|
|
162
|
+
(plus
|
|
163
|
+
.I label
|
|
164
|
+
with
|
|
165
|
+
.BR \-e ).
|
|
118
166
|
.TP
|
|
119
167
|
.BI \-\-parent " n"
|
|
120
168
|
Report the
|
|
@@ -149,10 +197,17 @@ matches per file.
|
|
|
149
197
|
.BR \-M ", " \-\-max\-total " \fIn\fR"
|
|
150
198
|
Stop after
|
|
151
199
|
.I n
|
|
152
|
-
matches in total across all files.
|
|
200
|
+
matches in total across all files. The budget counts matches, not files;
|
|
201
|
+
combined with
|
|
202
|
+
.B \-l
|
|
203
|
+
or
|
|
204
|
+
.B \-L
|
|
205
|
+
scanning stops once the budget is spent, which can cut the file list short.
|
|
153
206
|
.TP
|
|
154
207
|
.BR \-c ", " \-\-count
|
|
155
|
-
Print only a count of matches (per file when relevant).
|
|
208
|
+
Print only a count of matches (per file when relevant). Files with no match
|
|
209
|
+
report a zero count, as in
|
|
210
|
+
.BR grep .
|
|
156
211
|
.TP
|
|
157
212
|
.BR \-l ", " \-\-files\-with\-matches
|
|
158
213
|
Print only the names of files that have a match.
|
|
@@ -184,7 +239,12 @@ Colorize output:
|
|
|
184
239
|
A bare
|
|
185
240
|
.B \-\-color
|
|
186
241
|
means
|
|
187
|
-
.IR
|
|
242
|
+
.IR auto ,
|
|
243
|
+
as in
|
|
244
|
+
.BR grep ;
|
|
245
|
+
use
|
|
246
|
+
.B \-\-color=always
|
|
247
|
+
to force color into a pipe.
|
|
188
248
|
.TP
|
|
189
249
|
.BR \-h ", " \-\-help
|
|
190
250
|
Show help and exit.
|
|
@@ -208,10 +268,94 @@ Globs for
|
|
|
208
268
|
support
|
|
209
269
|
.BR * " (within a path segment), " ** " (across " / ),
|
|
210
270
|
.BR ? " (one non-slash char), and brace alternation like " *.{html,htm} .
|
|
271
|
+
.SH WATCH MODE
|
|
272
|
+
.TP
|
|
273
|
+
.B \-\-watch
|
|
274
|
+
Keep running and repeat the search whenever a watched file changes. Requires
|
|
275
|
+
file or directory arguments (standard input cannot be watched); cannot be
|
|
276
|
+
combined with
|
|
277
|
+
.B \-q
|
|
278
|
+
or the rewrite operations. Runs until interrupted; Ctrl-C exits with
|
|
279
|
+
status 0, like
|
|
280
|
+
.BR watch (1).
|
|
281
|
+
.TP
|
|
282
|
+
.B \-\-no\-clear
|
|
283
|
+
With
|
|
284
|
+
.B \-\-watch
|
|
285
|
+
on a terminal: append run results instead of clearing the screen.
|
|
286
|
+
.PP
|
|
287
|
+
Output adapts to its destination, like
|
|
288
|
+
.BR \-\-color=auto :
|
|
289
|
+
on a terminal each run clears the screen and reprints; piped output contains
|
|
290
|
+
no escape codes and appends each run after a
|
|
291
|
+
.RI \(dq== " HH:MM:SS changed-file " ==\(dq
|
|
292
|
+
separator; with
|
|
293
|
+
.B \-\-json
|
|
294
|
+
each rerun emits an NDJSON
|
|
295
|
+
.I {"event":"run","changed":...,"matches":n}
|
|
296
|
+
record followed by the match records.
|
|
297
|
+
.PP
|
|
298
|
+
Every rerun repeats the full directory walk, so new files are discovered (and
|
|
299
|
+
deleted ones dropped) under the same
|
|
300
|
+
.BR \-\-include / \-\-ignore / \-\-ext
|
|
301
|
+
rules as a fresh invocation; change bursts are debounced. Watching uses the
|
|
302
|
+
operating system's native file events (no polling), which may be unreliable
|
|
303
|
+
on network or virtual filesystems.
|
|
304
|
+
.SH REWRITING
|
|
305
|
+
Five repeatable, freely combinable operations edit the matched elements
|
|
306
|
+
instead of reporting them:
|
|
307
|
+
.TP
|
|
308
|
+
.BI \-\-add\-class " c"
|
|
309
|
+
Add a class to each matched element (deduplicated; attribute created if
|
|
310
|
+
missing).
|
|
311
|
+
.TP
|
|
312
|
+
.BI \-\-remove\-class " c"
|
|
313
|
+
Remove a class; the attribute is dropped when emptied.
|
|
314
|
+
.TP
|
|
315
|
+
.BI \-\-set\-attr " k=v"
|
|
316
|
+
Set attribute
|
|
317
|
+
.I k
|
|
318
|
+
to
|
|
319
|
+
.IR v ,
|
|
320
|
+
adding it if missing. The value is escaped.
|
|
321
|
+
.TP
|
|
322
|
+
.BI \-\-remove\-attr " k"
|
|
323
|
+
Remove attribute
|
|
324
|
+
.I k
|
|
325
|
+
(all source occurrences).
|
|
326
|
+
.TP
|
|
327
|
+
.BI \-\-rename\-tag " t"
|
|
328
|
+
Rename the element \(em its closing tag too, when one explicitly exists
|
|
329
|
+
(voids like
|
|
330
|
+
.IR <img> ,
|
|
331
|
+
self-closing and implied closes are left without one).
|
|
332
|
+
.TP
|
|
333
|
+
.B \-\-diff
|
|
334
|
+
Emit a unified diff instead of the rewritten document. Required for multiple
|
|
335
|
+
files; apply with
|
|
336
|
+
.BR git-apply (1)
|
|
337
|
+
or
|
|
338
|
+
.BR patch (1).
|
|
339
|
+
.PP
|
|
340
|
+
Only the matched tags' bytes change: matching runs once against the original
|
|
341
|
+
document and edits are byte-splices, so quoting, entities and formatting
|
|
342
|
+
everywhere else pass through untouched. Operations compose in a fixed order
|
|
343
|
+
\(em rename \(-> remove-attr \(-> set-attr \(-> remove-class \(-> add-class
|
|
344
|
+
\(em regardless of argument order.
|
|
345
|
+
.B \-\-parent
|
|
346
|
+
composes with rewriting. A single input prints the rewritten document to
|
|
347
|
+
standard output;
|
|
348
|
+
.B cssgrep
|
|
349
|
+
never writes a file. Input that is not valid UTF-8 is refused (exit 2).
|
|
350
|
+
Rewriting cannot be combined with
|
|
351
|
+
.BR \-n ", " \-p ", " \-\-attr ", " \-\-text ", " \-\-json ", " \-c ", "
|
|
352
|
+
.BR \-l ", " \-L ", " \-q ", " \-A / \-B / \-C ", " \-m / \-M ", " \-w ", "
|
|
353
|
+
.BR \-0 " or " \-e .
|
|
354
|
+
Exit status: 0 if anything was edited, 1 if nothing matched, 2 on error.
|
|
211
355
|
.SH EXIT STATUS
|
|
212
356
|
.TP
|
|
213
357
|
.B 0
|
|
214
|
-
One or more matches were found.
|
|
358
|
+
One or more matches were found (or, when rewriting, edits were made).
|
|
215
359
|
.TP
|
|
216
360
|
.B 1
|
|
217
361
|
No matches were found.
|
|
@@ -231,6 +375,31 @@ Recurse a tree, skipping vendored files:
|
|
|
231
375
|
.TP
|
|
232
376
|
Extract attribute values for scripting:
|
|
233
377
|
.B cssgrep \-\-attr href "a.external" page.html
|
|
378
|
+
.TP
|
|
379
|
+
Scrape several labeled fields in one pass:
|
|
380
|
+
.B cssgrep \-e "title=h1" \-e "price=.card .price" \-\-json page.html
|
|
381
|
+
.TP
|
|
382
|
+
Rename every <b> to <strong> across a tree, review, then apply:
|
|
383
|
+
.B cssgrep b \-\-rename\-tag strong \-r src/ \-\-diff | git apply
|
|
384
|
+
.SH INVERTING MATCHES
|
|
385
|
+
There is no
|
|
386
|
+
.B \-v
|
|
387
|
+
flag: CSS expresses inversion in the selector itself via
|
|
388
|
+
.BR :not() " (complex selectors and selector lists included) and " :has() ,
|
|
389
|
+
scoped to the elements of interest \(em a flag would have to invent its own
|
|
390
|
+
answer to \(lqwhich non-matching elements?\(rq.
|
|
391
|
+
.TP
|
|
392
|
+
Images missing alt text:
|
|
393
|
+
.B cssgrep \(dqimg:not([alt])\(dq \-rn .
|
|
394
|
+
.TP
|
|
395
|
+
Cards containing no link:
|
|
396
|
+
.B cssgrep \(dqdiv.card:not(:has(a))\(dq page.html
|
|
397
|
+
.TP
|
|
398
|
+
Links outside nav and footer:
|
|
399
|
+
.B cssgrep \(dqa:not(nav a, footer a)\(dq page.html
|
|
400
|
+
.PP
|
|
401
|
+
For whole files without any match, use
|
|
402
|
+
.BR \-L .
|
|
234
403
|
.SH VIM INTEGRATION
|
|
235
404
|
Wire
|
|
236
405
|
.B cssgrep
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cssgrep",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Search HTML by CSS selector and print matches grep-style (file:line:col with -n).",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "lib.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
6
7
|
"bin": {
|
|
7
|
-
"cssgrep": "
|
|
8
|
+
"cssgrep": "cli.js"
|
|
8
9
|
},
|
|
9
10
|
"man": "./man/cssgrep.1",
|
|
10
11
|
"files": [
|
|
11
|
-
"
|
|
12
|
+
"lib.js",
|
|
13
|
+
"cli.js",
|
|
14
|
+
"index.d.ts",
|
|
12
15
|
"README.md",
|
|
13
16
|
"CHANGELOG.md",
|
|
14
17
|
"LICENSE",
|
|
@@ -28,11 +31,11 @@
|
|
|
28
31
|
"homepage": "https://github.com/msbatarce/cssgrep#readme",
|
|
29
32
|
"scripts": {
|
|
30
33
|
"test": "node test.js",
|
|
31
|
-
"build:linux-x64": "bun build ./
|
|
32
|
-
"build:linux-arm64": "bun build ./
|
|
33
|
-
"build:darwin-x64": "bun build ./
|
|
34
|
-
"build:darwin-arm64": "bun build ./
|
|
35
|
-
"build:windows-x64": "bun build ./
|
|
34
|
+
"build:linux-x64": "bun build ./cli.js --compile --target=bun-linux-x64 --outfile dist/cssgrep-linux-x64",
|
|
35
|
+
"build:linux-arm64": "bun build ./cli.js --compile --target=bun-linux-arm64 --outfile dist/cssgrep-linux-arm64",
|
|
36
|
+
"build:darwin-x64": "bun build ./cli.js --compile --target=bun-darwin-x64 --outfile dist/cssgrep-darwin-x64",
|
|
37
|
+
"build:darwin-arm64": "bun build ./cli.js --compile --target=bun-darwin-arm64 --outfile dist/cssgrep-darwin-arm64",
|
|
38
|
+
"build:windows-x64": "bun build ./cli.js --compile --target=bun-windows-x64 --outfile dist/cssgrep-windows-x64.exe",
|
|
36
39
|
"build:binaries": "npm run build:linux-x64 && npm run build:linux-arm64 && npm run build:darwin-x64 && npm run build:darwin-arm64 && npm run build:windows-x64",
|
|
37
40
|
"build:sea": "node scripts/build-sea.js"
|
|
38
41
|
},
|