url-sanitize 0.1.2__tar.gz
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.
- url_sanitize-0.1.2/.changeset/config.json +11 -0
- url_sanitize-0.1.2/.github/ISSUE_TEMPLATE/broken-url.yml +34 -0
- url_sanitize-0.1.2/.github/ISSUE_TEMPLATE/rule-source-request.yml +25 -0
- url_sanitize-0.1.2/.github/workflows/auto-tag.yml +35 -0
- url_sanitize-0.1.2/.github/workflows/ci.yml +63 -0
- url_sanitize-0.1.2/.github/workflows/release.yml +203 -0
- url_sanitize-0.1.2/.github/workflows/sync-clearurls.yml +64 -0
- url_sanitize-0.1.2/.gitignore +23 -0
- url_sanitize-0.1.2/.husky/pre-commit +4 -0
- url_sanitize-0.1.2/.husky/pre-push +4 -0
- url_sanitize-0.1.2/.npmrc +1 -0
- url_sanitize-0.1.2/AGENTS.md +95 -0
- url_sanitize-0.1.2/CLAUDE.md +1 -0
- url_sanitize-0.1.2/CONTRIBUTING.md +47 -0
- url_sanitize-0.1.2/Cargo.lock +403 -0
- url_sanitize-0.1.2/Cargo.toml +26 -0
- url_sanitize-0.1.2/LICENSE +21 -0
- url_sanitize-0.1.2/PKG-INFO +42 -0
- url_sanitize-0.1.2/README.md +154 -0
- url_sanitize-0.1.2/biome.json +29 -0
- url_sanitize-0.1.2/catalog/clearurls.json +10811 -0
- url_sanitize-0.1.2/conformance/clearurls-corpus.jsonl +46 -0
- url_sanitize-0.1.2/conformance/conformance.test.ts +168 -0
- url_sanitize-0.1.2/conformance/inputs/corpus.txt +69 -0
- url_sanitize-0.1.2/conformance/inputs/vectors.jsonl +32 -0
- url_sanitize-0.1.2/conformance/manifest.json +17 -0
- url_sanitize-0.1.2/conformance/properties.md +96 -0
- url_sanitize-0.1.2/conformance/schema.json +81 -0
- url_sanitize-0.1.2/conformance/vectors.jsonl +32 -0
- url_sanitize-0.1.2/crates/url-sanitize/Cargo.toml +22 -0
- url_sanitize-0.1.2/crates/url-sanitize/README.md +22 -0
- url_sanitize-0.1.2/crates/url-sanitize/catalog/clearurls.json +10811 -0
- url_sanitize-0.1.2/crates/url-sanitize/src/main.rs +241 -0
- url_sanitize-0.1.2/crates/url-sanitize/tests/conformance.rs +194 -0
- url_sanitize-0.1.2/crates/url-sanitize-core/Cargo.toml +20 -0
- url_sanitize-0.1.2/crates/url-sanitize-core/README.md +21 -0
- url_sanitize-0.1.2/crates/url-sanitize-core/src/catalog.rs +55 -0
- url_sanitize-0.1.2/crates/url-sanitize-core/src/compile.rs +165 -0
- url_sanitize-0.1.2/crates/url-sanitize-core/src/lib.rs +14 -0
- url_sanitize-0.1.2/crates/url-sanitize-core/src/sanitize.rs +194 -0
- url_sanitize-0.1.2/crates/url-sanitize-core/src/types.rs +113 -0
- url_sanitize-0.1.2/docs/clearurls-compat.md +65 -0
- url_sanitize-0.1.2/docs/license-model.md +39 -0
- url_sanitize-0.1.2/docs/non-goals.md +48 -0
- url_sanitize-0.1.2/docs/roadmap.md +309 -0
- url_sanitize-0.1.2/docs/spec.md +273 -0
- url_sanitize-0.1.2/docs/threat-model.md +37 -0
- url_sanitize-0.1.2/package.json +63 -0
- url_sanitize-0.1.2/packages/clearurls/LICENSE +33 -0
- url_sanitize-0.1.2/packages/clearurls/NOTICE +14 -0
- url_sanitize-0.1.2/packages/clearurls/README.md +40 -0
- url_sanitize-0.1.2/packages/clearurls/data/data.json +1984 -0
- url_sanitize-0.1.2/packages/clearurls/data/metadata.json +6 -0
- url_sanitize-0.1.2/packages/clearurls/package.json +38 -0
- url_sanitize-0.1.2/packages/clearurls/src/adapter.ts +84 -0
- url_sanitize-0.1.2/packages/clearurls/src/index.ts +18 -0
- url_sanitize-0.1.2/packages/clearurls/src/raw.ts +6 -0
- url_sanitize-0.1.2/packages/clearurls/src/types.ts +21 -0
- url_sanitize-0.1.2/packages/clearurls/tsconfig.json +9 -0
- url_sanitize-0.1.2/packages/cli/README.md +32 -0
- url_sanitize-0.1.2/packages/cli/package.json +28 -0
- url_sanitize-0.1.2/packages/cli/src/bin.ts +195 -0
- url_sanitize-0.1.2/packages/cli/tsconfig.json +9 -0
- url_sanitize-0.1.2/packages/core/README.md +47 -0
- url_sanitize-0.1.2/packages/core/package.json +31 -0
- url_sanitize-0.1.2/packages/core/src/index.ts +10 -0
- url_sanitize-0.1.2/packages/core/src/sanitize.ts +292 -0
- url_sanitize-0.1.2/packages/core/src/types.ts +84 -0
- url_sanitize-0.1.2/packages/core/test/sanitize.test.ts +83 -0
- url_sanitize-0.1.2/packages/core/tsconfig.json +9 -0
- url_sanitize-0.1.2/pnpm-lock.yaml +2694 -0
- url_sanitize-0.1.2/pnpm-workspace.yaml +5 -0
- url_sanitize-0.1.2/pyproject.toml +34 -0
- url_sanitize-0.1.2/python/README.md +20 -0
- url_sanitize-0.1.2/python/url_sanitize/__init__.py +55 -0
- url_sanitize-0.1.2/python/url_sanitize/__main__.py +15 -0
- url_sanitize-0.1.2/python/url_sanitize/bin/.gitkeep +1 -0
- url_sanitize-0.1.2/scripts/build-catalog.ts +34 -0
- url_sanitize-0.1.2/scripts/build-conformance.ts +163 -0
- url_sanitize-0.1.2/scripts/bump-version.mjs +40 -0
- url_sanitize-0.1.2/scripts/install.ps1 +25 -0
- url_sanitize-0.1.2/scripts/install.sh +29 -0
- url_sanitize-0.1.2/scripts/pre-push.sh +13 -0
- url_sanitize-0.1.2/sources/clearurls/sync.ts +104 -0
- url_sanitize-0.1.2/tsconfig.base.json +22 -0
- url_sanitize-0.1.2/tsconfig.json +5 -0
- url_sanitize-0.1.2/vitest.config.ts +7 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
|
|
3
|
+
"changelog": "@changesets/cli/changelog",
|
|
4
|
+
"commit": false,
|
|
5
|
+
"fixed": [],
|
|
6
|
+
"linked": [],
|
|
7
|
+
"access": "public",
|
|
8
|
+
"baseBranch": "main",
|
|
9
|
+
"updateInternalDependencies": "patch",
|
|
10
|
+
"ignore": []
|
|
11
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Broken URL / bad cleanup
|
|
2
|
+
description: A URL produces wrong output (over-strips, under-strips, garbles)
|
|
3
|
+
title: '[broken-url] '
|
|
4
|
+
labels: [bug, broken-url]
|
|
5
|
+
body:
|
|
6
|
+
- type: input
|
|
7
|
+
id: input-url
|
|
8
|
+
attributes:
|
|
9
|
+
label: Input URL
|
|
10
|
+
description: Paste the URL fed to url-sanitize.
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: input
|
|
14
|
+
id: expected
|
|
15
|
+
attributes:
|
|
16
|
+
label: Expected output URL
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: input
|
|
20
|
+
id: actual
|
|
21
|
+
attributes:
|
|
22
|
+
label: Actual output URL
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
25
|
+
- type: input
|
|
26
|
+
id: version
|
|
27
|
+
attributes:
|
|
28
|
+
label: '@url-sanitize/clearurls version (from metadata.json)'
|
|
29
|
+
validations:
|
|
30
|
+
required: true
|
|
31
|
+
- type: textarea
|
|
32
|
+
id: notes
|
|
33
|
+
attributes:
|
|
34
|
+
label: Notes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Rule source request
|
|
2
|
+
description: Request support for a non-ClearURLs rule source (AdGuard, Brave, Firefox, custom)
|
|
3
|
+
title: '[source] '
|
|
4
|
+
labels: [enhancement, rule-source]
|
|
5
|
+
body:
|
|
6
|
+
- type: input
|
|
7
|
+
id: source
|
|
8
|
+
attributes:
|
|
9
|
+
label: Source name
|
|
10
|
+
description: e.g. AdGuard URL Tracking Protection, Brave Debouncer
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: input
|
|
14
|
+
id: source-url
|
|
15
|
+
attributes:
|
|
16
|
+
label: Upstream URL
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: use-case
|
|
21
|
+
attributes:
|
|
22
|
+
label: Use case
|
|
23
|
+
description: What does this source cover that ClearURLs doesn't?
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: auto-tag
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'packages/core/package.json'
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
actions: write
|
|
11
|
+
contents: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
tag:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Read version
|
|
20
|
+
id: version
|
|
21
|
+
run: echo "version=$(node -p "require('./packages/core/package.json').version")" >> "$GITHUB_OUTPUT"
|
|
22
|
+
|
|
23
|
+
- name: Create and push tag if missing
|
|
24
|
+
env:
|
|
25
|
+
TAG: v${{ steps.version.outputs.version }}
|
|
26
|
+
run: |
|
|
27
|
+
if git ls-remote --tags origin "$TAG" | grep -q "$TAG"; then
|
|
28
|
+
echo "Tag $TAG already exists — skipping"
|
|
29
|
+
else
|
|
30
|
+
git config user.name "github-actions[bot]"
|
|
31
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
32
|
+
git tag -a "$TAG" -m "release $TAG"
|
|
33
|
+
git push origin "$TAG"
|
|
34
|
+
gh workflow run release.yml --ref "$TAG"
|
|
35
|
+
fi
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- '**/*.md'
|
|
8
|
+
- 'docs/**'
|
|
9
|
+
- 'AGENTS.md'
|
|
10
|
+
- 'LICENSE'
|
|
11
|
+
- 'NOTICE'
|
|
12
|
+
pull_request:
|
|
13
|
+
paths-ignore:
|
|
14
|
+
- '**/*.md'
|
|
15
|
+
- 'docs/**'
|
|
16
|
+
- 'AGENTS.md'
|
|
17
|
+
- 'LICENSE'
|
|
18
|
+
- 'NOTICE'
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
ts:
|
|
22
|
+
name: TypeScript engine + conformance
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: pnpm/action-setup@v4
|
|
27
|
+
- uses: actions/setup-node@v4
|
|
28
|
+
with:
|
|
29
|
+
node-version: '22'
|
|
30
|
+
cache: 'pnpm'
|
|
31
|
+
- run: pnpm install --frozen-lockfile
|
|
32
|
+
- run: pnpm build
|
|
33
|
+
- name: Verify generated catalog matches checked-in catalog
|
|
34
|
+
run: |
|
|
35
|
+
pnpm build:catalog
|
|
36
|
+
git diff --exit-code catalog/clearurls.json \
|
|
37
|
+
|| (echo "catalog/clearurls.json is stale — run \`pnpm build:catalog\` and commit" && exit 1)
|
|
38
|
+
- name: Verify generated conformance corpus matches checked-in files
|
|
39
|
+
run: |
|
|
40
|
+
pnpm build:conformance
|
|
41
|
+
git diff --exit-code conformance/vectors.jsonl conformance/clearurls-corpus.jsonl conformance/manifest.json \
|
|
42
|
+
|| (echo "conformance corpus is stale — run \`pnpm build:conformance\` and commit" && exit 1)
|
|
43
|
+
- run: pnpm typecheck
|
|
44
|
+
- run: pnpm test
|
|
45
|
+
- run: pnpm lint
|
|
46
|
+
|
|
47
|
+
rust:
|
|
48
|
+
name: Rust engine + conformance
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v4
|
|
52
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
53
|
+
- uses: Swatinem/rust-cache@v2
|
|
54
|
+
- run: cargo build --workspace --all-targets
|
|
55
|
+
- run: cargo test --workspace
|
|
56
|
+
- name: Release binary size check
|
|
57
|
+
run: |
|
|
58
|
+
cargo build --release -p url-sanitize
|
|
59
|
+
ls -lh target/release/url-sanitize
|
|
60
|
+
size=$(stat -c%s target/release/url-sanitize)
|
|
61
|
+
echo "release binary size: $size bytes"
|
|
62
|
+
# M1 soft cap: 1.5 MB. M3 target: < 1 MB.
|
|
63
|
+
test "$size" -lt 1572864 || (echo "binary exceeded 1.5 MB soft cap" && exit 1)
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*'
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
verify:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: pnpm/action-setup@v4
|
|
19
|
+
- uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: '22'
|
|
22
|
+
cache: 'pnpm'
|
|
23
|
+
registry-url: 'https://registry.npmjs.org'
|
|
24
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
25
|
+
- uses: Swatinem/rust-cache@v2
|
|
26
|
+
- run: pnpm install --frozen-lockfile
|
|
27
|
+
- run: pnpm build
|
|
28
|
+
- run: pnpm typecheck
|
|
29
|
+
- run: pnpm test
|
|
30
|
+
- run: pnpm lint
|
|
31
|
+
- run: cargo build --workspace --all-targets
|
|
32
|
+
- run: cargo test --workspace
|
|
33
|
+
- run: cargo package -p url-sanitize-core
|
|
34
|
+
|
|
35
|
+
build-native:
|
|
36
|
+
needs: verify
|
|
37
|
+
strategy:
|
|
38
|
+
fail-fast: false
|
|
39
|
+
matrix:
|
|
40
|
+
include:
|
|
41
|
+
- os: ubuntu-latest
|
|
42
|
+
target: x86_64-unknown-linux-gnu
|
|
43
|
+
archive: url-sanitize-x86_64-unknown-linux-gnu.tar.gz
|
|
44
|
+
binary: url-sanitize
|
|
45
|
+
- os: ubuntu-24.04-arm
|
|
46
|
+
target: aarch64-unknown-linux-gnu
|
|
47
|
+
archive: url-sanitize-aarch64-unknown-linux-gnu.tar.gz
|
|
48
|
+
binary: url-sanitize
|
|
49
|
+
- os: macos-14
|
|
50
|
+
target: aarch64-apple-darwin
|
|
51
|
+
archive: url-sanitize-aarch64-apple-darwin.tar.gz
|
|
52
|
+
binary: url-sanitize
|
|
53
|
+
- os: windows-latest
|
|
54
|
+
target: x86_64-pc-windows-msvc
|
|
55
|
+
archive: url-sanitize-x86_64-pc-windows-msvc.zip
|
|
56
|
+
binary: url-sanitize.exe
|
|
57
|
+
runs-on: ${{ matrix.os }}
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@v4
|
|
60
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
61
|
+
with:
|
|
62
|
+
targets: ${{ matrix.target }}
|
|
63
|
+
- uses: Swatinem/rust-cache@v2
|
|
64
|
+
- name: Build native binary
|
|
65
|
+
run: cargo build --release -p url-sanitize --target "${{ matrix.target }}"
|
|
66
|
+
shell: bash
|
|
67
|
+
- name: Stage binary
|
|
68
|
+
run: |
|
|
69
|
+
set -euo pipefail
|
|
70
|
+
src="target/${{ matrix.target }}/release/${{ matrix.binary }}"
|
|
71
|
+
mkdir -p "dist/${{ matrix.target }}"
|
|
72
|
+
cp "$src" "dist/${{ matrix.target }}/${{ matrix.binary }}"
|
|
73
|
+
chmod +x "dist/${{ matrix.target }}/${{ matrix.binary }}" || true
|
|
74
|
+
shell: bash
|
|
75
|
+
- name: Smoke native binary
|
|
76
|
+
run: |
|
|
77
|
+
set -euo pipefail
|
|
78
|
+
"dist/${{ matrix.target }}/${{ matrix.binary }}" --version
|
|
79
|
+
"dist/${{ matrix.target }}/${{ matrix.binary }}" --json "https://example.com/?utm_source=x"
|
|
80
|
+
printf '%s\n' "https://example.com/?utm_source=x" | "dist/${{ matrix.target }}/${{ matrix.binary }}" -
|
|
81
|
+
shell: bash
|
|
82
|
+
- name: Build release archive
|
|
83
|
+
run: |
|
|
84
|
+
set -euo pipefail
|
|
85
|
+
mkdir -p release-assets
|
|
86
|
+
if [[ "${{ matrix.archive }}" == *.zip ]]; then
|
|
87
|
+
powershell -NoProfile -Command "Compress-Archive -Path 'dist/${{ matrix.target }}/*' -DestinationPath 'release-assets/${{ matrix.archive }}'"
|
|
88
|
+
else
|
|
89
|
+
tar -czf "release-assets/${{ matrix.archive }}" -C "dist/${{ matrix.target }}" .
|
|
90
|
+
fi
|
|
91
|
+
shell: bash
|
|
92
|
+
- uses: actions/upload-artifact@v4
|
|
93
|
+
with:
|
|
94
|
+
name: release-${{ matrix.target }}
|
|
95
|
+
path: release-assets/*
|
|
96
|
+
github-release:
|
|
97
|
+
needs: build-native
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
steps:
|
|
100
|
+
- uses: actions/checkout@v4
|
|
101
|
+
- uses: actions/download-artifact@v4
|
|
102
|
+
with:
|
|
103
|
+
pattern: release-*
|
|
104
|
+
path: release-assets
|
|
105
|
+
merge-multiple: true
|
|
106
|
+
- name: Add installer scripts and checksums
|
|
107
|
+
run: |
|
|
108
|
+
cp scripts/install.sh release-assets/url-sanitize-installer.sh
|
|
109
|
+
cp scripts/install.ps1 release-assets/url-sanitize-installer.ps1
|
|
110
|
+
chmod +x release-assets/url-sanitize-installer.sh
|
|
111
|
+
(cd release-assets && sha256sum * > SHA256SUMS)
|
|
112
|
+
- uses: softprops/action-gh-release@v2
|
|
113
|
+
with:
|
|
114
|
+
files: release-assets/*
|
|
115
|
+
generate_release_notes: true
|
|
116
|
+
|
|
117
|
+
publish-npm:
|
|
118
|
+
needs: verify
|
|
119
|
+
runs-on: ubuntu-latest
|
|
120
|
+
steps:
|
|
121
|
+
- uses: actions/checkout@v4
|
|
122
|
+
- uses: pnpm/action-setup@v4
|
|
123
|
+
- uses: actions/setup-node@v4
|
|
124
|
+
with:
|
|
125
|
+
node-version: '22.14'
|
|
126
|
+
cache: 'pnpm'
|
|
127
|
+
registry-url: 'https://registry.npmjs.org'
|
|
128
|
+
- run: npm install -g 'npm@^11.5.1'
|
|
129
|
+
- run: pnpm install --frozen-lockfile
|
|
130
|
+
- run: pnpm build
|
|
131
|
+
- name: Publish TypeScript npm packages
|
|
132
|
+
run: |
|
|
133
|
+
set -euo pipefail
|
|
134
|
+
VERSION="$(node -p "require('./packages/core/package.json').version")"
|
|
135
|
+
mkdir -p npm-packages
|
|
136
|
+
|
|
137
|
+
publish_pkg() {
|
|
138
|
+
pkg="$1"
|
|
139
|
+
filter="$2"
|
|
140
|
+
if npm view "$pkg@$VERSION" version >/dev/null 2>&1; then
|
|
141
|
+
echo "$pkg@$VERSION already published; skipping"
|
|
142
|
+
return
|
|
143
|
+
fi
|
|
144
|
+
rm -f npm-packages/*.tgz
|
|
145
|
+
pnpm --filter "$filter" pack --pack-destination "$PWD/npm-packages"
|
|
146
|
+
npm publish "$PWD"/npm-packages/*.tgz --access public
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
publish_pkg "@url-sanitize/core" "@url-sanitize/core"
|
|
150
|
+
publish_pkg "@url-sanitize/clearurls" "@url-sanitize/clearurls"
|
|
151
|
+
publish_pkg "@url-sanitize/cli" "@url-sanitize/cli"
|
|
152
|
+
|
|
153
|
+
publish-crates:
|
|
154
|
+
needs: verify
|
|
155
|
+
runs-on: ubuntu-latest
|
|
156
|
+
steps:
|
|
157
|
+
- uses: actions/checkout@v4
|
|
158
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
159
|
+
- uses: Swatinem/rust-cache@v2
|
|
160
|
+
- uses: rust-lang/crates-io-auth-action@v1
|
|
161
|
+
id: auth
|
|
162
|
+
- name: Read crate version
|
|
163
|
+
id: version
|
|
164
|
+
run: |
|
|
165
|
+
version="$(python3 -c 'import json, subprocess; data=json.loads(subprocess.check_output(["cargo", "metadata", "--no-deps", "--format-version=1"])); print(next(p["version"] for p in data["packages"] if p["name"] == "url-sanitize-core"))')"
|
|
166
|
+
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
167
|
+
- name: Publish url-sanitize-core to crates.io
|
|
168
|
+
run: |
|
|
169
|
+
if curl -fsSA "url-sanitize-release" "https://crates.io/api/v1/crates/url-sanitize-core/${{ steps.version.outputs.version }}" >/dev/null; then
|
|
170
|
+
echo "url-sanitize-core ${{ steps.version.outputs.version }} already published; skipping"
|
|
171
|
+
else
|
|
172
|
+
cargo publish -p url-sanitize-core
|
|
173
|
+
fi
|
|
174
|
+
env:
|
|
175
|
+
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
|
|
176
|
+
- name: Wait for crates.io index propagation
|
|
177
|
+
run: sleep 30
|
|
178
|
+
- name: Publish url-sanitize to crates.io
|
|
179
|
+
run: |
|
|
180
|
+
if curl -fsSA "url-sanitize-release" "https://crates.io/api/v1/crates/url-sanitize/${{ steps.version.outputs.version }}" >/dev/null; then
|
|
181
|
+
echo "url-sanitize ${{ steps.version.outputs.version }} already published; skipping"
|
|
182
|
+
else
|
|
183
|
+
cargo publish -p url-sanitize
|
|
184
|
+
fi
|
|
185
|
+
env:
|
|
186
|
+
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
|
|
187
|
+
|
|
188
|
+
publish-pypi:
|
|
189
|
+
needs: verify
|
|
190
|
+
runs-on: ubuntu-latest
|
|
191
|
+
environment: pypi
|
|
192
|
+
steps:
|
|
193
|
+
- uses: actions/checkout@v4
|
|
194
|
+
- uses: actions/setup-python@v5
|
|
195
|
+
with:
|
|
196
|
+
python-version: '3.x'
|
|
197
|
+
- name: Build Python package
|
|
198
|
+
run: |
|
|
199
|
+
python -m pip install --upgrade build
|
|
200
|
+
python -m build
|
|
201
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
202
|
+
with:
|
|
203
|
+
skip-existing: true
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: sync-clearurls
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '17 4 * * *'
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
sync:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: pnpm/action-setup@v4
|
|
18
|
+
- uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: '22'
|
|
21
|
+
cache: 'pnpm'
|
|
22
|
+
- run: pnpm install --frozen-lockfile
|
|
23
|
+
|
|
24
|
+
- name: Fetch and verify upstream rules
|
|
25
|
+
run: pnpm sync:clearurls
|
|
26
|
+
|
|
27
|
+
- name: Detect changes
|
|
28
|
+
id: diff
|
|
29
|
+
run: |
|
|
30
|
+
if git diff --quiet packages/clearurls/data; then
|
|
31
|
+
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
32
|
+
else
|
|
33
|
+
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
- name: Bump patch version
|
|
37
|
+
if: steps.diff.outputs.changed == 'true'
|
|
38
|
+
run: |
|
|
39
|
+
CURRENT=$(node -p "require('./packages/core/package.json').version")
|
|
40
|
+
IFS='.' read -r major minor patch <<< "$CURRENT"
|
|
41
|
+
NEW_VERSION="$major.$minor.$((patch + 1))"
|
|
42
|
+
node scripts/bump-version.mjs "$NEW_VERSION"
|
|
43
|
+
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
|
|
44
|
+
id: bump
|
|
45
|
+
|
|
46
|
+
- name: Open PR
|
|
47
|
+
if: steps.diff.outputs.changed == 'true'
|
|
48
|
+
id: cpr
|
|
49
|
+
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
|
|
50
|
+
with:
|
|
51
|
+
commit-message: 'release: v${{ steps.bump.outputs.new_version }}'
|
|
52
|
+
title: 'chore(clearurls): sync upstream rules → v${{ steps.bump.outputs.new_version }}'
|
|
53
|
+
body: |
|
|
54
|
+
Automated daily sync of ClearURLs rule catalog from
|
|
55
|
+
https://rules2.clearurls.xyz/data.minify.json.
|
|
56
|
+
SHA256 verified against rules.minify.hash.
|
|
57
|
+
branch: clearurls-sync
|
|
58
|
+
delete-branch: true
|
|
59
|
+
|
|
60
|
+
- name: Enable auto-merge
|
|
61
|
+
if: steps.diff.outputs.changed == 'true' && steps.cpr.outputs.pull-request-number != ''
|
|
62
|
+
env:
|
|
63
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
64
|
+
run: gh pr merge --auto --squash "${{ steps.cpr.outputs.pull-request-number }}"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
node_modules/
|
|
2
|
+
dist/
|
|
3
|
+
*.tsbuildinfo
|
|
4
|
+
.turbo/
|
|
5
|
+
coverage/
|
|
6
|
+
.DS_Store
|
|
7
|
+
*.log
|
|
8
|
+
.env
|
|
9
|
+
.env.local
|
|
10
|
+
|
|
11
|
+
# Python
|
|
12
|
+
__pycache__/
|
|
13
|
+
*.py[cod]
|
|
14
|
+
*.egg-info/
|
|
15
|
+
|
|
16
|
+
.idea/
|
|
17
|
+
.vscode/*
|
|
18
|
+
!.vscode/extensions.json
|
|
19
|
+
|
|
20
|
+
# Rust
|
|
21
|
+
target/
|
|
22
|
+
Cargo.lock.bak
|
|
23
|
+
**/*.rs.bk
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
confirm-modules-purge=false
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# url-sanitize — agent context
|
|
2
|
+
|
|
3
|
+
ClearURLs-compatible URL tracking cleanup toolkit. Removes tracking parameters and unwraps tracking redirects from TypeScript, Rust, npm CLI, native binaries, and Python wrapper surfaces.
|
|
4
|
+
|
|
5
|
+
## Package layout
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
packages/
|
|
9
|
+
core/ @url-sanitize/core pure algorithm, zero deps, MIT
|
|
10
|
+
clearurls/ @url-sanitize/clearurls ClearURLs catalog + pre-compiled sanitize(), LGPL-3.0 data
|
|
11
|
+
cli/ @url-sanitize/cli pure TypeScript npm CLI, MIT
|
|
12
|
+
crates/
|
|
13
|
+
url-sanitize-core/ Rust implementation
|
|
14
|
+
url-sanitize/ native CLI with embedded catalog
|
|
15
|
+
python/
|
|
16
|
+
url_sanitize/ PyPI wrapper around native CLI / PATH binary
|
|
17
|
+
sources/
|
|
18
|
+
clearurls/ upstream sync script (pnpm sync:clearurls)
|
|
19
|
+
docs/ threat model, license model, roadmap, compat notes
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Common workflows
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pnpm install # install all workspace deps
|
|
26
|
+
pnpm sync:clearurls # fetch + SHA256-verify upstream rules → packages/clearurls/data/
|
|
27
|
+
pnpm build # tsup build all packages (must run before typecheck)
|
|
28
|
+
pnpm test # vitest run
|
|
29
|
+
pnpm lint # biome check . (also enforces import order)
|
|
30
|
+
pnpm format # biome format --write .
|
|
31
|
+
pnpm typecheck # tsc --noEmit across all packages
|
|
32
|
+
cargo fmt --all --check # Rust formatting check
|
|
33
|
+
cargo clippy --workspace --all-targets -- -D warnings
|
|
34
|
+
cargo test --workspace # Rust conformance + unit tests
|
|
35
|
+
cargo package -p url-sanitize-core
|
|
36
|
+
cargo package -p url-sanitize
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Pre-push hook runs: `pnpm build && pnpm lint && pnpm test`
|
|
40
|
+
|
|
41
|
+
## Key conventions
|
|
42
|
+
|
|
43
|
+
- **Linter/formatter**: Biome — not ESLint/Prettier. Run `pnpm lint` to check, `pnpm format` to fix.
|
|
44
|
+
- **Build**: tsup (ESM only, `.d.ts` emitted). `dist/` is gitignored, included in npm via `"files"`.
|
|
45
|
+
- **Test runner**: vitest. Single test file: `bunx vitest run packages/core/test/sanitize.test.ts`
|
|
46
|
+
- **Imports**: must be alphabetically ordered (Biome enforces). Use `.js` extensions in source imports.
|
|
47
|
+
- **Versions**: npm packages, Rust workspace, and PyPI wrapper version-bump together on every release.
|
|
48
|
+
- **Roadmap**: `docs/roadmap.md` is canonical. Do not recreate `PLAN.md`.
|
|
49
|
+
- **npm native packages**: intentionally not used in v0.2. They create one package/trusted-publisher setup per platform. Keep npm CLI pure TypeScript unless this tradeoff is explicitly reopened.
|
|
50
|
+
|
|
51
|
+
## Publishing
|
|
52
|
+
|
|
53
|
+
Publish is fully automated from `v*` tags:
|
|
54
|
+
|
|
55
|
+
- npm packages use npm trusted publishing (OIDC).
|
|
56
|
+
- crates.io uses `rust-lang/crates-io-auth-action` trusted publishing.
|
|
57
|
+
- PyPI uses trusted publishing with the `pypi` GitHub environment.
|
|
58
|
+
- GitHub Releases receive native archives, SHA256SUMS, and installer scripts.
|
|
59
|
+
|
|
60
|
+
No long-lived registry token should be required after trusted publishers are configured.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# bump versions in packages/*/package.json, Cargo.toml, pyproject.toml
|
|
64
|
+
git commit -m "release: vX.Y.Z"
|
|
65
|
+
git tag -a vX.Y.Z -m "release X.Y.Z"
|
|
66
|
+
git push --follow-tags
|
|
67
|
+
# .github/workflows/release.yml publishes npm, crates, PyPI, and native assets
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Architecture
|
|
71
|
+
|
|
72
|
+
`compileSanitizer(catalog, opts?) → Sanitizer` — factory pattern. Compiles all RegExp at factory time. Call once at module init, reuse the returned function.
|
|
73
|
+
|
|
74
|
+
`@url-sanitize/clearurls` exports `sanitize` (pre-compiled with default options) for one-import usage:
|
|
75
|
+
```ts
|
|
76
|
+
import { sanitize } from '@url-sanitize/clearurls';
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Result is a discriminated union: `{ kind: 'unchanged' } | { kind: 'cleaned', strippedParams, matchedRules } | { kind: 'redirected', via } | { kind: 'blocked', via }`
|
|
80
|
+
|
|
81
|
+
## Daily sync
|
|
82
|
+
|
|
83
|
+
`.github/workflows/sync-clearurls.yml` runs at 04:17 UTC, opens a PR on change, auto-merges via squash. No manual action needed.
|
|
84
|
+
|
|
85
|
+
## Adding a new package
|
|
86
|
+
|
|
87
|
+
1. Create `packages/<name>/` with `package.json` (`"name": "@url-sanitize/<name>"`, `"publishConfig": { "access": "public" }`)
|
|
88
|
+
2. Add `tsconfig.json` extending `../../tsconfig.base.json`
|
|
89
|
+
3. Add `"build"` script using tsup
|
|
90
|
+
4. Add `"files": ["dist"]`
|
|
91
|
+
5. `pnpm install` to link workspace
|
|
92
|
+
|
|
93
|
+
## Non-goals
|
|
94
|
+
|
|
95
|
+
No browser extension UI, HTTP interception, DNS blocking, or telemetry. See `docs/non-goals.md`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Dev setup
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
pnpm install
|
|
7
|
+
pnpm sync:clearurls # populate packages/clearurls/data/
|
|
8
|
+
pnpm build
|
|
9
|
+
pnpm test
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Layout
|
|
13
|
+
|
|
14
|
+
This is a pnpm + changesets monorepo.
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
packages/
|
|
18
|
+
core/ @url-sanitize/core pure algorithm, zero deps
|
|
19
|
+
clearurls/ @url-sanitize/clearurls ClearURLs catalog adapter + bundled data
|
|
20
|
+
cli/ @url-sanitize/cli command-line tool
|
|
21
|
+
sources/
|
|
22
|
+
clearurls/ sync script + test fixtures
|
|
23
|
+
docs/ public docs (threat model, license, roadmap)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Workflow
|
|
27
|
+
|
|
28
|
+
1. Open an issue first for non-trivial changes.
|
|
29
|
+
2. Branch from `main`.
|
|
30
|
+
3. Run `pnpm changeset` to declare a version bump for any package you change.
|
|
31
|
+
4. Open PR. CI must pass (typecheck + lint + test + build).
|
|
32
|
+
|
|
33
|
+
## Adding a rule fixture
|
|
34
|
+
|
|
35
|
+
ClearURLs ruleset changes upstream. To pin a behavior:
|
|
36
|
+
|
|
37
|
+
1. Add a fixture under `sources/clearurls/fixtures/<provider>.json` with input + expected output URLs
|
|
38
|
+
2. Reference it in `packages/core/test/sanitize.test.ts`
|
|
39
|
+
3. PR
|
|
40
|
+
|
|
41
|
+
## Reporting a broken URL
|
|
42
|
+
|
|
43
|
+
Use the `broken-url.yml` issue template. Include: input URL, expected output, actual output, `@url-sanitize/clearurls` version (from `metadata.json`).
|
|
44
|
+
|
|
45
|
+
## Scope
|
|
46
|
+
|
|
47
|
+
See [docs/non-goals.md](docs/non-goals.md). PRs that add browser-extension UI, HTTP interception, DNS blocking, or telemetry will be closed.
|