@url-sanitize/cli 0.1.0 → 0.1.2
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/LICENSE +0 -6
- package/README.md +8 -1
- package/dist/bin.js +159 -35
- package/package.json +4 -4
package/LICENSE
CHANGED
|
@@ -19,9 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
-
|
|
23
|
-
Note: this MIT license applies to the @url-sanitize/core, @url-sanitize/cli,
|
|
24
|
-
@url-sanitize/fetch, and @url-sanitize/action packages. The
|
|
25
|
-
@url-sanitize/clearurls package ships a catalog derived from the ClearURLs
|
|
26
|
-
ruleset and is licensed under LGPL-3.0-only for that bundled data. See
|
|
27
|
-
packages/clearurls/LICENSE and docs/license-model.md for details.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @url-sanitize/cli
|
|
2
2
|
|
|
3
|
-
Command-line
|
|
3
|
+
Command-line tool for removing tracking parameters and unwrapping tracking redirects from URLs.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -18,8 +18,15 @@ url-sanitize "https://example.com/?utm_source=x"
|
|
|
18
18
|
|
|
19
19
|
url-sanitize --json "https://example.com/?utm_source=x"
|
|
20
20
|
# {"kind":"cleaned","original":"...","url":"...","strippedParams":["utm_source"],"matchedRules":[...]}
|
|
21
|
+
|
|
22
|
+
printf '%s\n' "https://example.com/?utm_source=x" | url-sanitize -
|
|
23
|
+
# https://example.com/
|
|
21
24
|
```
|
|
22
25
|
|
|
26
|
+
The npm CLI is pure TypeScript so it installs without native package setup. For
|
|
27
|
+
the smallest standalone binary, use `cargo install url-sanitize` or the GitHub
|
|
28
|
+
Release installer from the root README.
|
|
29
|
+
|
|
23
30
|
## License
|
|
24
31
|
|
|
25
32
|
MIT.
|
package/dist/bin.js
CHANGED
|
@@ -1,53 +1,177 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/bin.ts
|
|
4
|
-
import {
|
|
4
|
+
import { readFileSync } from "fs";
|
|
5
|
+
import { createRequire } from "module";
|
|
6
|
+
import { clearurlsCatalog, clearurlsMetadata } from "@url-sanitize/clearurls";
|
|
5
7
|
import { compileSanitizer } from "@url-sanitize/core";
|
|
6
8
|
var args = process.argv.slice(2);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
runTypeScriptCli(args);
|
|
10
|
+
function runTypeScriptCli(rawArgs) {
|
|
11
|
+
if (rawArgs.includes("-h") || rawArgs.includes("--help")) {
|
|
12
|
+
printHelp(process.stdout);
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
if (rawArgs.includes("--version")) {
|
|
16
|
+
process.stdout.write(
|
|
17
|
+
`url-sanitize ${packageVersion()} (catalog ${clearurlsMetadata.hash} ${clearurlsMetadata.fetchedAt})
|
|
18
|
+
`
|
|
19
|
+
);
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
const parsed = parseArgs(rawArgs);
|
|
23
|
+
if (typeof parsed === "string") {
|
|
24
|
+
process.stderr.write(`error: ${parsed}
|
|
25
|
+
`);
|
|
26
|
+
process.stderr.write("run `url-sanitize --help` for usage\n");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const sanitize = compileSanitizer(clearurlsCatalog, parsed.options);
|
|
30
|
+
let anyBlocked = false;
|
|
31
|
+
for (const url of parsed.urls) {
|
|
32
|
+
anyBlocked = emit(sanitize(url), parsed.json, parsed.explain) || anyBlocked;
|
|
33
|
+
}
|
|
34
|
+
if (parsed.readStdin || parsed.urls.length === 0 && !process.stdin.isTTY) {
|
|
35
|
+
const input = readAllStdin();
|
|
36
|
+
for (const line of input.split(/\r?\n/)) {
|
|
37
|
+
if (line.length === 0) continue;
|
|
38
|
+
anyBlocked = emit(sanitize(line), parsed.json, parsed.explain) || anyBlocked;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (parsed.urls.length === 0 && !parsed.readStdin && process.stdin.isTTY) {
|
|
42
|
+
printHelp(process.stderr);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
process.exit(anyBlocked ? 2 : 0);
|
|
10
46
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
47
|
+
function parseArgs(rawArgs) {
|
|
48
|
+
let json = false;
|
|
49
|
+
let explain = false;
|
|
50
|
+
let stripReferral = false;
|
|
51
|
+
let keepReferralExplicit = false;
|
|
52
|
+
let unwrapRedirects;
|
|
53
|
+
let domainBlocking = false;
|
|
54
|
+
let readStdin = false;
|
|
55
|
+
const urls = [];
|
|
56
|
+
for (const arg of rawArgs) {
|
|
57
|
+
switch (arg) {
|
|
58
|
+
case "--json":
|
|
59
|
+
json = true;
|
|
60
|
+
break;
|
|
61
|
+
case "--explain":
|
|
62
|
+
explain = true;
|
|
63
|
+
break;
|
|
64
|
+
case "--strip-referral":
|
|
65
|
+
stripReferral = true;
|
|
66
|
+
break;
|
|
67
|
+
case "--keep-referral":
|
|
68
|
+
keepReferralExplicit = true;
|
|
69
|
+
break;
|
|
70
|
+
case "--unwrap-redirects":
|
|
71
|
+
unwrapRedirects = true;
|
|
72
|
+
break;
|
|
73
|
+
case "--no-unwrap-redirects":
|
|
74
|
+
unwrapRedirects = false;
|
|
75
|
+
break;
|
|
76
|
+
case "--block-domains":
|
|
77
|
+
domainBlocking = true;
|
|
78
|
+
break;
|
|
79
|
+
case "-":
|
|
80
|
+
readStdin = true;
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
if (arg.startsWith("--") || arg.startsWith("-") && arg.length > 1) {
|
|
84
|
+
return `unknown flag: ${arg}`;
|
|
85
|
+
}
|
|
86
|
+
urls.push(arg);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (keepReferralExplicit) {
|
|
90
|
+
stripReferral = false;
|
|
91
|
+
}
|
|
92
|
+
const options = {
|
|
93
|
+
stripReferralMarketing: stripReferral,
|
|
94
|
+
domainBlocking
|
|
95
|
+
};
|
|
96
|
+
if (unwrapRedirects !== void 0) {
|
|
97
|
+
options.unwrapRedirects = unwrapRedirects;
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
json,
|
|
101
|
+
explain,
|
|
102
|
+
options,
|
|
103
|
+
readStdin,
|
|
104
|
+
urls
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function emit(result, json, explain) {
|
|
108
|
+
if (json) {
|
|
20
109
|
process.stdout.write(`${JSON.stringify(result)}
|
|
21
110
|
`);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
111
|
+
return result.kind === "blocked";
|
|
112
|
+
}
|
|
113
|
+
switch (result.kind) {
|
|
114
|
+
case "unchanged":
|
|
115
|
+
process.stdout.write(`${result.url}
|
|
26
116
|
`);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
process.stdout.write(`${result.url}
|
|
117
|
+
return false;
|
|
118
|
+
case "cleaned":
|
|
119
|
+
process.stdout.write(`${result.url}
|
|
31
120
|
`);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
process.stderr.write(
|
|
121
|
+
if (explain) {
|
|
122
|
+
const providers = result.matchedRules.map((rule) => rule.provider).join(",");
|
|
123
|
+
process.stderr.write(`# cleaned: ${result.original} -> ${result.url} [${providers}]
|
|
35
124
|
`);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
case "redirected":
|
|
128
|
+
process.stdout.write(`${result.url}
|
|
129
|
+
`);
|
|
130
|
+
if (explain) {
|
|
131
|
+
process.stderr.write(
|
|
132
|
+
`# redirected: ${result.original} -> ${result.url} [${result.via.provider}]
|
|
133
|
+
`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
case "blocked":
|
|
138
|
+
process.stderr.write(`blocked: ${result.original} (via ${result.via.provider})
|
|
139
|
+
`);
|
|
140
|
+
return true;
|
|
39
141
|
}
|
|
40
142
|
}
|
|
41
|
-
function
|
|
42
|
-
|
|
143
|
+
function readAllStdin() {
|
|
144
|
+
return readFileSync(0, "utf8");
|
|
145
|
+
}
|
|
146
|
+
function packageVersion() {
|
|
147
|
+
const require2 = createRequire(import.meta.url);
|
|
148
|
+
const pkg = require2("../package.json");
|
|
149
|
+
return pkg.version ?? "0.0.0";
|
|
150
|
+
}
|
|
151
|
+
function printHelp(stream) {
|
|
152
|
+
stream.write(
|
|
43
153
|
[
|
|
44
|
-
|
|
154
|
+
`url-sanitize ${packageVersion()} (catalog ${clearurlsMetadata.hash})`,
|
|
155
|
+
"",
|
|
156
|
+
"Strip tracking parameters from URLs.",
|
|
157
|
+
"",
|
|
158
|
+
"USAGE:",
|
|
159
|
+
" url-sanitize [OPTIONS] [URL]...",
|
|
160
|
+
" url-sanitize [OPTIONS] - read URLs from stdin (one per line)",
|
|
161
|
+
" url-sanitize [OPTIONS] < file same",
|
|
162
|
+
"",
|
|
163
|
+
"OPTIONS:",
|
|
164
|
+
" --json Emit one JSON SanitizeResult per input line",
|
|
165
|
+
" --explain Default mode, plus a matched-rule line on stderr",
|
|
166
|
+
" --strip-referral Strip affiliate / referral marketing params",
|
|
167
|
+
" --keep-referral Explicitly keep referral params (default)",
|
|
168
|
+
" --unwrap-redirects Unwrap redirector URLs (default)",
|
|
169
|
+
" --no-unwrap-redirects Leave redirector URLs untouched",
|
|
170
|
+
" --block-domains Emit blocked for domain-blocked URLs",
|
|
171
|
+
" --version Print version + catalog hash",
|
|
172
|
+
" -h, --help Show this help",
|
|
45
173
|
"",
|
|
46
|
-
"
|
|
47
|
-
" --json Emit JSON result objects (one per line)",
|
|
48
|
-
" --strip-referral Strip affiliate / referral marketing params (off by default)",
|
|
49
|
-
" --keep-referral Explicitly keep referral params (default)",
|
|
50
|
-
" -h, --help Show this help",
|
|
174
|
+
"Runtime: TypeScript",
|
|
51
175
|
""
|
|
52
176
|
].join("\n")
|
|
53
177
|
);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@url-sanitize/cli",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Command-line
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Command-line tool to remove tracking parameters and unwrap tracking redirects from URLs.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@url-sanitize/clearurls": "0.1.
|
|
15
|
-
"@url-sanitize/core": "0.1.
|
|
14
|
+
"@url-sanitize/clearurls": "0.1.2",
|
|
15
|
+
"@url-sanitize/core": "0.1.2"
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
18
|
"cli",
|