pyhtml2text 0.3.1__tar.gz → 0.4.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.
Files changed (41) hide show
  1. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/.gitignore +1 -0
  2. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/CHANGELOG.md +27 -0
  3. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/Cargo.lock +23 -105
  4. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/Cargo.toml +7 -7
  5. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/LICENSE +0 -1
  6. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/PKG-INFO +12 -14
  7. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/README.md +10 -11
  8. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/pyproject.toml +3 -4
  9. pyhtml2text-0.4.0/src/dom.rs +290 -0
  10. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/src/lib.rs +19 -29
  11. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/src/markdown.rs +9 -8
  12. pyhtml2text-0.4.0/src/table.rs +1226 -0
  13. pyhtml2text-0.4.0/src/text.rs +1333 -0
  14. pyhtml2text-0.4.0/src/url.rs +116 -0
  15. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/tests/test_basic.py +6 -0
  16. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/README.md +5 -5
  17. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/python/pyhtml2text/__init__.py +0 -0
  18. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/python/pyhtml2text/__init__.pyi +0 -0
  19. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/python/pyhtml2text/py.typed +0 -0
  20. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/tests/markdown_check.py +0 -0
  21. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/tests/test_markdown.py +0 -0
  22. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/Cargo.toml +0 -0
  23. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/LICENSE-APACHE +0 -0
  24. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/LICENSE-MIT +0 -0
  25. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/README.md +0 -0
  26. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/driver.rs +0 -0
  27. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/encoding.rs +0 -0
  28. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/lib.rs +0 -0
  29. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/macros.rs +0 -0
  30. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/serialize/mod.rs +0 -0
  31. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tokenizer/char_ref/mod.rs +0 -0
  32. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tokenizer/interface.rs +0 -0
  33. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tokenizer/mod.rs +0 -0
  34. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tokenizer/states.rs +0 -0
  35. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tree_builder/data.rs +0 -0
  36. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tree_builder/mod.rs +0 -0
  37. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tree_builder/open_elems.rs +0 -0
  38. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tree_builder/rules.rs +0 -0
  39. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tree_builder/tag_sets.rs +0 -0
  40. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/tree_builder/types.rs +0 -0
  41. {pyhtml2text-0.3.1 → pyhtml2text-0.4.0}/vendor/html5ever/src/util/str.rs +0 -0
@@ -3,3 +3,4 @@ dist/
3
3
  .venv/
4
4
  __pycache__/
5
5
  *.so
6
+ .DS_Store
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 (2026-10-22)
4
+
5
+ - `html2text()` is rendered by this package's own code. The library it used
6
+ before came from a fork that can no longer be fetched, so the source
7
+ distribution and fresh builds of 0.3.1 fail. The new renderer is a
8
+ clean-room implementation: it was written from 0.3.1's output, the HTML
9
+ standard and RFC 3986, without reference to the old library's source.
10
+ - Output is the same as 0.3.1's, byte for byte, with every option set: on
11
+ the benchmark corpus, on 38 of 39 other real pages (the last differs at
12
+ width 40 only), and on 1,500 random documents without tables. With tables,
13
+ 99.2% of 2,000 random documents match under each option set. The known
14
+ differences are all in unusual markup:
15
+ - A cell with nothing in it, beside a cell spanning rows: 0.3.1 draws the
16
+ span against the wrong cell, so borders and line breaks land a column
17
+ off. They now follow the spanning cell.
18
+ - A table with nothing to show whose cells span into further empty rows,
19
+ an empty `<pre>` or heading directly inside `<pre>`, and a table with
20
+ nothing to show in a paragraph: 0.3.1 writes an extra blank line.
21
+ - Headings, quotes and list items squeezed to fewer than three columns
22
+ break `**` and other markers in different places.
23
+ - Some emoji sequences (joined with U+200D) and Arabic lam-alef pairs, cut
24
+ at the end of a line in a narrow table cell.
25
+ - `html2text()` is 1.2–2× faster on real pages (7.0 ms against 10.8 ms for
26
+ a 780 KB Wikipedia article) and 2× faster on short snippets.
27
+ - `html2markdown()` output is unchanged.
28
+ - PyO3 0.30. Building from source needs maturin 1.9.4 or later.
29
+
3
30
  ## 0.3.1 (2026-10-19)
4
31
 
5
32
  - The vendored html5ever now carries
@@ -2,12 +2,6 @@
2
2
  # It is not intended for manual editing.
3
3
  version = 4
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
5
  [[package]]
12
6
  name = "bitflags"
