Skip to main content

max / balanced_breakfast

Replace html2text with pter for HTML-to-markdown conversion Use pter::convert() in html_to_text and extract_article Rhai host functions, producing readable markdown instead of fixed-width plain text. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-02 23:13 UTC
Commit: 41f9224d581ead9f455f278f0cb6be9c886a1c03
Parent: f0c72dd
4 files changed, +246 insertions, -67 deletions
M Cargo.lock +230 -59
@@ -96,7 +96,7 @@ dependencies = [
96 96 "cssparser 0.35.0",
97 97 "html5ever 0.35.0",
98 98 "maplit",
99 - "tendril",
99 + "tendril 0.4.3",
100 100 "url",
101 101 ]
102 102
@@ -204,6 +204,7 @@ dependencies = [
204 204 "open",
205 205 "parking_lot",
206 206 "rand 0.8.5",
207 + "regex",
207 208 "roxmltree",
208 209 "serde",
209 210 "serde_json",
@@ -257,9 +258,9 @@ dependencies = [
257 258 "chrono",
258 259 "docengine",
259 260 "futures",
260 - "html2text",
261 261 "keyring",
262 262 "parking_lot",
263 + "pter",
263 264 "rand 0.8.5",
264 265 "readable-readability",
265 266 "regex",
@@ -273,6 +274,7 @@ dependencies = [
273 274 "tracing",
274 275 "ureq",
275 276 "url",
277 + "zeroize",
276 278 ]
277 279
278 280 [[package]]
@@ -796,6 +798,19 @@ dependencies = [
796 798 ]
797 799
798 800 [[package]]
801 + name = "cssparser"
802 + version = "0.36.0"
803 + source = "registry+https://github.com/rust-lang/crates.io-index"
804 + checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2"
805 + dependencies = [
806 + "cssparser-macros",
807 + "dtoa-short",
808 + "itoa 1.0.17",
809 + "phf 0.13.1",
810 + "smallvec",
811 + ]
812 +
813 + [[package]]
799 814 name = "cssparser-macros"
800 815 version = "0.6.1"
801 816 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -923,6 +938,27 @@ dependencies = [
923 938 ]
924 939
925 940 [[package]]
941 + name = "derive_more"
942 + version = "2.1.1"
943 + source = "registry+https://github.com/rust-lang/crates.io-index"
944 + checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
945 + dependencies = [
946 + "derive_more-impl",
947 + ]
948 +
949 + [[package]]
950 + name = "derive_more-impl"
951 + version = "2.1.1"
952 + source = "registry+https://github.com/rust-lang/crates.io-index"
953 + checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
954 + dependencies = [
955 + "proc-macro2",
956 + "quote",
957 + "rustc_version",
958 + "syn 2.0.114",
959 + ]
960 +
961 + [[package]]
926 962 name = "digest"
927 963 version = "0.10.7"
928 964 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1059,6 +1095,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1059 1095 checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
1060 1096
1061 1097 [[package]]
1098 + name = "ego-tree"
1099 + version = "0.11.0"
1100 + source = "registry+https://github.com/rust-lang/crates.io-index"
1101 + checksum = "b04dc5a38e4f151a79d9f2451ae6037fb6eaf5cba34771f44781f80e508498e3"
1102 +
1103 + [[package]]
1062 1104 name = "either"
1063 1105 version = "1.15.0"
1064 1106 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1505,7 +1547,7 @@ version = "0.2.24"
1505 1547 source = "registry+https://github.com/rust-lang/crates.io-index"
1506 1548 checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"
1507 1549 dependencies = [
1508 - "unicode-width 0.2.2",
1550 + "unicode-width",
1509 1551 ]
1510 1552
1511 1553 [[package]]
@@ -1803,19 +1845,6 @@ dependencies = [
1803 1845 ]
1804 1846
1805 1847 [[package]]
1806 - name = "html2text"
1807 - version = "0.12.6"
1808 - source = "registry+https://github.com/rust-lang/crates.io-index"
1809 - checksum = "042a9677c258ac2952dd026bb0cd21972f00f644a5a38f5a215cb22cdaf6834e"
1810 - dependencies = [
1811 - "html5ever 0.27.0",
1812 - "markup5ever 0.12.1",
1813 - "tendril",
1814 - "thiserror 1.0.69",
1815 - "unicode-width 0.1.13",
1816 - ]
1817 -
1818 - [[package]]
1819 1848 name = "html5ever"
1820 1849 version = "0.25.2"
1821 1850 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1831,20 +1860,6 @@ dependencies = [
1831 1860
1832 1861 [[package]]
1833 1862 name = "html5ever"
1834 - version = "0.27.0"
1835 - source = "registry+https://github.com/rust-lang/crates.io-index"
1836 - checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4"
1837 - dependencies = [
1838 - "log",
1839 - "mac",
1840 - "markup5ever 0.12.1",
1841 - "proc-macro2",
1842 - "quote",
1843 - "syn 2.0.114",
1844 - ]
1845 -
1846 - [[package]]
1847 - name = "html5ever"
1848 1863 version = "0.29.1"
1849 1864 source = "registry+https://github.com/rust-lang/crates.io-index"
1850 1865 checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c"
@@ -1867,6 +1882,16 @@ dependencies = [
1867 1882 ]
1868 1883
1869 1884 [[package]]
1885 + name = "html5ever"
1886 + version = "0.39.0"
1887 + source = "registry+https://github.com/rust-lang/crates.io-index"
1888 + checksum = "46a1761807faccc9a19e86944bbf40610014066306f96edcdedc2fb714bcb7b8"
1889 + dependencies = [
1890 + "log",
1891 + "markup5ever 0.39.0",
1892 + ]
1893 +
1894 + [[package]]
1870 1895 name = "http"
1871 1896 version = "1.4.0"
1872 1897 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2468,48 +2493,45 @@ dependencies = [
2468 2493 "log",
2469 2494 "phf 0.8.0",
2470 2495 "phf_codegen 0.8.0",
2471 - "string_cache",
2472 - "string_cache_codegen",
2473 - "tendril",
2496 + "string_cache 0.8.9",
2497 + "string_cache_codegen 0.5.4",
2498 + "tendril 0.4.3",
2474 2499 ]
2475 2500
2476 2501 [[package]]
2477 2502 name = "markup5ever"
2478 - version = "0.12.1"
2503 + version = "0.14.1"
2479 2504 source = "registry+https://github.com/rust-lang/crates.io-index"
2480 - checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45"
2505 + checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
2481 2506 dependencies = [
2482 2507 "log",
2483 2508 "phf 0.11.3",
2484 2509 "phf_codegen 0.11.3",
2485 - "string_cache",
2486 - "string_cache_codegen",
2487 - "tendril",
2510 + "string_cache 0.8.9",
2511 + "string_cache_codegen 0.5.4",
2512 + "tendril 0.4.3",
2488 2513 ]
2489 2514
2490 2515 [[package]]
2491 2516 name = "markup5ever"
2492 - version = "0.14.1"
2517 + version = "0.35.0"
2493 2518 source = "registry+https://github.com/rust-lang/crates.io-index"
2494 - checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
2519 + checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3"
2495 2520 dependencies = [
2496 2521 "log",
2497 - "phf 0.11.3",
2498 - "phf_codegen 0.11.3",
2499 - "string_cache",
2500 - "string_cache_codegen",
2501 - "tendril",
2522 + "tendril 0.4.3",
2523 + "web_atoms 0.1.3",
2502 2524 ]
2503 2525
2504 2526 [[package]]
2505 2527 name = "markup5ever"
2506 - version = "0.35.0"
2528 + version = "0.39.0"
2507 2529 source = "registry+https://github.com/rust-lang/crates.io-index"
2508 - checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3"
2530 + checksum = "7122d987ec5f704ee56f6e5b41a7d93722e9aae27ae07cafa4036c4d3f9757de"
2509 2531 dependencies = [
2510 2532 "log",
2511 - "tendril",
2512 - "web_atoms",
2533 + "tendril 0.5.0",
2534 + "web_atoms 0.2.4",
2513 2535 ]
2514 2536
2515 2537 [[package]]
@@ -3233,6 +3255,17 @@ dependencies = [
3233 3255 ]
3234 3256
3235 3257 [[package]]
3258 + name = "phf"
3259 + version = "0.13.1"
3260 + source = "registry+https://github.com/rust-lang/crates.io-index"
3261 + checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
3262 + dependencies = [
3263 + "phf_macros 0.13.1",
3264 + "phf_shared 0.13.1",
3265 + "serde",
3266 + ]
3267 +
3268 + [[package]]
3236 3269 name = "phf_codegen"
3237 3270 version = "0.8.0"
3238 3271 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3253,6 +3286,16 @@ dependencies = [
3253 3286 ]
3254 3287
3255 3288 [[package]]
3289 + name = "phf_codegen"
3290 + version = "0.13.1"
3291 + source = "registry+https://github.com/rust-lang/crates.io-index"
3292 + checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1"
3293 + dependencies = [
3294 + "phf_generator 0.13.1",
3295 + "phf_shared 0.13.1",
3296 + ]
3297 +
3298 + [[package]]
3256 3299 name = "phf_generator"
3257 3300 version = "0.8.0"
3258 3301 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3283,6 +3326,16 @@ dependencies = [
3283 3326 ]
3284 3327
3285 3328 [[package]]
3329 + name = "phf_generator"
3330 + version = "0.13.1"
3331 + source = "registry+https://github.com/rust-lang/crates.io-index"
3332 + checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
3333 + dependencies = [
3334 + "fastrand",
3335 + "phf_shared 0.13.1",
3336 + ]
3337 +
3338 + [[package]]
3286 3339 name = "phf_macros"
3287 3340 version = "0.8.0"
3288 3341 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3324,6 +3377,19 @@ dependencies = [
3324 3377 ]
3325 3378
3326 3379 [[package]]
3380 + name = "phf_macros"
3381 + version = "0.13.1"
3382 + source = "registry+https://github.com/rust-lang/crates.io-index"
3383 + checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef"
3384 + dependencies = [
3385 + "phf_generator 0.13.1",
3386 + "phf_shared 0.13.1",
3387 + "proc-macro2",
3388 + "quote",
3389 + "syn 2.0.114",
3390 + ]
3391 +
3392 + [[package]]
3327 3393 name = "phf_shared"
3328 3394 version = "0.8.0"
3329 3395 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3351,6 +3417,15 @@ dependencies = [
3351 3417 ]
3352 3418
3353 3419 [[package]]
3420 + name = "phf_shared"
3421 + version = "0.13.1"
3422 + source = "registry+https://github.com/rust-lang/crates.io-index"
3423 + checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
3424 + dependencies = [
3425 + "siphasher 1.0.2",
3426 + ]
3427 +
3428 + [[package]]
3354 3429 name = "pin-project-lite"
3355 3430 version = "0.2.16"
3356 3431 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3543,6 +3618,13 @@ dependencies = [
3543 3618 ]
3544 3619
3545 3620 [[package]]
3621 + name = "pter"
3622 + version = "0.1.0"
3623 + dependencies = [
3624 + "scraper",
3625 + ]
3626 +
3627 + [[package]]
3546 3628 name = "pulldown-cmark"
3547 3629 version = "0.12.2"
3548 3630 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3938,6 +4020,12 @@ dependencies = [
3938 4020 ]
3939 4021
3940 4022 [[package]]
4023 + name = "rustc-hash"
4024 + version = "2.1.2"
4025 + source = "registry+https://github.com/rust-lang/crates.io-index"
4026 + checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
4027 +
4028 + [[package]]
3941 4029 name = "rustc_version"
3942 4030 version = "0.4.1"
3943 4031 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4121,6 +4209,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
4121 4209 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
4122 4210
4123 4211 [[package]]
4212 + name = "scraper"
4213 + version = "0.26.0"
4214 + source = "registry+https://github.com/rust-lang/crates.io-index"
4215 + checksum = "f0f5297102b8b62b4454ee8561601b2d551b4913148feb4241ca9d1a04bf4526"
4216 + dependencies = [
4217 + "cssparser 0.36.0",
4218 + "ego-tree",
4219 + "getopts",
4220 + "html5ever 0.39.0",
4221 + "precomputed-hash",
4222 + "selectors 0.36.1",
4223 + "tendril 0.5.0",
4224 + ]
4225 +
4226 + [[package]]
4124 4227 name = "security-framework"
4125 4228 version = "3.6.0"
4126 4229 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4151,7 +4254,7 @@ checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe"
4151 4254 dependencies = [
4152 4255 "bitflags 1.3.2",
4153 4256 "cssparser 0.27.2",
4154 - "derive_more",
4257 + "derive_more 0.99.20",
4155 4258 "fxhash",
4156 4259 "log",
4157 4260 "matches",
@@ -4171,7 +4274,7 @@ checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416"
4171 4274 dependencies = [
4172 4275 "bitflags 1.3.2",
4173 4276 "cssparser 0.29.6",
4174 - "derive_more",
4277 + "derive_more 0.99.20",
4175 4278 "fxhash",
4176 4279 "log",
4177 4280 "phf 0.8.0",
@@ -4182,6 +4285,25 @@ dependencies = [
4182 4285 ]
4183 4286
4184 4287 [[package]]
4288 + name = "selectors"
4289 + version = "0.36.1"
4290 + source = "registry+https://github.com/rust-lang/crates.io-index"
4291 + checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c"
4292 + dependencies = [
4293 + "bitflags 2.10.0",
4294 + "cssparser 0.36.0",
4295 + "derive_more 2.1.1",
4296 + "log",
4297 + "new_debug_unreachable",
4298 + "phf 0.13.1",
4299 + "phf_codegen 0.13.1",
4300 + "precomputed-hash",
4301 + "rustc-hash",
4302 + "servo_arc 0.4.3",
4303 + "smallvec",
4304 + ]
4305 +
4306 + [[package]]
4185 4307 name = "semver"
4186 4308 version = "1.0.27"
4187 4309 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4372,6 +4494,15 @@ dependencies = [
4372 4494 ]
4373 4495
4374 4496 [[package]]
4497 + name = "servo_arc"
4498 + version = "0.4.3"
4499 + source = "registry+https://github.com/rust-lang/crates.io-index"
4500 + checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930"
4501 + dependencies = [
4502 + "stable_deref_trait",
4503 + ]
4504 +
4505 + [[package]]
4375 4506 name = "sha1"
4376 4507 version = "0.10.6"
4377 4508 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4810,6 +4941,18 @@ dependencies = [
4810 4941 ]
4811 4942
4812 4943 [[package]]
4944 + name = "string_cache"
4945 + version = "0.9.0"
4946 + source = "registry+https://github.com/rust-lang/crates.io-index"
4947 + checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901"
4948 + dependencies = [
4949 + "new_debug_unreachable",
4950 + "parking_lot",
4951 + "phf_shared 0.13.1",
4952 + "precomputed-hash",
4953 + ]
4954 +
4955 + [[package]]
4813 4956 name = "string_cache_codegen"
4814 4957 version = "0.5.4"
4815 4958 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4822,6 +4965,18 @@ dependencies = [
4822 4965 ]
4823 4966
4824 4967 [[package]]
4968 + name = "string_cache_codegen"
4969 + version = "0.6.1"
4970 + source = "registry+https://github.com/rust-lang/crates.io-index"
4971 + checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69"
4972 + dependencies = [
4973 + "phf_generator 0.13.1",
4974 + "phf_shared 0.13.1",
4975 + "proc-macro2",
4976 + "quote",
4977 + ]
4978 +
4979 + [[package]]
4825 4980 name = "stringprep"
4826 4981 version = "0.1.5"
4827 4982 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5394,6 +5549,16 @@ dependencies = [
5394 5549 ]
5395 5550
5396 5551 [[package]]
5552 + name = "tendril"
5553 + version = "0.5.0"
5554 + source = "registry+https://github.com/rust-lang/crates.io-index"
5555 + checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24"
5556 + dependencies = [
5557 + "new_debug_unreachable",
5558 + "utf-8",
5559 + ]
5560 +
5561 + [[package]]
5397 5562 name = "theme-common"
5398 5563 version = "0.3.1"
5399 5564 dependencies = [
@@ -5925,12 +6090,6 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
5925 6090
5926 6091 [[package]]
5927 6092 name = "unicode-width"
5928 - version = "0.1.13"
5929 - source = "registry+https://github.com/rust-lang/crates.io-index"
5930 - checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
5931 -
5932 - [[package]]
5933 - name = "unicode-width"
5934 6093 version = "0.2.2"
5935 6094 source = "registry+https://github.com/rust-lang/crates.io-index"
5936 6095 checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
@@ -6214,8 +6373,20 @@ checksum = "57ffde1dc01240bdf9992e3205668b235e59421fd085e8a317ed98da0178d414"
6214 6373 dependencies = [
6215 6374 "phf 0.11.3",
6216 6375 "phf_codegen 0.11.3",
6217 - "string_cache",
6218 - "string_cache_codegen",
6376 + "string_cache 0.8.9",
6377 + "string_cache_codegen 0.5.4",
6378 + ]
6379 +
6380 + [[package]]
6381 + name = "web_atoms"
6382 + version = "0.2.4"
6383 + source = "registry+https://github.com/rust-lang/crates.io-index"
6384 + checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538"
6385 + dependencies = [
6386 + "phf 0.13.1",
6387 + "phf_codegen 0.13.1",
6388 + "string_cache 0.9.0",
6389 + "string_cache_codegen 0.6.1",
6219 6390 ]
6220 6391
6221 6392 [[package]]
M Cargo.toml +2
@@ -61,4 +61,6 @@ synckit-client = { path = "../../MNW/shared/synckit-client" }
61 61 tauri = "2.10.2"
62 62 tauri-plugin-updater = "2"
63 63 tagtree = { path = "../../MNW/shared/tagtree" }
64 + regex = "1"
65 + zeroize = "1"
64 66 wiremock = "0.6"
@@ -24,6 +24,9 @@ rand = { workspace = true }
24 24 # Keychain access for encryption key
25 25 keyring.workspace = true
26 26
27 + # Zeroing key material on drop
28 + zeroize.workspace = true
29 +
27 30 # Lock primitives (no poisoning)
28 31 parking_lot.workspace = true
29 32
@@ -36,8 +39,8 @@ ureq = { version = "2.12.1", features = ["json"] }
36 39 # XML parsing for RSS/Atom feeds in plugins
37 40 roxmltree.workspace = true
38 41
39 - # HTML to text conversion
40 - html2text = "0.12.6"
42 + # HTML to markdown conversion
43 + pter = { path = "../../../../pter" }
41 44
42 45 # URL parsing for tracker stripping
43 46 url = "2"
@@ -50,6 +50,8 @@ fn validate_url(url: &str) -> Result<(), String> {
50 50 host_and_port.split(':').next().unwrap_or("").to_string() // strip port
51 51 };
52 52 let host = host.as_str();
53 + // Strip userinfo (user@) from host to prevent blocklist bypass via http://user@localhost/
54 + let host = host.split('@').last().unwrap_or(host);
53 55 if host == "localhost"
54 56 || host == "127.0.0.1"
55 57 || host == "[::1]"
@@ -57,6 +59,7 @@ fn validate_url(url: &str) -> Result<(), String> {
57 59 || host.starts_with("10.")
58 60 || host.starts_with("192.168.")
59 61 || host.starts_with("169.254.")
62 + || host.starts_with("100.")
60 63 {
61 64 return Err(format!("Blocked request to internal address: {}", url));
62 65 }
@@ -260,9 +263,9 @@ pub(super) fn register_host_functions(
260 263 // Current UTC timestamp as Unix epoch seconds (i64).
261 264 engine.register_fn("timestamp_now", || -> i64 { chrono::Utc::now().timestamp() });
262 265
263 - // Strip HTML tags and render to plain text (80-char line width).
266 + // Convert HTML to readable markdown.
264 267 engine.register_fn("html_to_text", |html: &str| -> String {
265 - html2text::from_read(html.as_bytes(), 80)
268 + pter::convert(html)
266 269 });
267 270
268 271 // Truncate text with ellipsis (character-count aware for multibyte UTF-8)
@@ -370,8 +373,8 @@ pub(super) fn register_host_functions(
370 373 node.serialize(&mut content).unwrap_or_default();
371 374 let content_html = String::from_utf8_lossy(&content).to_string();
372 375
373 - // Plain text via html2text
374 - let text = html2text::from_read(content_html.as_bytes(), 80);
376 + // Readable markdown via pter
377 + let text = pter::convert(&content_html);
375 378
376 379 map.insert(
377 380 "title".into(),
@@ -426,9 +429,9 @@ mod tests {
426 429 .map_err(|e| format!("Date parse error: {}", e))
427 430 }
428 431
429 - /// Strip HTML tags and render to plain text (mirrors the Rhai closure).
432 + /// Convert HTML to readable markdown (mirrors the Rhai closure).
430 433 fn html_to_text(html: &str) -> String {
431 - html2text::from_read(html.as_bytes(), 80)
434 + pter::convert(html)
432 435 }
433 436
434 437 /// String contains check (mirrors the Rhai closure).