pyhtml2text 0.1.0__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.
@@ -0,0 +1,298 @@
1
+ # This file is autogenerated by maturin v1.15.0
2
+ # To update, run
3
+ #
4
+ # maturin generate-ci github
5
+ #
6
+ name: CI
7
+
8
+ on:
9
+ push:
10
+ branches:
11
+ - main
12
+ - master
13
+ tags:
14
+ - '*'
15
+ pull_request:
16
+ workflow_dispatch:
17
+
18
+ permissions:
19
+ contents: read
20
+
21
+ jobs:
22
+ linux:
23
+ runs-on: ${{ matrix.platform.runner }}
24
+ strategy:
25
+ matrix:
26
+ platform:
27
+ - runner: ubuntu-22.04
28
+ target: x86_64
29
+ - runner: ubuntu-22.04
30
+ target: x86
31
+ - runner: ubuntu-22.04
32
+ target: aarch64
33
+ - runner: ubuntu-22.04
34
+ target: armv7
35
+ - runner: ubuntu-22.04
36
+ target: s390x
37
+ - runner: ubuntu-22.04
38
+ target: ppc64le
39
+ steps:
40
+ - uses: actions/checkout@v6
41
+ - uses: actions/setup-python@v6
42
+ with:
43
+ python-version: "3.9"
44
+ - name: Build wheels
45
+ uses: PyO3/maturin-action@v1
46
+ with:
47
+ target: ${{ matrix.platform.target }}
48
+ args: --release --out dist
49
+ sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
50
+ manylinux: auto
51
+ - name: Build free-threaded wheels
52
+ uses: PyO3/maturin-action@v1
53
+ with:
54
+ target: ${{ matrix.platform.target }}
55
+ args: --release --out dist -i python3.14t
56
+ sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
57
+ manylinux: auto
58
+ - name: Upload wheels
59
+ uses: actions/upload-artifact@v6
60
+ with:
61
+ name: wheels-linux-${{ matrix.platform.target }}
62
+ path: dist
63
+ - uses: astral-sh/setup-uv@v7
64
+ if: ${{ startsWith(matrix.platform.target, 'x86_64') }}
65
+ - name: pytest
66
+ if: ${{ startsWith(matrix.platform.target, 'x86_64') }}
67
+ shell: bash
68
+ run: |
69
+ set -e
70
+ uv venv .venv
71
+ source .venv/bin/activate
72
+ uv pip install pyhtml2text --no-index --no-deps --find-links dist --reinstall
73
+ uv pip install pyhtml2text pytest
74
+ pytest
75
+ - name: pytest
76
+ if: ${{ !startsWith(matrix.platform.target, 'x86') && matrix.platform.target != 'ppc64' }}
77
+ uses: uraimo/run-on-arch-action@v3
78
+ with:
79
+ arch: ${{ matrix.platform.target }}
80
+ distro: ubuntu24.04
81
+ githubToken: ${{ github.token }}
82
+ install: |
83
+ apt-get update
84
+ apt-get install -y --no-install-recommends python3 python3-venv
85
+ run: |
86
+ set -e
87
+ python3 -m venv .venv
88
+ source .venv/bin/activate
89
+ pip install pytest
90
+ pip install pyhtml2text --no-index --no-deps --find-links dist --force-reinstall
91
+ pip install pyhtml2text
92
+ pytest
93
+
94
+ musllinux:
95
+ runs-on: ${{ matrix.platform.runner }}
96
+ strategy:
97
+ matrix:
98
+ platform:
99
+ - runner: ubuntu-22.04
100
+ target: x86_64
101
+ - runner: ubuntu-22.04
102
+ target: x86
103
+ - runner: ubuntu-22.04
104
+ target: aarch64
105
+ - runner: ubuntu-22.04
106
+ target: armv7
107
+ steps:
108
+ - uses: actions/checkout@v6
109
+ - uses: actions/setup-python@v6
110
+ with:
111
+ python-version: "3.9"
112
+ - name: Build wheels
113
+ uses: PyO3/maturin-action@v1
114
+ with:
115
+ target: ${{ matrix.platform.target }}
116
+ args: --release --out dist
117
+ sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
118
+ manylinux: musllinux_1_2
119
+ - name: Build free-threaded wheels
120
+ uses: PyO3/maturin-action@v1
121
+ with:
122
+ target: ${{ matrix.platform.target }}
123
+ args: --release --out dist -i python3.14t
124
+ sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
125
+ manylinux: musllinux_1_2
126
+ - name: Upload wheels
127
+ uses: actions/upload-artifact@v6
128
+ with:
129
+ name: wheels-musllinux-${{ matrix.platform.target }}
130
+ path: dist
131
+ - name: pytest
132
+ if: ${{ startsWith(matrix.platform.target, 'x86_64') }}
133
+ run: |
134
+ set -e
135
+ docker run --rm -v ${{ github.workspace }}:/io -w /io alpine:latest sh -c '
136
+ apk add py3-pip py3-virtualenv
137
+ python3 -m virtualenv .venv
138
+ source .venv/bin/activate
139
+ pip install pyhtml2text --no-index --no-deps --find-links dist --force-reinstall
140
+ pip install pyhtml2text pytest
141
+ pytest
142
+ '
143
+ - name: pytest
144
+ if: ${{ !startsWith(matrix.platform.target, 'x86') }}
145
+ uses: uraimo/run-on-arch-action@v3
146
+ with:
147
+ arch: ${{ matrix.platform.target }}
148
+ distro: alpine_latest
149
+ githubToken: ${{ github.token }}
150
+ install: |
151
+ apk add py3-virtualenv
152
+ run: |
153
+ set -e
154
+ python3 -m virtualenv .venv
155
+ source .venv/bin/activate
156
+ pip install pyhtml2text --no-index --no-deps --find-links dist --force-reinstall
157
+ pip install pyhtml2text pytest
158
+ pytest
159
+
160
+ windows:
161
+ runs-on: ${{ matrix.platform.runner }}
162
+ strategy:
163
+ matrix:
164
+ platform:
165
+ - runner: windows-latest
166
+ target: x64
167
+ python_arch: x64
168
+ - runner: windows-latest
169
+ target: x86
170
+ python_arch: x86
171
+ - runner: windows-11-arm
172
+ target: aarch64
173
+ python_arch: arm64
174
+ steps:
175
+ - uses: actions/checkout@v6
176
+ - uses: actions/setup-python@v6
177
+ with:
178
+ python-version: "3.13"
179
+ architecture: ${{ matrix.platform.python_arch }}
180
+ - name: Build wheels
181
+ uses: PyO3/maturin-action@v1
182
+ with:
183
+ target: ${{ matrix.platform.target }}
184
+ args: --release --out dist
185
+ sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
186
+ - uses: actions/setup-python@v6
187
+ with:
188
+ python-version: "3.14t"
189
+ architecture: ${{ matrix.platform.python_arch }}
190
+ - name: Build free-threaded wheels
191
+ uses: PyO3/maturin-action@v1
192
+ with:
193
+ target: ${{ matrix.platform.target }}
194
+ args: --release --out dist -i python3.14t
195
+ sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
196
+ - name: Upload wheels
197
+ uses: actions/upload-artifact@v6
198
+ with:
199
+ name: wheels-windows-${{ matrix.platform.target }}
200
+ path: dist
201
+ - uses: astral-sh/setup-uv@v7
202
+ - name: pytest
203
+ shell: bash
204
+ run: |
205
+ set -e
206
+ uv venv .venv
207
+ source .venv/Scripts/activate
208
+ uv pip install pyhtml2text --no-index --no-deps --find-links dist --reinstall
209
+ uv pip install pyhtml2text pytest
210
+ pytest
211
+
212
+ macos:
213
+ runs-on: ${{ matrix.platform.runner }}
214
+ strategy:
215
+ matrix:
216
+ platform:
217
+ - runner: macos-15-intel
218
+ target: x86_64
219
+ - runner: macos-latest
220
+ target: aarch64
221
+ steps:
222
+ - uses: actions/checkout@v6
223
+ - uses: actions/setup-python@v6
224
+ with:
225
+ python-version: "3.9"
226
+ - name: Build wheels
227
+ uses: PyO3/maturin-action@v1
228
+ with:
229
+ target: ${{ matrix.platform.target }}
230
+ args: --release --out dist
231
+ sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
232
+ - uses: actions/setup-python@v6
233
+ with:
234
+ python-version: "3.14t"
235
+ - name: Build free-threaded wheels
236
+ uses: PyO3/maturin-action@v1
237
+ with:
238
+ target: ${{ matrix.platform.target }}
239
+ args: --release --out dist -i python3.14t
240
+ sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
241
+ - name: Upload wheels
242
+ uses: actions/upload-artifact@v6
243
+ with:
244
+ name: wheels-macos-${{ matrix.platform.target }}
245
+ path: dist
246
+ - uses: astral-sh/setup-uv@v7
247
+ - name: pytest
248
+ run: |
249
+ set -e
250
+ uv venv .venv
251
+ source .venv/bin/activate
252
+ uv pip install pyhtml2text --no-index --no-deps --find-links dist --reinstall
253
+ uv pip install pyhtml2text pytest
254
+ pytest
255
+
256
+ sdist:
257
+ runs-on: ubuntu-latest
258
+ steps:
259
+ - uses: actions/checkout@v6
260
+ - name: Build sdist
261
+ uses: PyO3/maturin-action@v1
262
+ with:
263
+ command: sdist
264
+ args: --out dist
265
+ - name: Upload sdist
266
+ uses: actions/upload-artifact@v6
267
+ with:
268
+ name: wheels-sdist
269
+ path: dist
270
+
271
+ release:
272
+ name: Release
273
+ runs-on: ubuntu-latest
274
+ if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
275
+ needs: [linux, musllinux, windows, macos, sdist]
276
+ environment:
277
+ name: pypi
278
+ url: https://pypi.org/p/pyhtml2text
279
+ permissions:
280
+ # Use to sign the release artifacts
281
+ id-token: write
282
+ # Used to upload release artifacts
283
+ contents: write
284
+ # Used to generate artifact attestation
285
+ attestations: write
286
+ steps:
287
+ - uses: actions/download-artifact@v7
288
+ - name: Generate artifact attestation
289
+ uses: actions/attest@v4
290
+ with:
291
+ subject-path: 'wheels-*/*'
292
+ - name: Install uv
293
+ if: ${{ startsWith(github.ref, 'refs/tags/') }}
294
+ uses: astral-sh/setup-uv@v7
295
+ - name: Publish to PyPI
296
+ if: ${{ startsWith(github.ref, 'refs/tags/') }}
297
+ # Trusted publishing (OIDC) - no token stored in the repo.
298
+ run: uv publish --trusted-publishing always 'wheels-*/*'
@@ -0,0 +1,5 @@
1
+ target/
2
+ dist/
3
+ .venv/
4
+ __pycache__/
5
+ *.so
@@ -0,0 +1,456 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "autocfg"
7
+ version = "1.5.1"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
10
+
11
+ [[package]]
12
+ name = "bitflags"
13
+ version = "2.13.2"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
16
+
17
+ [[package]]
18
+ name = "cfg-if"
19
+ version = "1.0.5"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
22
+
23
+ [[package]]
24
+ name = "fastrand"
25
+ version = "2.5.0"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
28
+
29
+ [[package]]
30
+ name = "heck"
31
+ version = "0.5.0"
32
+ source = "registry+https://github.com/rust-lang/crates.io-index"
33
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
34
+
35
+ [[package]]
36
+ name = "html2text"
37
+ version = "0.17.1"
38
+ source = "git+https://github.com/jaredlynskey/rust-html2text?rev=ee049006a900891e9df46299004c38ff59c41d65#ee049006a900891e9df46299004c38ff59c41d65"
39
+ dependencies = [
40
+ "html5ever",
41
+ "tendril",
42
+ "thiserror",
43
+ "unicode-width",
44
+ ]
45
+
46
+ [[package]]
47
+ name = "html5ever"
48
+ version = "0.39.0"
49
+ source = "registry+https://github.com/rust-lang/crates.io-index"
50
+ checksum = "46a1761807faccc9a19e86944bbf40610014066306f96edcdedc2fb714bcb7b8"
51
+ dependencies = [
52
+ "log",
53
+ "markup5ever",
54
+ ]
55
+
56
+ [[package]]
57
+ name = "indoc"
58
+ version = "2.0.8"
59
+ source = "registry+https://github.com/rust-lang/crates.io-index"
60
+ checksum = "a37b2691796cffeb8a8cd305ac66e65841559f147f4e63231d0eafa4db5384d1"
61
+ dependencies = [
62
+ "rustversion",
63
+ ]
64
+
65
+ [[package]]
66
+ name = "libc"
67
+ version = "0.2.190"
68
+ source = "registry+https://github.com/rust-lang/crates.io-index"
69
+ checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
70
+
71
+ [[package]]
72
+ name = "lock_api"
73
+ version = "0.4.14"
74
+ source = "registry+https://github.com/rust-lang/crates.io-index"
75
+ checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
76
+ dependencies = [
77
+ "scopeguard",
78
+ ]
79
+
80
+ [[package]]
81
+ name = "log"
82
+ version = "0.4.34"
83
+ source = "registry+https://github.com/rust-lang/crates.io-index"
84
+ checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
85
+
86
+ [[package]]
87
+ name = "markup5ever"
88
+ version = "0.39.0"
89
+ source = "registry+https://github.com/rust-lang/crates.io-index"
90
+ checksum = "7122d987ec5f704ee56f6e5b41a7d93722e9aae27ae07cafa4036c4d3f9757de"
91
+ dependencies = [
92
+ "log",
93
+ "tendril",
94
+ "web_atoms",
95
+ ]
96
+
97
+ [[package]]
98
+ name = "memoffset"
99
+ version = "0.9.1"
100
+ source = "registry+https://github.com/rust-lang/crates.io-index"
101
+ checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
102
+ dependencies = [
103
+ "autocfg",
104
+ ]
105
+
106
+ [[package]]
107
+ name = "new_debug_unreachable"
108
+ version = "1.0.6"
109
+ source = "registry+https://github.com/rust-lang/crates.io-index"
110
+ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
111
+
112
+ [[package]]
113
+ name = "once_cell"
114
+ version = "1.21.4"
115
+ source = "registry+https://github.com/rust-lang/crates.io-index"
116
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
117
+
118
+ [[package]]
119
+ name = "parking_lot"
120
+ version = "0.12.5"
121
+ source = "registry+https://github.com/rust-lang/crates.io-index"
122
+ checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
123
+ dependencies = [
124
+ "lock_api",
125
+ "parking_lot_core",
126
+ ]
127
+
128
+ [[package]]
129
+ name = "parking_lot_core"
130
+ version = "0.9.12"
131
+ source = "registry+https://github.com/rust-lang/crates.io-index"
132
+ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
133
+ dependencies = [
134
+ "cfg-if",
135
+ "libc",
136
+ "redox_syscall",
137
+ "smallvec",
138
+ "windows-link",
139
+ ]
140
+
141
+ [[package]]
142
+ name = "phf"
143
+ version = "0.13.1"
144
+ source = "registry+https://github.com/rust-lang/crates.io-index"
145
+ checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
146
+ dependencies = [
147
+ "phf_shared",
148
+ "serde",
149
+ ]
150
+
151
+ [[package]]
152
+ name = "phf_codegen"
153
+ version = "0.13.1"
154
+ source = "registry+https://github.com/rust-lang/crates.io-index"
155
+ checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1"
156
+ dependencies = [
157
+ "phf_generator",
158
+ "phf_shared",
159
+ ]
160
+
161
+ [[package]]
162
+ name = "phf_generator"
163
+ version = "0.13.1"
164
+ source = "registry+https://github.com/rust-lang/crates.io-index"
165
+ checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
166
+ dependencies = [
167
+ "fastrand",
168
+ "phf_shared",
169
+ ]
170
+
171
+ [[package]]
172
+ name = "phf_shared"
173
+ version = "0.13.1"
174
+ source = "registry+https://github.com/rust-lang/crates.io-index"
175
+ checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
176
+ dependencies = [
177
+ "siphasher",
178
+ ]
179
+
180
+ [[package]]
181
+ name = "portable-atomic"
182
+ version = "1.15.0"
183
+ source = "registry+https://github.com/rust-lang/crates.io-index"
184
+ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
185
+
186
+ [[package]]
187
+ name = "precomputed-hash"
188
+ version = "0.1.1"
189
+ source = "registry+https://github.com/rust-lang/crates.io-index"
190
+ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
191
+
192
+ [[package]]
193
+ name = "proc-macro2"
194
+ version = "1.0.107"
195
+ source = "registry+https://github.com/rust-lang/crates.io-index"
196
+ checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
197
+ dependencies = [
198
+ "unicode-ident",
199
+ ]
200
+
201
+ [[package]]
202
+ name = "pyhtml2text"
203
+ version = "0.1.0"
204
+ dependencies = [
205
+ "html2text",
206
+ "pyo3",
207
+ ]
208
+
209
+ [[package]]
210
+ name = "pyo3"
211
+ version = "0.26.0"
212
+ source = "registry+https://github.com/rust-lang/crates.io-index"
213
+ checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383"
214
+ dependencies = [
215
+ "indoc",
216
+ "libc",
217
+ "memoffset",
218
+ "once_cell",
219
+ "portable-atomic",
220
+ "pyo3-build-config",
221
+ "pyo3-ffi",
222
+ "pyo3-macros",
223
+ "unindent",
224
+ ]
225
+
226
+ [[package]]
227
+ name = "pyo3-build-config"
228
+ version = "0.26.0"
229
+ source = "registry+https://github.com/rust-lang/crates.io-index"
230
+ checksum = "4fc6ddaf24947d12a9aa31ac65431fb1b851b8f4365426e182901eabfb87df5f"
231
+ dependencies = [
232
+ "target-lexicon",
233
+ ]
234
+
235
+ [[package]]
236
+ name = "pyo3-ffi"
237
+ version = "0.26.0"
238
+ source = "registry+https://github.com/rust-lang/crates.io-index"
239
+ checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105"
240
+ dependencies = [
241
+ "libc",
242
+ "pyo3-build-config",
243
+ ]
244
+
245
+ [[package]]
246
+ name = "pyo3-macros"
247
+ version = "0.26.0"
248
+ source = "registry+https://github.com/rust-lang/crates.io-index"
249
+ checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded"
250
+ dependencies = [
251
+ "proc-macro2",
252
+ "pyo3-macros-backend",
253
+ "quote",
254
+ "syn 2.0.119",
255
+ ]
256
+
257
+ [[package]]
258
+ name = "pyo3-macros-backend"
259
+ version = "0.26.0"
260
+ source = "registry+https://github.com/rust-lang/crates.io-index"
261
+ checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf"
262
+ dependencies = [
263
+ "heck",
264
+ "proc-macro2",
265
+ "pyo3-build-config",
266
+ "quote",
267
+ "syn 2.0.119",
268
+ ]
269
+
270
+ [[package]]
271
+ name = "quote"
272
+ version = "1.0.47"
273
+ source = "registry+https://github.com/rust-lang/crates.io-index"
274
+ checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
275
+ dependencies = [
276
+ "proc-macro2",
277
+ ]
278
+
279
+ [[package]]
280
+ name = "redox_syscall"
281
+ version = "0.5.18"
282
+ source = "registry+https://github.com/rust-lang/crates.io-index"
283
+ checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
284
+ dependencies = [
285
+ "bitflags",
286
+ ]
287
+
288
+ [[package]]
289
+ name = "rustversion"
290
+ version = "1.0.23"
291
+ source = "registry+https://github.com/rust-lang/crates.io-index"
292
+ checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
293
+
294
+ [[package]]
295
+ name = "scopeguard"
296
+ version = "1.2.0"
297
+ source = "registry+https://github.com/rust-lang/crates.io-index"
298
+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
299
+
300
+ [[package]]
301
+ name = "serde"
302
+ version = "1.0.229"
303
+ source = "registry+https://github.com/rust-lang/crates.io-index"
304
+ checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
305
+ dependencies = [
306
+ "serde_core",
307
+ ]
308
+
309
+ [[package]]
310
+ name = "serde_core"
311
+ version = "1.0.229"
312
+ source = "registry+https://github.com/rust-lang/crates.io-index"
313
+ checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
314
+ dependencies = [
315
+ "serde_derive",
316
+ ]
317
+
318
+ [[package]]
319
+ name = "serde_derive"
320
+ version = "1.0.229"
321
+ source = "registry+https://github.com/rust-lang/crates.io-index"
322
+ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
323
+ dependencies = [
324
+ "proc-macro2",
325
+ "quote",
326
+ "syn 3.0.9",
327
+ ]
328
+
329
+ [[package]]
330
+ name = "siphasher"
331
+ version = "1.0.4"
332
+ source = "registry+https://github.com/rust-lang/crates.io-index"
333
+ checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256"
334
+
335
+ [[package]]
336
+ name = "smallvec"
337
+ version = "1.16.3"
338
+ source = "registry+https://github.com/rust-lang/crates.io-index"
339
+ checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b"
340
+
341
+ [[package]]
342
+ name = "string_cache"
343
+ version = "0.9.0"
344
+ source = "registry+https://github.com/rust-lang/crates.io-index"
345
+ checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901"
346
+ dependencies = [
347
+ "new_debug_unreachable",
348
+ "parking_lot",
349
+ "phf_shared",
350
+ "precomputed-hash",
351
+ ]
352
+
353
+ [[package]]
354
+ name = "string_cache_codegen"
355
+ version = "0.6.1"
356
+ source = "registry+https://github.com/rust-lang/crates.io-index"
357
+ checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69"
358
+ dependencies = [
359
+ "phf_generator",
360
+ "phf_shared",
361
+ "proc-macro2",
362
+ "quote",
363
+ ]
364
+
365
+ [[package]]
366
+ name = "syn"
367
+ version = "2.0.119"
368
+ source = "registry+https://github.com/rust-lang/crates.io-index"
369
+ checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
370
+ dependencies = [
371
+ "proc-macro2",
372
+ "quote",
373
+ "unicode-ident",
374
+ ]
375
+
376
+ [[package]]
377
+ name = "syn"
378
+ version = "3.0.9"
379
+ source = "registry+https://github.com/rust-lang/crates.io-index"
380
+ checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"
381
+ dependencies = [
382
+ "proc-macro2",
383
+ "quote",
384
+ "unicode-ident",
385
+ ]
386
+
387
+ [[package]]
388
+ name = "target-lexicon"
389
+ version = "0.13.5"
390
+ source = "registry+https://github.com/rust-lang/crates.io-index"
391
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
392
+
393
+ [[package]]
394
+ name = "tendril"
395
+ version = "0.5.1"
396
+ source = "registry+https://github.com/rust-lang/crates.io-index"
397
+ checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08"
398
+ dependencies = [
399
+ "new_debug_unreachable",
400
+ ]
401
+
402
+ [[package]]
403
+ name = "thiserror"
404
+ version = "2.0.21"
405
+ source = "registry+https://github.com/rust-lang/crates.io-index"
406
+ checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e"
407
+ dependencies = [
408
+ "thiserror-impl",
409
+ ]
410
+
411
+ [[package]]
412
+ name = "thiserror-impl"
413
+ version = "2.0.21"
414
+ source = "registry+https://github.com/rust-lang/crates.io-index"
415
+ checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524"
416
+ dependencies = [
417
+ "proc-macro2",
418
+ "quote",
419
+ "syn 3.0.9",
420
+ ]
421
+
422
+ [[package]]
423
+ name = "unicode-ident"
424
+ version = "1.0.27"
425
+ source = "registry+https://github.com/rust-lang/crates.io-index"
426
+ checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
427
+
428
+ [[package]]
429
+ name = "unicode-width"
430
+ version = "0.2.2"
431
+ source = "registry+https://github.com/rust-lang/crates.io-index"
432
+ checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
433
+
434
+ [[package]]
435
+ name = "unindent"
436
+ version = "0.2.4"
437
+ source = "registry+https://github.com/rust-lang/crates.io-index"
438
+ checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
439
+
440
+ [[package]]
441
+ name = "web_atoms"
442
+ version = "0.2.6"
443
+ source = "registry+https://github.com/rust-lang/crates.io-index"
444
+ checksum = "ba8b815c1b593dc0baf78dd0f4fc8fdb2de53198fb1163738093e9a311c33fb3"
445
+ dependencies = [
446
+ "phf",
447
+ "phf_codegen",
448
+ "string_cache",
449
+ "string_cache_codegen",
450
+ ]
451
+
452
+ [[package]]
453
+ name = "windows-link"
454
+ version = "0.2.1"
455
+ source = "registry+https://github.com/rust-lang/crates.io-index"
456
+ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
@@ -0,0 +1,21 @@
1
+ [package]
2
+ name = "pyhtml2text"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ license = "MIT"
6
+ publish = false
7
+ readme = "README.md"
8
+
9
+ [lib]
10
+ name = "_pyhtml2text"
11
+ crate-type = ["cdylib"]
12
+
13
+ [dependencies]
14
+ pyo3 = { version = "0.26", features = ["extension-module", "abi3-py39"] }
15
+ # Fork of jugglerchris/rust-html2text with Config::base_url added.
16
+ html2text = { git = "https://github.com/jaredlynskey/rust-html2text", rev = "ee049006a900891e9df46299004c38ff59c41d65" }
17
+
18
+ [profile.release]
19
+ lto = true
20
+ codegen-units = 1
21
+ strip = true
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jared Lynskey
4
+ Copyright (c) 2016 Chris Emerson (rust-html2text, which this package embeds)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyhtml2text
3
+ Version: 0.1.0
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: Topic :: Text Processing :: Markup :: HTML
7
+ License-File: LICENSE
8
+ Summary: Fast HTML to plain text, with relative link resolution (Python bindings to rust-html2text)
9
+ Keywords: html,text,markdown,html2text
10
+ Author-email: Jared Lynskey <jared@lynskey.co.nz>
11
+ License-Expression: MIT
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
14
+ Project-URL: Source, https://github.com/jaredlynskey/pyhtml2text
15
+ Project-URL: Upstream, https://github.com/jugglerchris/rust-html2text
16
+
17
+ # pyhtml2text
18
+
19
+ Fast HTML to plain text for Python, built on
20
+ [rust-html2text](https://github.com/jugglerchris/rust-html2text).
21
+
22
+ It adds one thing the upstream crate doesn't have yet: relative links can be
23
+ resolved against the page's URL, so footnote links are usable on their own.
24
+
25
+ ```python
26
+ from pyhtml2text import html2text
27
+
28
+ html = '<p>Please <a href="/login">sign in</a> first.</p>'
29
+
30
+ print(html2text(html, base_url="https://example.com/docs/page.html"))
31
+ # Please [sign in][1] first.
32
+ #
33
+ # [1]: https://example.com/login
34
+ ```
35
+
36
+ ## Options
37
+
38
+ `html2text(html, width=80, *, ...)`
39
+
40
+ | option | default | |
41
+ |---|---|---|
42
+ | `base_url` | `None` | resolve relative `href`s against this URL (RFC 3986). Absolute and `mailto:` etc. links are left alone |
43
+ | `decorate` | `True` | markdown-ish `*em*`, `**strong**`, `` `code` `` |
44
+ | `link_footnotes` | `True` | list link targets as `[1]: ...` footnotes |
45
+ | `table_borders` | `True` | draw table borders |
46
+ | `wrap_links` | `True` | allow long links to wrap |
47
+ | `max_wrap_width` | `None` | wrap paragraphs narrower than `width` |
48
+ | `raw` | `False` | flatten tables so cell text stays together |
49
+
50
+ ## Credits
51
+
52
+ The rendering is done by rust-html2text by Chris Emerson (MIT). This package
53
+ uses [a fork](https://github.com/jaredlynskey/rust-html2text/tree/base-url-resolution)
54
+ that adds `base_url`. It isn't affiliated with or endorsed by the upstream project,
55
+ so please report issues here rather than upstream.
56
+
@@ -0,0 +1,39 @@
1
+ # pyhtml2text
2
+
3
+ Fast HTML to plain text for Python, built on
4
+ [rust-html2text](https://github.com/jugglerchris/rust-html2text).
5
+
6
+ It adds one thing the upstream crate doesn't have yet: relative links can be
7
+ resolved against the page's URL, so footnote links are usable on their own.
8
+
9
+ ```python
10
+ from pyhtml2text import html2text
11
+
12
+ html = '<p>Please <a href="/login">sign in</a> first.</p>'
13
+
14
+ print(html2text(html, base_url="https://example.com/docs/page.html"))
15
+ # Please [sign in][1] first.
16
+ #
17
+ # [1]: https://example.com/login
18
+ ```
19
+
20
+ ## Options
21
+
22
+ `html2text(html, width=80, *, ...)`
23
+
24
+ | option | default | |
25
+ |---|---|---|
26
+ | `base_url` | `None` | resolve relative `href`s against this URL (RFC 3986). Absolute and `mailto:` etc. links are left alone |
27
+ | `decorate` | `True` | markdown-ish `*em*`, `**strong**`, `` `code` `` |
28
+ | `link_footnotes` | `True` | list link targets as `[1]: ...` footnotes |
29
+ | `table_borders` | `True` | draw table borders |
30
+ | `wrap_links` | `True` | allow long links to wrap |
31
+ | `max_wrap_width` | `None` | wrap paragraphs narrower than `width` |
32
+ | `raw` | `False` | flatten tables so cell text stays together |
33
+
34
+ ## Credits
35
+
36
+ The rendering is done by rust-html2text by Chris Emerson (MIT). This package
37
+ uses [a fork](https://github.com/jaredlynskey/rust-html2text/tree/base-url-resolution)
38
+ that adds `base_url`. It isn't affiliated with or endorsed by the upstream project,
39
+ so please report issues here rather than upstream.
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.7,<2"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "pyhtml2text"
7
+ version = "0.1.0"
8
+ description = "Fast HTML to plain text, with relative link resolution (Python bindings to rust-html2text)"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.9"
13
+ authors = [{ name = "Jared Lynskey", email = "jared@lynskey.co.nz" }]
14
+ keywords = ["html", "text", "markdown", "html2text"]
15
+ classifiers = [
16
+ "Programming Language :: Rust",
17
+ "Programming Language :: Python :: 3",
18
+ "Topic :: Text Processing :: Markup :: HTML",
19
+ ]
20
+
21
+ [project.urls]
22
+ Source = "https://github.com/jaredlynskey/pyhtml2text"
23
+ Upstream = "https://github.com/jugglerchris/rust-html2text"
24
+
25
+ [tool.maturin]
26
+ python-source = "python"
27
+ module-name = "pyhtml2text._pyhtml2text"
28
+
29
+ [tool.maturin.generate-ci.github]
30
+ pytest = true
@@ -0,0 +1,3 @@
1
+ from ._pyhtml2text import html2text
2
+
3
+ __all__ = ["html2text"]
@@ -0,0 +1,14 @@
1
+ from typing import Optional
2
+
3
+ def html2text(
4
+ html: str,
5
+ width: int = 80,
6
+ *,
7
+ base_url: Optional[str] = None,
8
+ decorate: bool = True,
9
+ link_footnotes: bool = True,
10
+ table_borders: bool = True,
11
+ wrap_links: bool = True,
12
+ max_wrap_width: Optional[int] = None,
13
+ raw: bool = False,
14
+ ) -> str: ...
File without changes
@@ -0,0 +1,62 @@
1
+ use html2text::config;
2
+ use pyo3::exceptions::PyValueError;
3
+ use pyo3::prelude::*;
4
+
5
+ /// Render HTML as plain text.
6
+ #[pyfunction]
7
+ #[pyo3(name = "html2text", signature = (
8
+ html,
9
+ width = 80,
10
+ *,
11
+ base_url = None,
12
+ decorate = true,
13
+ link_footnotes = true,
14
+ table_borders = true,
15
+ wrap_links = true,
16
+ max_wrap_width = None,
17
+ raw = false,
18
+ ))]
19
+ #[allow(clippy::too_many_arguments)]
20
+ fn render(
21
+ py: Python<'_>,
22
+ html: &str,
23
+ width: usize,
24
+ base_url: Option<String>,
25
+ decorate: bool,
26
+ link_footnotes: bool,
27
+ table_borders: bool,
28
+ wrap_links: bool,
29
+ max_wrap_width: Option<usize>,
30
+ raw: bool,
31
+ ) -> PyResult<String> {
32
+ let mut conf = if decorate {
33
+ config::plain()
34
+ } else {
35
+ config::plain_no_decorate()
36
+ };
37
+ conf = conf.link_footnotes(link_footnotes).allow_width_overflow();
38
+ if let Some(base) = base_url {
39
+ conf = conf.base_url(base);
40
+ }
41
+ if !table_borders {
42
+ conf = conf.no_table_borders();
43
+ }
44
+ if !wrap_links {
45
+ conf = conf.no_link_wrapping();
46
+ }
47
+ if let Some(w) = max_wrap_width {
48
+ conf = conf.max_wrap_width(w);
49
+ }
50
+ if raw {
51
+ conf = conf.raw_mode(true);
52
+ }
53
+ // Rendering is pure Rust, so let other Python threads run meanwhile.
54
+ py.detach(|| conf.string_from_read(html.as_bytes(), width))
55
+ .map_err(|e| PyValueError::new_err(e.to_string()))
56
+ }
57
+
58
+ #[pymodule]
59
+ fn _pyhtml2text(m: &Bound<'_, PyModule>) -> PyResult<()> {
60
+ m.add_function(wrap_pyfunction!(render, m)?)?;
61
+ Ok(())
62
+ }
@@ -0,0 +1,58 @@
1
+ from pyhtml2text import html2text
2
+
3
+ PAGE = "https://example.com/dir/page.html"
4
+
5
+
6
+ def test_plain():
7
+ assert html2text("<p>Hello <b>world</b></p>") == "Hello **world**\n"
8
+
9
+
10
+ def test_relative_links_unchanged_without_base():
11
+ out = html2text('<p><a href="/login">Sign in</a></p>')
12
+ assert out == "[Sign in][1]\n\n[1]: /login\n"
13
+
14
+
15
+ def test_base_url_resolves():
16
+ html = (
17
+ '<p><a href="/login">a</a> <a href="../other.html">b</a> '
18
+ '<a href="next.html?p=2#top">c</a> <a href="https://other.example/x">d</a> '
19
+ '<a href="mailto:x@example.com">e</a></p>'
20
+ )
21
+ out = html2text(html, base_url=PAGE)
22
+ assert "[1]: https://example.com/login\n" in out
23
+ assert "[2]: https://example.com/other.html\n" in out
24
+ assert "[3]: https://example.com/dir/next.html?p=2#top\n" in out
25
+ assert "[4]: https://other.example/x\n" in out
26
+ assert "[5]: mailto:x@example.com\n" in out
27
+
28
+
29
+ def test_no_footnotes():
30
+ assert html2text('<a href="/x">x</a>', link_footnotes=False) == "[x]\n"
31
+
32
+
33
+ def test_width_wraps():
34
+ out = html2text("<p>" + "word " * 30 + "</p>", width=20)
35
+ assert all(len(line) <= 20 for line in out.splitlines())
36
+
37
+
38
+ def test_bad_base_url_leaves_links_alone():
39
+ for base in ("not a url", ""):
40
+ assert html2text('<a href="/x">x</a>', base_url=base) == "[x][1]\n\n[1]: /x\n"
41
+
42
+
43
+ def test_zero_width_raises():
44
+ import pytest
45
+
46
+ with pytest.raises(ValueError):
47
+ html2text("<p>hi</p>", width=0)
48
+
49
+
50
+ def test_tables():
51
+ html = "<table><tr><td>a</td><td>b</td></tr></table>"
52
+ assert html2text(html) == "─┬─\na│b\n─┴─\n"
53
+ assert html2text(html, table_borders=False) == "a b\n"
54
+
55
+
56
+ def test_unicode_and_empty():
57
+ assert html2text("<p>한국어 텍스트 é</p>") == "한국어 텍스트 é\n"
58
+ assert html2text("") == ""