html-to-markdown 3.4.0 → 3.6.0.pre.rc.23

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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -0
  3. data/README.md +347 -0
  4. data/Steepfile +10 -2
  5. data/ext/html_to_markdown_rb/Cargo.toml +3 -2
  6. data/ext/html_to_markdown_rb/extconf.rb +5 -5
  7. data/ext/html_to_markdown_rb/native/Cargo.lock +962 -0
  8. data/ext/html_to_markdown_rb/native/Cargo.toml +6 -11
  9. data/ext/html_to_markdown_rb/native/extconf.rb +14 -0
  10. data/ext/html_to_markdown_rb/src/lib.rs +1715 -646
  11. data/lib/html_to_markdown/native.rb +913 -37
  12. data/lib/html_to_markdown/version.rb +3 -3
  13. data/lib/html_to_markdown.rb +9 -4
  14. data/lib/html_to_markdown_rb.so +0 -0
  15. data/sig/types.rbs +59 -292
  16. metadata +32 -179
  17. data/ext/html_to_markdown_rb/Makefile +0 -592
  18. data/lib/bin/html-to-markdown +0 -0
  19. data/vendor/Cargo.toml +0 -33
  20. data/vendor/html-to-markdown-rs/Cargo.toml +0 -54
  21. data/vendor/html-to-markdown-rs/README.md +0 -278
  22. data/vendor/html-to-markdown-rs/examples/basic.rs +0 -24
  23. data/vendor/html-to-markdown-rs/examples/table.rs +0 -25
  24. data/vendor/html-to-markdown-rs/examples/test_deser.rs +0 -12
  25. data/vendor/html-to-markdown-rs/examples/test_escape.rs +0 -58
  26. data/vendor/html-to-markdown-rs/examples/test_inline_formatting.rs +0 -113
  27. data/vendor/html-to-markdown-rs/examples/test_lists.rs +0 -39
  28. data/vendor/html-to-markdown-rs/examples/test_semantic_tags.rs +0 -89
  29. data/vendor/html-to-markdown-rs/examples/test_tables.rs +0 -100
  30. data/vendor/html-to-markdown-rs/examples/test_task_lists.rs +0 -61
  31. data/vendor/html-to-markdown-rs/examples/test_whitespace.rs +0 -34
  32. data/vendor/html-to-markdown-rs/src/convert_api.rs +0 -349
  33. data/vendor/html-to-markdown-rs/src/converter/block/blockquote.rs +0 -178
  34. data/vendor/html-to-markdown-rs/src/converter/block/container.rs +0 -114
  35. data/vendor/html-to-markdown-rs/src/converter/block/div.rs +0 -149
  36. data/vendor/html-to-markdown-rs/src/converter/block/heading.rs +0 -428
  37. data/vendor/html-to-markdown-rs/src/converter/block/horizontal_rule.rs +0 -103
  38. data/vendor/html-to-markdown-rs/src/converter/block/line_break.rs +0 -89
  39. data/vendor/html-to-markdown-rs/src/converter/block/mod.rs +0 -10
  40. data/vendor/html-to-markdown-rs/src/converter/block/paragraph.rs +0 -140
  41. data/vendor/html-to-markdown-rs/src/converter/block/preformatted.rs +0 -298
  42. data/vendor/html-to-markdown-rs/src/converter/block/table/builder.rs +0 -453
  43. data/vendor/html-to-markdown-rs/src/converter/block/table/caption.rs +0 -44
  44. data/vendor/html-to-markdown-rs/src/converter/block/table/cell.rs +0 -276
  45. data/vendor/html-to-markdown-rs/src/converter/block/table/cells.rs +0 -336
  46. data/vendor/html-to-markdown-rs/src/converter/block/table/layout.rs +0 -58
  47. data/vendor/html-to-markdown-rs/src/converter/block/table/mod.rs +0 -266
  48. data/vendor/html-to-markdown-rs/src/converter/block/table/scanner.rs +0 -146
  49. data/vendor/html-to-markdown-rs/src/converter/block/table/utils.rs +0 -34
  50. data/vendor/html-to-markdown-rs/src/converter/block/unknown.rs +0 -138
  51. data/vendor/html-to-markdown-rs/src/converter/context.rs +0 -208
  52. data/vendor/html-to-markdown-rs/src/converter/dom_context.rs +0 -337
  53. data/vendor/html-to-markdown-rs/src/converter/form/elements.rs +0 -770
  54. data/vendor/html-to-markdown-rs/src/converter/form/mod.rs +0 -82
  55. data/vendor/html-to-markdown-rs/src/converter/format/djot.rs +0 -64
  56. data/vendor/html-to-markdown-rs/src/converter/format/markdown.rs +0 -59
  57. data/vendor/html-to-markdown-rs/src/converter/format/mod.rs +0 -43
  58. data/vendor/html-to-markdown-rs/src/converter/handlers/blockquote.rs +0 -173
  59. data/vendor/html-to-markdown-rs/src/converter/handlers/code_block.rs +0 -434
  60. data/vendor/html-to-markdown-rs/src/converter/handlers/graphic.rs +0 -234
  61. data/vendor/html-to-markdown-rs/src/converter/handlers/image.rs +0 -282
  62. data/vendor/html-to-markdown-rs/src/converter/handlers/link.rs +0 -316
  63. data/vendor/html-to-markdown-rs/src/converter/handlers/mod.rs +0 -26
  64. data/vendor/html-to-markdown-rs/src/converter/inline/code.rs +0 -306
  65. data/vendor/html-to-markdown-rs/src/converter/inline/emphasis.rs +0 -345
  66. data/vendor/html-to-markdown-rs/src/converter/inline/link.rs +0 -428
  67. data/vendor/html-to-markdown-rs/src/converter/inline/mod.rs +0 -237
  68. data/vendor/html-to-markdown-rs/src/converter/inline/ruby.rs +0 -337
  69. data/vendor/html-to-markdown-rs/src/converter/inline/semantic/marks.rs +0 -566
  70. data/vendor/html-to-markdown-rs/src/converter/inline/semantic/mod.rs +0 -86
  71. data/vendor/html-to-markdown-rs/src/converter/inline/semantic/typography.rs +0 -558
  72. data/vendor/html-to-markdown-rs/src/converter/list/definition.rs +0 -232
  73. data/vendor/html-to-markdown-rs/src/converter/list/item.rs +0 -332
  74. data/vendor/html-to-markdown-rs/src/converter/list/mod.rs +0 -70
  75. data/vendor/html-to-markdown-rs/src/converter/list/ordered.rs +0 -201
  76. data/vendor/html-to-markdown-rs/src/converter/list/unordered.rs +0 -195
  77. data/vendor/html-to-markdown-rs/src/converter/list/utils.rs +0 -314
  78. data/vendor/html-to-markdown-rs/src/converter/main.rs +0 -710
  79. data/vendor/html-to-markdown-rs/src/converter/main_helpers.rs +0 -452
  80. data/vendor/html-to-markdown-rs/src/converter/media/embedded.rs +0 -393
  81. data/vendor/html-to-markdown-rs/src/converter/media/graphic.rs +0 -4
  82. data/vendor/html-to-markdown-rs/src/converter/media/image.rs +0 -183
  83. data/vendor/html-to-markdown-rs/src/converter/media/mod.rs +0 -87
  84. data/vendor/html-to-markdown-rs/src/converter/media/svg.rs +0 -280
  85. data/vendor/html-to-markdown-rs/src/converter/metadata.rs +0 -220
  86. data/vendor/html-to-markdown-rs/src/converter/mod.rs +0 -156
  87. data/vendor/html-to-markdown-rs/src/converter/plain_text.rs +0 -516
  88. data/vendor/html-to-markdown-rs/src/converter/preprocessing_helpers.rs +0 -201
  89. data/vendor/html-to-markdown-rs/src/converter/reference_collector.rs +0 -69
  90. data/vendor/html-to-markdown-rs/src/converter/semantic/attributes.rs +0 -269
  91. data/vendor/html-to-markdown-rs/src/converter/semantic/definition_list.rs +0 -266
  92. data/vendor/html-to-markdown-rs/src/converter/semantic/figure.rs +0 -391
  93. data/vendor/html-to-markdown-rs/src/converter/semantic/mod.rs +0 -112
  94. data/vendor/html-to-markdown-rs/src/converter/semantic/sectioning.rs +0 -85
  95. data/vendor/html-to-markdown-rs/src/converter/semantic/summary.rs +0 -324
  96. data/vendor/html-to-markdown-rs/src/converter/text/mod.rs +0 -8
  97. data/vendor/html-to-markdown-rs/src/converter/text/processing.rs +0 -56
  98. data/vendor/html-to-markdown-rs/src/converter/text_node.rs +0 -269
  99. data/vendor/html-to-markdown-rs/src/converter/utility/attributes.rs +0 -151
  100. data/vendor/html-to-markdown-rs/src/converter/utility/caching.rs +0 -74
  101. data/vendor/html-to-markdown-rs/src/converter/utility/content.rs +0 -271
  102. data/vendor/html-to-markdown-rs/src/converter/utility/mod.rs +0 -17
  103. data/vendor/html-to-markdown-rs/src/converter/utility/preprocessing.rs +0 -1002
  104. data/vendor/html-to-markdown-rs/src/converter/utility/serialization.rs +0 -126
  105. data/vendor/html-to-markdown-rs/src/converter/utility/siblings.rs +0 -97
  106. data/vendor/html-to-markdown-rs/src/converter/visitor_hooks.rs +0 -189
  107. data/vendor/html-to-markdown-rs/src/error.rs +0 -43
  108. data/vendor/html-to-markdown-rs/src/exports.rs +0 -24
  109. data/vendor/html-to-markdown-rs/src/inline_images.rs +0 -336
  110. data/vendor/html-to-markdown-rs/src/lib.rs +0 -139
  111. data/vendor/html-to-markdown-rs/src/metadata/collector.rs +0 -457
  112. data/vendor/html-to-markdown-rs/src/metadata/config.rs +0 -394
  113. data/vendor/html-to-markdown-rs/src/metadata/extraction.rs +0 -398
  114. data/vendor/html-to-markdown-rs/src/metadata/mod.rs +0 -288
  115. data/vendor/html-to-markdown-rs/src/metadata/types.rs +0 -477
  116. data/vendor/html-to-markdown-rs/src/options/conversion.rs +0 -559
  117. data/vendor/html-to-markdown-rs/src/options/inline_image.rs +0 -111
  118. data/vendor/html-to-markdown-rs/src/options/mod.rs +0 -20
  119. data/vendor/html-to-markdown-rs/src/options/preprocessing.rs +0 -201
  120. data/vendor/html-to-markdown-rs/src/options/validation.rs +0 -416
  121. data/vendor/html-to-markdown-rs/src/prelude.rs +0 -1
  122. data/vendor/html-to-markdown-rs/src/rcdom.rs +0 -487
  123. data/vendor/html-to-markdown-rs/src/text.rs +0 -358
  124. data/vendor/html-to-markdown-rs/src/types/document.rs +0 -191
  125. data/vendor/html-to-markdown-rs/src/types/mod.rs +0 -17
  126. data/vendor/html-to-markdown-rs/src/types/result.rs +0 -54
  127. data/vendor/html-to-markdown-rs/src/types/structure_builder.rs +0 -791
  128. data/vendor/html-to-markdown-rs/src/types/structure_collector.rs +0 -483
  129. data/vendor/html-to-markdown-rs/src/types/tables.rs +0 -52
  130. data/vendor/html-to-markdown-rs/src/types/warnings.rs +0 -33
  131. data/vendor/html-to-markdown-rs/src/validation.rs +0 -158
  132. data/vendor/html-to-markdown-rs/src/visitor/default_impl.rs +0 -63
  133. data/vendor/html-to-markdown-rs/src/visitor/mod.rs +0 -41
  134. data/vendor/html-to-markdown-rs/src/visitor/traits.rs +0 -370
  135. data/vendor/html-to-markdown-rs/src/visitor/types.rs +0 -319
  136. data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/callbacks/mod.rs +0 -1
  137. data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/content.rs +0 -126
  138. data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/mod.rs +0 -27
  139. data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/state.rs +0 -110
  140. data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/traversal.rs +0 -250
  141. data/vendor/html-to-markdown-rs/src/visitor_helpers.rs +0 -597
  142. data/vendor/html-to-markdown-rs/src/wrapper/sync.rs +0 -413
  143. data/vendor/html-to-markdown-rs/src/wrapper/utils.rs +0 -290
  144. data/vendor/html-to-markdown-rs/src/wrapper.rs +0 -9
  145. data/vendor/html-to-markdown-rs/tests/br_in_inline_test.rs +0 -87
  146. data/vendor/html-to-markdown-rs/tests/commonmark_compliance_test.rs +0 -297
  147. data/vendor/html-to-markdown-rs/tests/djot_output_test.rs +0 -153
  148. data/vendor/html-to-markdown-rs/tests/exclude_selectors_test.rs +0 -132
  149. data/vendor/html-to-markdown-rs/tests/integration_test.rs +0 -631
  150. data/vendor/html-to-markdown-rs/tests/issue_121_regressions.rs +0 -49
  151. data/vendor/html-to-markdown-rs/tests/issue_127_regressions.rs +0 -58
  152. data/vendor/html-to-markdown-rs/tests/issue_128_regressions.rs +0 -17
  153. data/vendor/html-to-markdown-rs/tests/issue_131_regressions.rs +0 -41
  154. data/vendor/html-to-markdown-rs/tests/issue_134_regressions.rs +0 -40
  155. data/vendor/html-to-markdown-rs/tests/issue_139_regressions.rs +0 -26
  156. data/vendor/html-to-markdown-rs/tests/issue_140_regressions.rs +0 -185
  157. data/vendor/html-to-markdown-rs/tests/issue_143_regressions.rs +0 -100
  158. data/vendor/html-to-markdown-rs/tests/issue_145_regressions.rs +0 -133
  159. data/vendor/html-to-markdown-rs/tests/issue_146_regressions.rs +0 -144
  160. data/vendor/html-to-markdown-rs/tests/issue_176_regressions.rs +0 -62
  161. data/vendor/html-to-markdown-rs/tests/issue_190_regressions.rs +0 -128
  162. data/vendor/html-to-markdown-rs/tests/issue_199_regressions.rs +0 -20
  163. data/vendor/html-to-markdown-rs/tests/issue_200_regressions.rs +0 -62
  164. data/vendor/html-to-markdown-rs/tests/issue_212_regressions.rs +0 -68
  165. data/vendor/html-to-markdown-rs/tests/issue_216_217_regressions.rs +0 -87
  166. data/vendor/html-to-markdown-rs/tests/issue_336_regressions.rs +0 -74
  167. data/vendor/html-to-markdown-rs/tests/issue_339_regressions.rs +0 -92
  168. data/vendor/html-to-markdown-rs/tests/issue_347_regressions.rs +0 -154
  169. data/vendor/html-to-markdown-rs/tests/issue_348_visitor_plain.rs +0 -93
  170. data/vendor/html-to-markdown-rs/tests/json_ld_script_extraction.rs +0 -44
  171. data/vendor/html-to-markdown-rs/tests/lists_test.rs +0 -199
  172. data/vendor/html-to-markdown-rs/tests/plain_output_test.rs +0 -273
  173. data/vendor/html-to-markdown-rs/tests/preprocessing_tests.rs +0 -61
  174. data/vendor/html-to-markdown-rs/tests/reference_links_test.rs +0 -169
  175. data/vendor/html-to-markdown-rs/tests/sectioning_elements_test.rs +0 -137
  176. data/vendor/html-to-markdown-rs/tests/skip_images_test.rs +0 -522
  177. data/vendor/html-to-markdown-rs/tests/tables_test.rs +0 -743
  178. data/vendor/html-to-markdown-rs/tests/test_custom_elements.rs +0 -41
  179. data/vendor/html-to-markdown-rs/tests/test_issue_187.rs +0 -204
  180. data/vendor/html-to-markdown-rs/tests/test_issue_218.rs +0 -68
  181. data/vendor/html-to-markdown-rs/tests/test_issue_277.rs +0 -77
  182. data/vendor/html-to-markdown-rs/tests/test_max_depth.rs +0 -82
  183. data/vendor/html-to-markdown-rs/tests/test_nested_simple.rs +0 -45
  184. data/vendor/html-to-markdown-rs/tests/test_script_style_stripping.rs +0 -396
  185. data/vendor/html-to-markdown-rs/tests/test_spa_bisect.rs +0 -34
  186. data/vendor/html-to-markdown-rs/tests/visitor_code_integration_test.rs +0 -121
  187. data/vendor/html-to-markdown-rs/tests/visitor_integration_test.rs +0 -1190
  188. data/vendor/html-to-markdown-rs/tests/xml_tables_test.rs +0 -372