13
7
  version = "2.13.2"
@@ -16,9 +10,9 @@ checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
16
10
 
17
11
  [[package]]
18
12
  name = "cc"
19
- version = "1.8.0"
13
+ version = "1.9.0"
20
14
  source = "registry+https://github.com/rust-lang/crates.io-index"
21
- checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838"
15
+ checksum = "877bf67ac8e52449eb2f9e98a344ea163beb70dd1f9eebe3cc5357dcfeaee4df"
22
16
  dependencies = [
23
17
  "find-msvc-tools",
24
18
  "shlex",
@@ -38,9 +32,9 @@ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
38
32
 
39
33
  [[package]]
40
34
  name = "find-msvc-tools"
41
- version = "0.1.14"
35
+ version = "0.1.15"
42
36
  source = "registry+https://github.com/rust-lang/crates.io-index"
43
- checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484"
37
+ checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48"
44
38
 
45
39
  [[package]]
46
40
  name = "heck"
@@ -48,17 +42,6 @@ version = "0.5.0"
48
42
  source = "registry+https://github.com/rust-lang/crates.io-index"
49
43
  checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
50
44
 
51
- [[package]]
52
- name = "html2text"
53
- version = "0.17.1"
54
- source = "git+https://github.com/jaredlynskey/rust-html2text?rev=b42930f8e6688ea121daf392e27a7d9812e6192d#b42930f8e6688ea121daf392e27a7d9812e6192d"
55
- dependencies = [
56
- "html5ever",
57
- "tendril",
58
- "thiserror",
59
- "unicode-width",
60
- ]
61
-
62
45
  [[package]]
63
46
  name = "html5ever"
64
47
  version = "0.39.0"
@@ -67,20 +50,11 @@ dependencies = [
67
50
  "markup5ever",
68
51
  ]
69
52
 
70
- [[package]]
71
- name = "indoc"
72
- version = "2.0.8"
73
- source = "registry+https://github.com/rust-lang/crates.io-index"
74
- checksum = "a37b2691796cffeb8a8cd305ac66e65841559f147f4e63231d0eafa4db5384d1"
75
- dependencies = [
76
- "rustversion",
77
- ]
78
-
79
53
  [[package]]
80
54
  name = "libc"
81
- version = "0.2.190"
55
+ version = "0.2.191"
82
56
  source = "registry+https://github.com/rust-lang/crates.io-index"
83
- checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
57
+ checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
84
58
 
85
59
  [[package]]
86
60
  name = "libmimalloc-sys"
@@ -123,15 +97,6 @@ version = "2.8.3"
123
97
  source = "registry+https://github.com/rust-lang/crates.io-index"
124
98
  checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
125
99
 
126
- [[package]]
127
- name = "memoffset"
128
- version = "0.9.1"
129
- source = "registry+https://github.com/rust-lang/crates.io-index"
130
- checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
131
- dependencies = [
132
- "autocfg",
133
- ]
134
-
135
100
  [[package]]
136
101
  name = "mimalloc"
137
102
  version = "0.1.52"
@@ -238,9 +203,9 @@ dependencies = [
238
203
 
239
204
  [[package]]
240
205
  name = "pulldown-cmark"
241
- version = "0.13.4"
206
+ version = "0.13.5"
242
207
  source = "registry+https://github.com/rust-lang/crates.io-index"
243
- checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e"
208
+ checksum = "278e9268c93b9e498a2da46c34d90ba93a3255eb99009646398f34bc73ab36eb"
244
209
  dependencies = [
245
210
  "bitflags",
246
211
  "memchr",
@@ -249,46 +214,43 @@ dependencies = [
249
214
 
250
215
  [[package]]
251
216
  name = "pyhtml2text"
252
- version = "0.3.1"
217
+ version = "0.4.0"
253
218
  dependencies = [
254
- "html2text",
255
219
  "html5ever",
256
220
  "mimalloc",
257
221
  "pulldown-cmark",
258
222
  "pyo3",
223
+ "unicode-width",
259
224
  ]
260
225
 
261
226
  [[package]]
262
227
  name = "pyo3"
263
- version = "0.26.0"
228
+ version = "0.30.1"
264
229
  source = "registry+https://github.com/rust-lang/crates.io-index"
265
- checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383"
230
+ checksum = "229ca13b8a15bb0d1487b81ab975bfcd97513416499a8312011b6036e42e0de4"
266
231
  dependencies = [
267
- "indoc",
268
232
  "libc",
269
- "memoffset",
270
233
  "once_cell",
271
234
  "portable-atomic",
272
235
  "pyo3-build-config",
273
236
  "pyo3-ffi",
274
237
  "pyo3-macros",
275
- "unindent",
276
238
  ]
277
239
 
278
240
  [[package]]
279
241
  name = "pyo3-build-config"
280
- version = "0.26.0"
242
+ version = "0.30.1"
281
243
  source = "registry+https://github.com/rust-lang/crates.io-index"
282
- checksum = "4fc6ddaf24947d12a9aa31ac65431fb1b851b8f4365426e182901eabfb87df5f"
244
+ checksum = "70130e2b6dd1ee589a8788026a429561ca5c40fa7a2fa7914c2282eddae24700"
283
245
  dependencies = [
284
246
  "target-lexicon",
285
247
  ]
286
248
 
287
249
  [[package]]
288
250
  name = "pyo3-ffi"
289
- version = "0.26.0"
251
+ version = "0.30.1"
290
252
  source = "registry+https://github.com/rust-lang/crates.io-index"
291
- checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105"
253
+ checksum = "5e7ff73c555c286d212d4ce7e5fbda845a973c4f61bd5f160f5f2c3c2a04d1c4"
292
254
  dependencies = [
293
255
  "libc",
294
256
  "pyo3-build-config",
@@ -296,27 +258,26 @@ dependencies = [
296
258
 
297
259
  [[package]]
298
260
  name = "pyo3-macros"
299
- version = "0.26.0"
261
+ version = "0.30.1"
300
262
  source = "registry+https://github.com/rust-lang/crates.io-index"
301
- checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded"
263
+ checksum = "c46d2e5862c7bb8207e3b639f713dda3c499933444784154c11d013c5a691b60"
302
264
  dependencies = [
303
265
  "proc-macro2",
304
266
  "pyo3-macros-backend",
305
267
  "quote",
306
- "syn 2.0.119",
268
+ "syn",
307
269
  ]
308
270
 
309
271
  [[package]]
310
272
  name = "pyo3-macros-backend"
311
- version = "0.26.0"
273
+ version = "0.30.1"
312
274
  source = "registry+https://github.com/rust-lang/crates.io-index"
313
- checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf"
275
+ checksum = "38b89f066f2ae72a2aef52d1537ca2fcd104440ebfadee06e97aa90738a25b9b"
314
276
  dependencies = [
315
277
  "heck",
316
278
  "proc-macro2",
317
- "pyo3-build-config",
318
279
  "quote",
319
- "syn 2.0.119",
280
+ "syn",
320
281
  ]
321
282
 
322
283
  [[package]]
@@ -337,12 +298,6 @@ dependencies = [
337
298
  "bitflags",
338
299
  ]
339
300
 
340
- [[package]]
341
- name = "rustversion"
342
- version = "1.0.23"
343
- source = "registry+https://github.com/rust-lang/crates.io-index"
344
- checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
345
-
346
301
  [[package]]
347
302
  name = "scopeguard"
348
303
  version = "1.2.0"
@@ -375,7 +330,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
375
330
  dependencies = [
376
331
  "proc-macro2",
377
332
  "quote",
378
- "syn 3.0.9",
333
+ "syn",
379
334
  ]
380
335
 
381
336
  [[package]]
@@ -420,17 +375,6 @@ dependencies = [
420
375
  "quote",
421
376
  ]
422
377
 
423
- [[package]]
424
- name = "syn"
425
- version = "2.0.119"
426
- source = "registry+https://github.com/rust-lang/crates.io-index"
427
- checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
428
- dependencies = [
429
- "proc-macro2",
430
- "quote",
431
- "unicode-ident",
432
- ]
433
-
434
378
  [[package]]
435
379
  name = "syn"
436
380
  version = "3.0.9"
@@ -457,26 +401,6 @@ dependencies = [
457
401
  "new_debug_unreachable",
458
402
  ]
459
403
 
460
- [[package]]
461
- name = "thiserror"
462
- version = "2.0.21"
463
- source = "registry+https://github.com/rust-lang/crates.io-index"
464
- checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e"
465
- dependencies = [
466
- "thiserror-impl",
467
- ]
468
-
469
- [[package]]
470
- name = "thiserror-impl"
471
- version = "2.0.21"
472
- source = "registry+https://github.com/rust-lang/crates.io-index"
473
- checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524"
474
- dependencies = [
475
- "proc-macro2",
476
- "quote",
477
- "syn 3.0.9",
478
- ]
479
-
480
404
  [[package]]
481
405
  name = "unicase"
482
406
  version = "2.10.0"
@@ -495,12 +419,6 @@ version = "0.2.2"
495
419
  source = "registry+https://github.com/rust-lang/crates.io-index"
496
420
  checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
497
421
 
498
- [[package]]
499
- name = "unindent"
500
- version = "0.2.4"
501
- source = "registry+https://github.com/rust-lang/crates.io-index"
502
- checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
503
-
504
422
  [[package]]
505
423
  name = "web_atoms"
506
424
  version = "0.2.6"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pyhtml2text"
3
- version = "0.3.1"
3
+ version = "0.4.0"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  publish = false
@@ -11,16 +11,16 @@ name = "_pyhtml2text"
11
11
  crate-type = ["cdylib"]
12
12
 
13
13
  [dependencies]
14
- pyo3 = { version = "0.26", features = ["extension-module", "abi3-py310"] }
15
- # Fork of jugglerchris/rust-html2text with Config::base_url, some performance
16
- # changes and the DOM exports the Markdown output uses (branch pyhtml2text-perf).
17
- html2text = { git = "https://github.com/jaredlynskey/rust-html2text", rev = "b42930f8e6688ea121daf392e27a7d9812e6192d" }
18
- # The parser html2text uses; patched below. Used directly to read element attributes.
14
+ pyo3 = { version = "0.30", features = ["abi3-py310"] }
15
+ # The HTML parser; patched below.
19
16
  html5ever = "0.39"
17
+ # Display width of characters, for wrapping.
18
+ unicode-width = "=0.2.2"
20
19
  # Reads the Markdown back to check that emphasis parses as intended.
21
20
  pulldown-cmark = { version = "0.13", default-features = false }
22
21
 
23
- # Much faster than the system allocators for html2text's many small allocations.
22
+ # Much faster than the system allocators for the many small allocations of
23
+ # parsing and rendering.
24
24
  # Not on glibc armv7/ppc64le/s390x: their manylinux2014 cross compilers are too
25
25
  # old to build it (keep in sync with the cfg in src/lib.rs).
26
26
  [target.'cfg(not(all(target_env = "gnu", any(target_arch = "arm", target_arch = "powerpc64", target_arch = "s390x"))))'.dependencies]
@@ -1,7 +1,6 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) 2026 Jared Lynskey
4
- Copyright (c) 2016 Chris Emerson (rust-html2text, which this package embeds)
5
4
 
6
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,23 +1,21 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyhtml2text
3
- Version: 0.3.1
3
+ Version: 0.4.0
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Topic :: Text Processing :: Markup :: HTML
7
7
  License-File: LICENSE
8
- Summary: Fast HTML to plain text, with relative link resolution (Python bindings to rust-html2text)
8
+ Summary: Fast HTML to plain text and Markdown, with relative link resolution
9
9
  Keywords: html,text,markdown,html2text
10
10
  Author-email: Jared Lynskey <jared@lynskey.co.nz>
11
11
  License-Expression: MIT
12
12
  Requires-Python: >=3.10
13
13
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
14
14
  Project-URL: Source, https://github.com/jaredlynskey/pyhtml2text
15
- Project-URL: Upstream, https://github.com/jugglerchris/rust-html2text
16
15
 
17
16
  # pyhtml2text
18
17
 
19
- Fast HTML to plain text and to Markdown for Python, built on
20
- [rust-html2text](https://github.com/jugglerchris/rust-html2text).
18
+ Fast HTML to plain text and to Markdown for Python, written in Rust.
21
19
 
22
20
  Relative links can be resolved against the page's URL, so the output's links
23
21
  work on their own.
@@ -114,7 +112,7 @@ To plain text:
114
112
  |---|---|---|
115
113
  | [html2text](https://pypi.org/project/html2text/) (pure Python) | 71.5 ms | 14.9 ms |
116
114
  | [html2text-rs](https://pypi.org/project/html2text-rs/) | 15.2 ms | 2.5 ms |
117
- | **pyhtml2text** | **10.9 ms** | **1.6 ms** |
115
+ | **pyhtml2text** | **7.0 ms** | **1.3 ms** |
118
116
 
119
117
  - The GIL is released while converting, so threads scale across cores. On
120
118
  free-threaded Python (3.14t) the module runs without re-enabling the GIL.
@@ -128,14 +126,14 @@ To plain text:
128
126
 
129
127
  ## Credits
130
128
 
131
- The plain-text rendering is done by rust-html2text by Chris Emerson (MIT).
132
- This package uses [a fork](https://github.com/jaredlynskey/rust-html2text/tree/pyhtml2text-perf)
133
- that adds `base_url` and some performance changes, and a copy of
134
- [html5ever](https://github.com/servo/html5ever) (MIT/Apache-2.0) with
129
+ HTML is parsed by a copy of [html5ever](https://github.com/servo/html5ever)
130
+ (MIT/Apache-2.0) with
135
131
  [servo/html5ever#800](https://github.com/servo/html5ever/pull/800) by Josef
136
132
  Guenther applied, which makes parsing deeply nested HTML linear (see
137
- `vendor/`). Markdown output is checked with
138
- [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) (MIT). It
139
- isn't affiliated with or endorsed by any of these projects, so please report
140
- issues here rather than upstream.
133
+ `vendor/`). Text is measured with
134
+ [unicode-width](https://github.com/unicode-rs/unicode-width) (MIT/Apache-2.0)
135
+ and Markdown output is checked with
136
+ [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) (MIT). This
137
+ package isn't affiliated with or endorsed by any of these projects, so please
138
+ report issues here rather than upstream.
141
139
 
@@ -1,7 +1,6 @@
1
1
  # pyhtml2text
2
2
 
3
- Fast HTML to plain text and to Markdown for Python, built on
4
- [rust-html2text](https://github.com/jugglerchris/rust-html2text).
3
+ Fast HTML to plain text and to Markdown for Python, written in Rust.
5
4
 
6
5
  Relative links can be resolved against the page's URL, so the output's links
7
6
  work on their own.
@@ -98,7 +97,7 @@ To plain text:
98
97
  |---|---|---|
99
98
  | [html2text](https://pypi.org/project/html2text/) (pure Python) | 71.5 ms | 14.9 ms |
100
99
  | [html2text-rs](https://pypi.org/project/html2text-rs/) | 15.2 ms | 2.5 ms |
101
- | **pyhtml2text** | **10.9 ms** | **1.6 ms** |
100
+ | **pyhtml2text** | **7.0 ms** | **1.3 ms** |
102
101
 
103
102
  - The GIL is released while converting, so threads scale across cores. On
104
103
  free-threaded Python (3.14t) the module runs without re-enabling the GIL.
@@ -112,13 +111,13 @@ To plain text:
112
111
 
113
112
  ## Credits
114
113
 
115
- The plain-text rendering is done by rust-html2text by Chris Emerson (MIT).
116
- This package uses [a fork](https://github.com/jaredlynskey/rust-html2text/tree/pyhtml2text-perf)
117
- that adds `base_url` and some performance changes, and a copy of
118
- [html5ever](https://github.com/servo/html5ever) (MIT/Apache-2.0) with
114
+ HTML is parsed by a copy of [html5ever](https://github.com/servo/html5ever)
115
+ (MIT/Apache-2.0) with
119
116
  [servo/html5ever#800](https://github.com/servo/html5ever/pull/800) by Josef
120
117
  Guenther applied, which makes parsing deeply nested HTML linear (see
121
- `vendor/`). Markdown output is checked with
122
- [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) (MIT). It
123
- isn't affiliated with or endorsed by any of these projects, so please report
124
- issues here rather than upstream.
118
+ `vendor/`). Text is measured with
119
+ [unicode-width](https://github.com/unicode-rs/unicode-width) (MIT/Apache-2.0)
120
+ and Markdown output is checked with
121
+ [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) (MIT). This
122
+ package isn't affiliated with or endorsed by any of these projects, so please
123
+ report issues here rather than upstream.
@@ -1,11 +1,11 @@
1
1
  [build-system]
2
- requires = ["maturin>=1.7,<2"]
2
+ requires = ["maturin>=1.9.4,<2"]
3
3
  build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "pyhtml2text"
7
- version = "0.3.1"
8
- description = "Fast HTML to plain text, with relative link resolution (Python bindings to rust-html2text)"
7
+ version = "0.4.0"
8
+ description = "Fast HTML to plain text and Markdown, with relative link resolution"
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  license-files = ["LICENSE"]
@@ -20,7 +20,6 @@ classifiers = [
20
20
 
21
21
  [project.urls]
22
22
  Source = "https://github.com/jaredlynskey/pyhtml2text"
23
- Upstream = "https://github.com/jugglerchris/rust-html2text"
24
23
 
25
24
  [tool.maturin]
26
25
  python-source = "python"