@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 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 URL sanitizer.
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 { clearurlsCatalog } from "@url-sanitize/clearurls";
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
- if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
8
- printHelp();
9
- process.exit(args.length === 0 ? 1 : 0);
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
- var jsonMode = args.includes("--json");
12
- var stripReferral = args.includes("--keep-referral") ? false : args.includes("--strip-referral");
13
- var positional = args.filter((a) => !a.startsWith("--") && !a.startsWith("-"));
14
- var sanitize = compileSanitizer(clearurlsCatalog, {
15
- stripReferralMarketing: stripReferral
16
- });
17
- for (const url of positional) {
18
- const result = sanitize(url);
19
- if (jsonMode) {
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
- } else {
23
- switch (result.kind) {
24
- case "unchanged":
25
- process.stdout.write(`${result.url}
111
+ return result.kind === "blocked";
112
+ }
113
+ switch (result.kind) {
114
+ case "unchanged":
115
+ process.stdout.write(`${result.url}
26
116
  `);
27
- break;
28
- case "cleaned":
29
- case "redirected":
30
- process.stdout.write(`${result.url}
117
+ return false;
118
+ case "cleaned":
119
+ process.stdout.write(`${result.url}
31
120
  `);
32
- break;
33
- case "blocked":
34
- process.stderr.write(`blocked: ${result.original} (via ${result.via.provider})
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
- process.exitCode = 2;
37
- break;
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 printHelp() {
42
- process.stdout.write(
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
- "url-sanitize <url> [<url>...]",
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
- "Options:",
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.0",
4
- "description": "Command-line URL sanitizer for cleaning, explaining, and validating tracking-heavy URLs.",
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.0",
15
- "@url-sanitize/core": "0.1.0"
14
+ "@url-sanitize/clearurls": "0.1.2",
15
+ "@url-sanitize/core": "0.1.2"
16
16
  },
17
17
  "keywords": [
18
18
  "cli",