@@ -1,522 +0,0 @@
1
- #![allow(missing_docs)]
2
-
3
- use html_to_markdown_rs::ConversionOptions;
4
-
5
- #[test]
6
- fn test_skip_images_enabled() {
7
- // Verify that when skip_images: true, all img tags are omitted
8
- let html = r#"<p>Here is an image:</p>
9
- <img src="test.jpg" alt="Test Image" />
10
- <p>And here is some text after.</p>"#;
11
-
12
- let options = ConversionOptions {
13
- skip_images: true,
14
- ..Default::default()
15
- };
16
-
17
- let result = convert(html, Some(options)).unwrap();
18
-
19
- // Should contain text content
20
- assert!(result.contains("Here is an image"), "Should contain text before image");
21
- assert!(
22
- result.contains("And here is some text after"),
23
- "Should contain text after image"
24
- );
25
-
26
- // Should NOT contain the image markdown
27
- assert!(!result.contains("![Test Image]"), "Should not contain image markdown");
28
- assert!(!result.contains("test.jpg"), "Should not contain image URL");
29
- }
30
-
31
- #[test]
32
- fn test_skip_images_skips_svg_output() {
33
- let html = r#"<svg width="10" height="10"><title>Logo</title><rect width="10" height="10"/></svg>"#;
34
-
35
- let options = ConversionOptions {
36
- skip_images: true,
37
- ..Default::default()
38
- };
39
-
40
- let result = convert(html, Some(options)).unwrap();
41
-
42
- assert!(
43
- !result.contains("data:image/svg+xml"),
44
- "Should not include SVG data URIs when skip_images is enabled"
45
- );
46
- assert!(
47
- !result.contains("SVG Image"),
48
- "Should not include SVG alt text when skip_images is enabled"
49
- );
50
- }
51
-
52
- #[test]
53
- fn test_skip_images_disabled() {
54
- // Verify that when skip_images: false (default), images are converted to markdown
55
- let html = r#"<p>Here is an image:</p>
56
- <img src="test.jpg" alt="Test Image" />
57
- <p>And here is some text after.</p>"#;
58
-
59
- let options = ConversionOptions {
60
- skip_images: false,
61
- ..Default::default()
62
- };
63
-
64
- let result = convert(html, Some(options)).unwrap();
65
-
66
- // Should contain text content
67
- assert!(result.contains("Here is an image"), "Should contain text before image");
68
- assert!(
69
- result.contains("And here is some text after"),
70
- "Should contain text after image"
71
- );
72
-
73
- // Should contain the image markdown
74
- assert!(result.contains("![Test Image]"), "Should contain image markdown");
75
- assert!(result.contains("test.jpg"), "Should contain image URL");
76
- }
77
-
78
- #[test]
79
- fn test_skip_images_default_behavior() {
80
- // Verify that default behavior (without specifying skip_images) includes images
81
- let html = r#"<img src="default.png" alt="Default Image" />"#;
82
-
83
- let result = convert(html, None).unwrap();
84
-
85
- // Default should be to include images (skip_images: false)
86
- assert!(result.contains("![Default Image]"), "Default should include images");
87
- assert!(result.contains("default.png"), "Default should include image URLs");
88
- }
89
-
90
- #[test]
91
- fn test_skip_images_mixed_content() {
92
- // Test HTML with both images and other content to ensure only images are skipped
93
- let html = r#"<article>
94
- <h1>Article Title</h1>
95
- <p>Introduction paragraph.</p>
96
- <img src="hero.jpg" alt="Hero Image" />
97
- <h2>Section One</h2>
98
- <p>Section content with <strong>bold text</strong> and <em>italic text</em>.</p>
99
- <img src="section-image.png" alt="Section Image" />
100
- <h2>Section Two</h2>
101
- <p>More content here.</p>
102
- <img src="footer-image.gif" alt="Footer Image" />
103
- <footer>
104
- <p>Footer text with a <a href="https://example.com">link</a>.</p>
105
- </footer>
106
- </article>"#;
107
-
108
- let options = ConversionOptions {
109
- skip_images: true,
110
- ..Default::default()
111
- };
112
-
113
- let result = convert(html, Some(options)).unwrap();
114
-
115
- // Should contain all text content
116
- assert!(result.contains("Article Title"), "Should contain heading");
117
- assert!(result.contains("Introduction paragraph"), "Should contain intro");
118
- assert!(result.contains("Section One"), "Should contain section heading");
119
- assert!(result.contains("Section content"), "Should contain section content");
120
- assert!(result.contains("bold text"), "Should contain bold text");
121
- assert!(result.contains("italic text"), "Should contain italic text");
122
- assert!(result.contains("Section Two"), "Should contain second section");
123
- assert!(result.contains("More content"), "Should contain more content");
124
- assert!(result.contains("Footer text"), "Should contain footer");
125
- assert!(result.contains("example.com"), "Should contain link");
126
-
127
- // Should NOT contain any images
128
- assert!(!result.contains("![Hero Image]"), "Should not contain hero image");
129
- assert!(!result.contains("hero.jpg"), "Should not contain hero image URL");
130
- assert!(!result.contains("![Section Image]"), "Should not contain section image");
131
- assert!(
132
- !result.contains("section-image.png"),
133
- "Should not contain section image URL"
134
- );
135
- assert!(!result.contains("![Footer Image]"), "Should not contain footer image");
136
- assert!(
137
- !result.contains("footer-image.gif"),
138
- "Should not contain footer image URL"
139
- );
140
- }
141
-
142
- #[test]
143
- fn test_skip_images_with_base64_data_uri() {
144
- // Verify base64 data URI images are skipped
145
- let html = r#"<p>Before image</p>
146
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" alt="Embedded PNG" />
147
- <p>After image</p>"#;
148
-
149
- let options = ConversionOptions {
150
- skip_images: true,
151
- ..Default::default()
152
- };
153
-
154
- let result = convert(html, Some(options)).unwrap();
155
-
156
- // Should contain text
157
- assert!(result.contains("Before image"), "Should contain text before image");
158
- assert!(result.contains("After image"), "Should contain text after image");
159
-
160
- // Should NOT contain base64 data or image markdown
161
- assert!(!result.contains("![Embedded PNG]"), "Should not contain base64 image");
162
- assert!(!result.contains("data:image"), "Should not contain data URI");
163
- assert!(!result.contains("iVBORw0KGgo"), "Should not contain base64 content");
164
- }
165
-
166
- #[test]
167
- fn test_skip_images_with_external_urls() {
168
- // Verify external URL images are skipped
169
- let html = r#"<section>
170
- <h1>Photo Gallery</h1>
171
- <p>Check out these amazing photos:</p>
172
- <img src="https://example.com/images/photo1.jpg" alt="Photo 1" />
173
- <img src="https://cdn.example.org/photo2.png" alt="Photo 2" />
174
- <img src="https://images.example.net/photo3.webp" alt="Photo 3" />
175
- <p>Thanks for viewing!</p>
176
- </section>"#;
177
-
178
- let options = ConversionOptions {
179
- skip_images: true,
180
- ..Default::default()
181
- };
182
-
183
- let result = convert(html, Some(options)).unwrap();
184
-
185
- // Should contain text content
186
- assert!(result.contains("Photo Gallery"), "Should contain gallery heading");
187
- assert!(result.contains("Check out"), "Should contain intro text");
188
- assert!(result.contains("Thanks for viewing"), "Should contain closing text");
189
-
190
- // Should NOT contain any image references
191
- assert!(
192
- !result.contains("![Photo 1]"),
193
- "Should not contain first photo markdown"
194
- );
195
- assert!(
196
- !result.contains("![Photo 2]"),
197
- "Should not contain second photo markdown"
198
- );
199
- assert!(
200
- !result.contains("![Photo 3]"),
201
- "Should not contain third photo markdown"
202
- );
203
- assert!(!result.contains("example.com/images"), "Should not contain photo URLs");
204
- assert!(!result.contains("cdn.example.org"), "Should not contain CDN URLs");
205
- }
206
-
207
- #[test]
208
- fn test_skip_images_preserves_alt_text_context() {
209
- // Ensure surrounding content is preserved correctly and not confused with alt text
210
- let html = r#"<div>
211
- <p>The following image demonstrates our product:</p>
212
- <img src="product.jpg" alt="Product Screenshot" />
213
- <p>As you can see, this is how the interface looks.</p>
214
- <img src="feature.png" alt="Feature Comparison Chart" />
215
- <p>Our solution outperforms the competition.</p>
216
- </div>"#;
217
-
218
- let options = ConversionOptions {
219
- skip_images: true,
220
- ..Default::default()
221
- };
222
-
223
- let result = convert(html, Some(options)).unwrap();
224
-
225
- // Verify all surrounding text is present and properly ordered
226
- assert!(result.contains("following image"), "Should contain introductory text");
227
- assert!(
228
- result.contains("how the interface looks"),
229
- "Should contain descriptive text"
230
- );
231
- assert!(
232
- result.contains("solution outperforms"),
233
- "Should contain concluding text"
234
- );
235
-
236
- // Verify images are not present (alt text is not included as text)
237
- assert!(!result.contains("Product Screenshot"), "Should not include alt text");
238
- assert!(
239
- !result.contains("Feature Comparison Chart"),
240
- "Should not include alt text"
241
- );
242
- assert!(!result.contains("product.jpg"), "Should not contain image URL");
243
- assert!(!result.contains("feature.png"), "Should not contain image URL");
244
- }
245
-
246
- #[test]
247
- fn test_skip_images_inline_vs_block_images() {
248
- // Test skipping both inline and block-level images
249
- let html = r#"<p>Start of paragraph with <img src="inline.jpg" alt="Inline" /> in the middle.</p>
250
- <img src="block.png" alt="Block" />
251
- <p>End of content.</p>"#;
252
-
253
- let options = ConversionOptions {
254
- skip_images: true,
255
- ..Default::default()
256
- };
257
-
258
- let result = convert(html, Some(options)).unwrap();
259
-
260
- // Should contain paragraph text
261
- assert!(result.contains("Start of paragraph"), "Should contain paragraph start");
262
- assert!(result.contains("in the middle"), "Should contain paragraph content");
263
- assert!(result.contains("End of content"), "Should contain paragraph end");
264
-
265
- // Should not contain either image
266
- assert!(!result.contains("![Inline]"), "Should not contain inline image");
267
- assert!(!result.contains("inline.jpg"), "Should not contain inline image URL");
268
- assert!(!result.contains("![Block]"), "Should not contain block image");
269
- assert!(!result.contains("block.png"), "Should not contain block image URL");
270
- }
271
-
272
- #[test]
273
- fn test_skip_images_with_multiple_attributes() {
274
- // Test images with additional attributes (width, height, class, etc.)
275
- let html = r#"<img src="image.jpg" alt="Styled Image" width="500" height="300" class="responsive" data-lazy="true" />
276
- <p>Image with attributes above.</p>"#;
277
-
278
- let options = ConversionOptions {
279
- skip_images: true,
280
- ..Default::default()
281
- };
282
-
283
- let result = convert(html, Some(options)).unwrap();
284
-
285
- // Should contain text
286
- assert!(result.contains("Image with attributes"), "Should contain text");
287
-
288
- // Should not contain image or its attributes
289
- assert!(!result.contains("![Styled Image]"), "Should not contain image markdown");
290
- assert!(!result.contains("image.jpg"), "Should not contain image URL");
291
- assert!(!result.contains("500"), "Should not contain width attribute");
292
- assert!(!result.contains("300"), "Should not contain height attribute");
293
- }
294
-
295
- #[test]
296
- fn test_skip_images_empty_document() {
297
- // Test that skip_images doesn't break on documents with only images
298
- let html = r#"<img src="image1.jpg" alt="Image 1" />
299
- <img src="image2.png" alt="Image 2" />
300
- <img src="image3.gif" alt="Image 3" />"#;
301
-
302
- let options = ConversionOptions {
303
- skip_images: true,
304
- ..Default::default()
305
- };
306
-
307
- let result = convert(html, Some(options)).unwrap();
308
-
309
- // Result should be empty or near-empty (no meaningful content)
310
- // Just verify no images appear
311
- assert!(!result.contains("![Image 1]"), "Should not contain first image");
312
- assert!(!result.contains("![Image 2]"), "Should not contain second image");
313
- assert!(!result.contains("![Image 3]"), "Should not contain third image");
314
- }
315
-
316
- #[test]
317
- fn test_skip_images_with_lists_and_images() {
318
- // Test that skip_images works correctly with lists containing images
319
- let html = r#"<ul>
320
- <li>First item</li>
321
- <li><img src="list-item.jpg" alt="List Item Image" /> Item with image</li>
322
- <li>Third item</li>
323
- </ul>"#;
324
-
325
- let options = ConversionOptions {
326
- skip_images: true,
327
- ..Default::default()
328
- };
329
-
330
- let result = convert(html, Some(options)).unwrap();
331
-
332
- // Should contain list items
333
- assert!(result.contains("First item"), "Should contain first list item");
334
- assert!(result.contains("Item with image"), "Should contain list item text");
335
- assert!(result.contains("Third item"), "Should contain third list item");
336
-
337
- // Should not contain image
338
- assert!(
339
- !result.contains("![List Item Image]"),
340
- "Should not contain image in list"
341
- );
342
- assert!(
343
- !result.contains("list-item.jpg"),
344
- "Should not contain image URL in list"
345
- );
346
- }
347
-
348
- #[test]
349
- fn test_skip_images_with_table_images() {
350
- // Test that skip_images works correctly with images inside tables
351
- let html = r#"<table>
352
- <tr>
353
- <td>Cell 1</td>
354
- <td><img src="table-image.jpg" alt="Table Image" /></td>
355
- </tr>
356
- <tr>
357
- <td>Cell 3</td>
358
- <td>Cell 4</td>
359
- </tr>
360
- </table>"#;
361
-
362
- let options = ConversionOptions {
363
- skip_images: true,
364
- ..Default::default()
365
- };
366
-
367
- let result = convert(html, Some(options)).unwrap();
368
-
369
- // Should contain table content
370
- assert!(result.contains("Cell 1"), "Should contain table cell 1");
371
- assert!(result.contains("Cell 3"), "Should contain table cell 3");
372
- assert!(result.contains("Cell 4"), "Should contain table cell 4");
373
-
374
- // Should not contain image
375
- assert!(!result.contains("![Table Image]"), "Should not contain image in table");
376
- assert!(
377
- !result.contains("table-image.jpg"),
378
- "Should not contain image URL in table"
379
- );
380
- }
381
-
382
- #[test]
383
- fn test_skip_images_with_figure_figcaption() {
384
- // Test that skip_images removes images from figure elements
385
- let html = r#"<figure>
386
- <img src="diagram.svg" alt="Diagram" />
387
- <figcaption>This is a diagram caption</figcaption>
388
- </figure>
389
- <p>More content.</p>"#;
390
-
391
- let options = ConversionOptions {
392
- skip_images: true,
393
- ..Default::default()
394
- };
395
-
396
- let result = convert(html, Some(options)).unwrap();
397
-
398
- // Should contain caption text
399
- assert!(
400
- result.contains("This is a diagram caption"),
401
- "Should contain figcaption text"
402
- );
403
- assert!(result.contains("More content"), "Should contain following content");
404
-
405
- // Should not contain image
406
- assert!(!result.contains("![Diagram]"), "Should not contain image markdown");
407
- assert!(!result.contains("diagram.svg"), "Should not contain image URL");
408
- }
409
-
410
- #[test]
411
- fn test_skip_images_false_with_alt_text() {
412
- // When skip_images is false, verify images with alt text are converted correctly
413
- let html = r#"<p>Image below:</p>
414
- <img src="image.jpg" alt="Test Alt Text" />
415
- <p>Text below.</p>"#;
416
-
417
- let options = ConversionOptions {
418
- skip_images: false,
419
- ..Default::default()
420
- };
421
-
422
- let result = convert(html, Some(options)).unwrap();
423
-
424
- // Should include image with alt text
425
- assert!(
426
- result.contains("![Test Alt Text]"),
427
- "Should contain image markdown with alt text"
428
- );
429
- assert!(result.contains("image.jpg"), "Should contain image URL");
430
- }
431
-
432
- #[test]
433
- fn test_skip_images_false_without_alt_text() {
434
- // When skip_images is false, verify images without alt text are handled
435
- let html = r#"<p>Image below:</p>
436
- <img src="image.jpg" />
437
- <p>Text below.</p>"#;
438
-
439
- let options = ConversionOptions {
440
- skip_images: false,
441
- ..Default::default()
442
- };
443
-
444
- let result = convert(html, Some(options)).unwrap();
445
-
446
- // Should include image (even without alt text, may use empty alt or URL)
447
- assert!(result.contains("image.jpg"), "Should contain image URL");
448
- // The exact format for images without alt text depends on implementation
449
- }
450
-
451
- #[test]
452
- fn test_skip_images_with_picture_element() {
453
- // Test handling of picture elements with multiple sources
454
- let html = r#"<picture>
455
- <source srcset="image.webp" type="image/webp" />
456
- <source srcset="image.jpg" type="image/jpeg" />
457
- <img src="image.jpg" alt="Fallback Image" />
458
- </picture>
459
- <p>After picture element.</p>"#;
460
-
461
- let options = ConversionOptions {
462
- skip_images: true,
463
- ..Default::default()
464
- };
465
-
466
- let result = convert(html, Some(options)).unwrap();
467
-
468
- // Should contain text after
469
- assert!(
470
- result.contains("After picture element"),
471
- "Should contain text after picture"
472
- );
473
-
474
- // Should not contain any images or sources
475
- assert!(
476
- !result.contains("![Fallback Image]"),
477
- "Should not contain fallback image"
478
- );
479
- assert!(!result.contains("image.webp"), "Should not contain webp source");
480
- assert!(!result.contains("image.jpg"), "Should not contain jpg source");
481
- }
482
-
483
- #[test]
484
- fn test_skip_images_preserves_links_and_formatting() {
485
- // Verify that skip_images doesn't affect other markdown conversions
486
- let html = r#"<p>This is <strong>bold</strong>, <em>italic</em>, and <code>code</code>.</p>
487
- <p>Here's a <a href="https://example.com">link</a>.</p>
488
- <img src="ignored.jpg" alt="Ignored" />
489
- <p>And a quote:</p>
490
- <blockquote>
491
- <p>This is a blockquote.</p>
492
- </blockquote>"#;
493
-
494
- let options = ConversionOptions {
495
- skip_images: true,
496
- ..Default::default()
497
- };
498
-
499
- let result = convert(html, Some(options)).unwrap();
500
-
501
- // Should preserve formatting
502
- assert!(result.contains("**bold**"), "Should preserve bold");
503
- assert!(result.contains("*italic*"), "Should preserve italic");
504
- assert!(result.contains("`code`"), "Should preserve code");
505
-
506
- // Should preserve links
507
- assert!(result.contains("[link]"), "Should preserve link text");
508
- assert!(result.contains("https://example.com"), "Should preserve link URL");
509
-
510
- // Should preserve blockquote
511
- assert!(result.contains("This is a blockquote"), "Should preserve blockquote");
512
-
513
- // Should not contain image
514
- assert!(!result.contains("![Ignored]"), "Should not contain image");
515
- }
516
-
517
- fn convert(
518
- html: &str,
519
- opts: Option<html_to_markdown_rs::ConversionOptions>,
520
- ) -> html_to_markdown_rs::error::Result<String> {
521
- html_to_markdown_rs::convert(html, opts).map(|r| r.content.unwrap_or_default())
522
- }