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,319 +0,0 @@
1
- //! Type definitions for the visitor pattern.
2
- //!
3
- //! This module contains the core data types used in the visitor pattern:
4
- //! - `NodeType`: Categorization of HTML elements
5
- //! - `NodeContext`: Metadata about the current node being visited
6
- //! - `VisitResult`: Control flow signals from visitor methods
7
-
8
- use std::collections::BTreeMap;
9
-
10
- /// Node type enumeration covering all HTML element types.
11
- ///
12
- /// This enum categorizes all HTML elements that the converter recognizes,
13
- /// providing a coarse-grained classification for visitor dispatch.
14
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15
- #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16
- pub enum NodeType {
17
- /// Text node (most frequent - 100+ per document)
18
- Text,
19
-
20
- /// Generic element node
21
- Element,
22
-
23
- /// Heading elements (h1-h6)
24
- Heading,
25
- /// Paragraph element
26
- Paragraph,
27
- /// Generic div container
28
- Div,
29
- /// Blockquote element
30
- Blockquote,
31
- /// Preformatted text block
32
- Pre,
33
- /// Horizontal rule
34
- Hr,
35
-
36
- /// Ordered or unordered list (ul, ol)
37
- List,
38
- /// List item (li)
39
- ListItem,
40
- /// Definition list (dl)
41
- DefinitionList,
42
- /// Definition term (dt)
43
- DefinitionTerm,
44
- /// Definition description (dd)
45
- DefinitionDescription,
46
-
47
- /// Table element
48
- Table,
49
- /// Table row (tr)
50
- TableRow,
51
- /// Table cell (td, th)
52
- TableCell,
53
- /// Table header cell (th)
54
- TableHeader,
55
- /// Table body (tbody)
56
- TableBody,
57
- /// Table head (thead)
58
- TableHead,
59
- /// Table foot (tfoot)
60
- TableFoot,
61
-
62
- /// Anchor link (a)
63
- Link,
64
- /// Image (img)
65
- Image,
66
- /// Strong/bold (strong, b)
67
- Strong,
68
- /// Emphasis/italic (em, i)
69
- Em,
70
- /// Inline code (code)
71
- Code,
72
- /// Strikethrough (s, del, strike)
73
- Strikethrough,
74
- /// Underline (u, ins)
75
- Underline,
76
- /// Subscript (sub)
77
- Subscript,
78
- /// Superscript (sup)
79
- Superscript,
80
- /// Mark/highlight (mark)
81
- Mark,
82
- /// Small text (small)
83
- Small,
84
- /// Line break (br)
85
- Br,
86
- /// Span element
87
- Span,
88
-
89
- /// Article element
90
- Article,
91
- /// Section element
92
- Section,
93
- /// Navigation element
94
- Nav,
95
- /// Aside element
96
- Aside,
97
- /// Header element
98
- Header,
99
- /// Footer element
100
- Footer,
101
- /// Main element
102
- Main,
103
- /// Figure element
104
- Figure,
105
- /// Figure caption
106
- Figcaption,
107
- /// Time element
108
- Time,
109
- /// Details element
110
- Details,
111
- /// Summary element
112
- Summary,
113
-
114
- /// Form element
115
- Form,
116
- /// Input element
117
- Input,
118
- /// Select element
119
- Select,
120
- /// Option element
121
- Option,
122
- /// Button element
123
- Button,
124
- /// Textarea element
125
- Textarea,
126
- /// Label element
127
- Label,
128
- /// Fieldset element
129
- Fieldset,
130
- /// Legend element
131
- Legend,
132
-
133
- /// Audio element
134
- Audio,
135
- /// Video element
136
- Video,
137
- /// Picture element
138
- Picture,
139
- /// Source element
140
- Source,
141
- /// Iframe element
142
- Iframe,
143
- /// SVG element
144
- Svg,
145
- /// Canvas element
146
- Canvas,
147
-
148
- /// Ruby annotation
149
- Ruby,
150
- /// Ruby text
151
- Rt,
152
- /// Ruby parenthesis
153
- Rp,
154
- /// Abbreviation
155
- Abbr,
156
- /// Keyboard input
157
- Kbd,
158
- /// Sample output
159
- Samp,
160
- /// Variable
161
- Var,
162
- /// Citation
163
- Cite,
164
- /// Quote
165
- Q,
166
- /// Deleted text
167
- Del,
168
- /// Inserted text
169
- Ins,
170
- /// Data element
171
- Data,
172
- /// Meter element
173
- Meter,
174
- /// Progress element
175
- Progress,
176
- /// Output element
177
- Output,
178
- /// Template element
179
- Template,
180
- /// Slot element
181
- Slot,
182
-
183
- /// HTML root element
184
- Html,
185
- /// Head element
186
- Head,
187
- /// Body element
188
- Body,
189
- /// Title element
190
- Title,
191
- /// Meta element
192
- Meta,
193
- /// Link element (not anchor)
194
- LinkTag,
195
- /// Style element
196
- Style,
197
- /// Script element
198
- Script,
199
- /// Base element
200
- Base,
201
-
202
- /// Custom element (web components) or unknown tag
203
- Custom,
204
- }
205
-
206
- /// Context information passed to all visitor methods.
207
- ///
208
- /// Provides comprehensive metadata about the current node being visited,
209
- /// including its type, attributes, position in the DOM tree, and parent context.
210
- #[derive(Debug, Clone)]
211
- #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
212
- pub struct NodeContext {
213
- /// Coarse-grained node type classification
214
- pub node_type: NodeType,
215
-
216
- /// Raw HTML tag name (e.g., "div", "h1", "custom-element")
217
- pub tag_name: String,
218
-
219
- /// All HTML attributes as key-value pairs
220
- pub attributes: BTreeMap<String, String>,
221
-
222
- /// Depth in the DOM tree (0 = root)
223
- pub depth: usize,
224
-
225
- /// Index among siblings (0-based)
226
- pub index_in_parent: usize,
227
-
228
- /// Parent element's tag name (None if root)
229
- pub parent_tag: Option<String>,
230
-
231
- /// Whether this element is treated as inline vs block
232
- pub is_inline: bool,
233
- }
234
-
235
- /// Result of a visitor callback.
236
- ///
237
- /// Allows visitors to control the conversion flow by either proceeding
238
- /// with default behavior, providing custom output, skipping elements,
239
- /// preserving HTML, or signaling errors.
240
- #[derive(Debug, Clone, Default)]
241
- #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
242
- pub enum VisitResult {
243
- #[default]
244
- /// Continue with default conversion behavior
245
- Continue,
246
-
247
- /// Replace default output with custom markdown
248
- ///
249
- /// The visitor takes full responsibility for the markdown output
250
- /// of this node and its children.
251
- Custom(String),
252
-
253
- /// Skip this element entirely (don't output anything)
254
- ///
255
- /// The element and all its children are ignored in the output.
256
- Skip,
257
-
258
- /// Preserve original HTML (don't convert to markdown)
259
- ///
260
- /// The element's raw HTML is included verbatim in the output.
261
- PreserveHtml,
262
-
263
- /// Stop conversion with an error
264
- ///
265
- /// The conversion process halts and returns this error message.
266
- Error(String),
267
- }
268
-
269
- #[cfg(test)]
270
- mod tests {
271
- use super::*;
272
-
273
- #[test]
274
- fn test_node_type_equality() {
275
- assert_eq!(NodeType::Text, NodeType::Text);
276
- assert_ne!(NodeType::Text, NodeType::Element);
277
- assert_eq!(NodeType::Heading, NodeType::Heading);
278
- }
279
-
280
- #[test]
281
- fn test_node_context_creation() {
282
- let ctx = NodeContext {
283
- node_type: NodeType::Heading,
284
- tag_name: "h1".to_string(),
285
- attributes: BTreeMap::new(),
286
- depth: 1,
287
- index_in_parent: 0,
288
- parent_tag: Some("body".to_string()),
289
- is_inline: false,
290
- };
291
-
292
- assert_eq!(ctx.node_type, NodeType::Heading);
293
- assert_eq!(ctx.tag_name, "h1");
294
- assert_eq!(ctx.depth, 1);
295
- assert!(!ctx.is_inline);
296
- }
297
-
298
- #[test]
299
- fn test_visit_result_variants() {
300
- let continue_result = VisitResult::Continue;
301
- matches!(continue_result, VisitResult::Continue);
302
-
303
- let custom_result = VisitResult::Custom("# Custom Output".to_string());
304
- if let VisitResult::Custom(output) = custom_result {
305
- assert_eq!(output, "# Custom Output");
306
- }
307
-
308
- let skip_result = VisitResult::Skip;
309
- matches!(skip_result, VisitResult::Skip);
310
-
311
- let preserve_result = VisitResult::PreserveHtml;
312
- matches!(preserve_result, VisitResult::PreserveHtml);
313
-
314
- let error_result = VisitResult::Error("Test error".to_string());
315
- if let VisitResult::Error(msg) = error_result {
316
- assert_eq!(msg, "Test error");
317
- }
318
- }
319
- }
@@ -1 +0,0 @@
1
- //! Callback management for visitor pattern.
@@ -1,126 +0,0 @@
1
- //! Content extraction and result handling.
2
- //!
3
- //! This module provides the `VisitorDispatch` enum and helper methods for
4
- //! processing the results of visitor callbacks.
5
-
6
- /// Result of dispatching a visitor callback.
7
- ///
8
- /// This enum represents the outcome of a visitor callback dispatch,
9
- /// providing a more ergonomic interface for control flow than the
10
- /// raw `VisitResult` type.
11
- #[allow(dead_code)]
12
- #[derive(Debug)]
13
- pub enum VisitorDispatch {
14
- /// Continue with default conversion behavior
15
- Continue,
16
-
17
- /// Replace default output with custom markdown
18
- Custom(String),
19
-
20
- /// Skip this element entirely (don't output anything)
21
- Skip,
22
-
23
- /// Preserve original HTML (don't convert to markdown)
24
- PreserveHtml,
25
- }
26
-
27
- impl VisitorDispatch {
28
- /// Check if this dispatch result indicates continuation.
29
- #[allow(dead_code)]
30
- #[inline]
31
- #[must_use]
32
- pub const fn is_continue(&self) -> bool {
33
- matches!(self, Self::Continue)
34
- }
35
-
36
- /// Check if this dispatch result contains custom output.
37
- #[allow(dead_code)]
38
- #[inline]
39
- #[must_use]
40
- pub const fn is_custom(&self) -> bool {
41
- matches!(self, Self::Custom(_))
42
- }
43
-
44
- /// Check if this dispatch result indicates skipping.
45
- #[allow(dead_code)]
46
- #[inline]
47
- #[must_use]
48
- pub const fn is_skip(&self) -> bool {
49
- matches!(self, Self::Skip)
50
- }
51
-
52
- /// Check if this dispatch result indicates HTML preservation.
53
- #[allow(dead_code)]
54
- #[inline]
55
- #[must_use]
56
- pub const fn is_preserve_html(&self) -> bool {
57
- matches!(self, Self::PreserveHtml)
58
- }
59
-
60
- /// Extract custom output if present.
61
- #[allow(dead_code)]
62
- #[inline]
63
- #[must_use]
64
- pub fn into_custom(self) -> Option<String> {
65
- match self {
66
- Self::Custom(output) => Some(output),
67
- _ => None,
68
- }
69
- }
70
-
71
- /// Extract custom output reference if present.
72
- #[allow(dead_code)]
73
- #[inline]
74
- #[must_use]
75
- pub fn as_custom(&self) -> Option<&str> {
76
- match self {
77
- Self::Custom(output) => Some(output),
78
- _ => None,
79
- }
80
- }
81
- }
82
-
83
- #[cfg(test)]
84
- mod tests {
85
- use super::*;
86
-
87
- #[test]
88
- fn test_visitor_dispatch_predicates() {
89
- let continue_dispatch = VisitorDispatch::Continue;
90
- assert!(continue_dispatch.is_continue());
91
- assert!(!continue_dispatch.is_custom());
92
- assert!(!continue_dispatch.is_skip());
93
-
94
- let custom_dispatch = VisitorDispatch::Custom("output".to_string());
95
- assert!(!custom_dispatch.is_continue());
96
- assert!(custom_dispatch.is_custom());
97
- assert!(!custom_dispatch.is_skip());
98
-
99
- let skip_dispatch = VisitorDispatch::Skip;
100
- assert!(!skip_dispatch.is_continue());
101
- assert!(!skip_dispatch.is_custom());
102
- assert!(skip_dispatch.is_skip());
103
-
104
- let preserve_dispatch = VisitorDispatch::PreserveHtml;
105
- assert!(!preserve_dispatch.is_continue());
106
- assert!(preserve_dispatch.is_preserve_html());
107
- }
108
-
109
- #[test]
110
- fn test_visitor_dispatch_into_custom() {
111
- let custom = VisitorDispatch::Custom("test".to_string());
112
- assert_eq!(custom.into_custom(), Some("test".to_string()));
113
-
114
- let continue_dispatch = VisitorDispatch::Continue;
115
- assert_eq!(continue_dispatch.into_custom(), None);
116
- }
117
-
118
- #[test]
119
- fn test_visitor_dispatch_as_custom() {
120
- let custom = VisitorDispatch::Custom("test".to_string());
121
- assert_eq!(custom.as_custom(), Some("test"));
122
-
123
- let skip = VisitorDispatch::Skip;
124
- assert_eq!(skip.as_custom(), None);
125
- }
126
- }
@@ -1,27 +0,0 @@
1
- //! Helper functions for visitor pattern integration.
2
- //!
3
- //! This module provides efficient utilities for building visitor contexts,
4
- //! dispatching visitor callbacks, and handling visitor results during the
5
- //! HTML→Markdown conversion process.
6
- //!
7
- //! # Design Goals
8
- //!
9
- //! - **Zero allocation when possible**: Reuse existing data structures
10
- //! - **Minimal overhead**: Inline hot paths, avoid unnecessary clones
11
- //! - **Type safety**: Leverage Rust's type system for correct visitor handling
12
- //! - **Ergonomics**: Reduce boilerplate for common visitor patterns
13
- //!
14
- //! # Usage
15
- //!
16
- //! These helpers are designed to be used within the converter module during
17
- //! the DOM traversal. They bridge the gap between the internal conversion
18
- //! state and the public visitor API.
19
-
20
- pub mod callbacks;
21
- pub mod content;
22
- pub mod state;
23
- pub mod traversal;
24
-
25
- pub use content::VisitorDispatch;
26
- pub use state::build_node_context;
27
- pub use traversal::dispatch_visitor;
@@ -1,110 +0,0 @@
1
- //! Visitor state management and context building.
2
- //!
3
- //! This module handles construction of `NodeContext` objects that represent
4
- //! the state of DOM nodes during traversal.
5
-
6
- use std::collections::BTreeMap;
7
-
8
- use crate::visitor::NodeContext;
9
- use crate::visitor::NodeType;
10
-
11
- /// Build a `NodeContext` from current parsing state.
12
- ///
13
- /// Creates a complete `NodeContext` suitable for passing to visitor callbacks.
14
- /// This function collects metadata about the current node from various sources:
15
- /// - Tag name and attributes from the HTML element
16
- /// - Depth and parent information from the DOM tree
17
- /// - Index among siblings for positional awareness
18
- /// - Inline/block classification
19
- ///
20
- /// # Parameters
21
- ///
22
- /// - `node_type`: Coarse-grained classification (Link, Image, Heading, etc.)
23
- /// - `tag_name`: Raw HTML tag name (e.g., "div", "h1", "custom-element")
24
- /// - `attributes`: All HTML attributes as key-value pairs
25
- /// - `depth`: Nesting depth in the DOM tree (0 = root)
26
- /// - `index_in_parent`: Zero-based index among siblings
27
- /// - `parent_tag`: Parent element's tag name (None if root)
28
- /// - `is_inline`: Whether this element is treated as inline vs block
29
- ///
30
- /// # Returns
31
- ///
32
- /// A fully populated `NodeContext` ready for visitor dispatch.
33
- ///
34
- /// # Performance
35
- ///
36
- /// This function performs minimal allocations:
37
- /// - Clones `tag_name` (typically 2-10 bytes)
38
- /// - Clones `parent_tag` if present (typically 2-10 bytes)
39
- /// - Clones the attributes `BTreeMap` (heap allocation if non-empty)
40
- ///
41
- /// For text nodes and simple elements without attributes, allocations are minimal.
42
- ///
43
- /// # Examples
44
- ///
45
- /// ```text
46
- /// let ctx = build_node_context(
47
- /// NodeType::Heading,
48
- /// "h1",
49
- /// &attrs,
50
- /// 1,
51
- /// 0,
52
- /// Some("body"),
53
- /// false,
54
- /// );
55
- /// ```
56
- #[allow(dead_code)]
57
- #[inline]
58
- pub fn build_node_context(
59
- node_type: NodeType,
60
- tag_name: &str,
61
- attributes: &BTreeMap<String, String>,
62
- depth: usize,
63
- index_in_parent: usize,
64
- parent_tag: Option<&str>,
65
- is_inline: bool,
66
- ) -> NodeContext {
67
- NodeContext {
68
- node_type,
69
- tag_name: tag_name.to_string(),
70
- attributes: attributes.clone(),
71
- depth,
72
- index_in_parent,
73
- parent_tag: parent_tag.map(String::from),
74
- is_inline,
75
- }
76
- }
77
-
78
- #[cfg(test)]
79
- mod tests {
80
- use super::*;
81
-
82
- #[test]
83
- fn test_build_node_context() {
84
- let mut attrs = BTreeMap::new();
85
- attrs.insert("id".to_string(), "main".to_string());
86
- attrs.insert("class".to_string(), "container".to_string());
87
-
88
- let ctx = build_node_context(NodeType::Div, "div", &attrs, 2, 3, Some("body"), false);
89
-
90
- assert_eq!(ctx.node_type, NodeType::Div);
91
- assert_eq!(ctx.tag_name, "div");
92
- assert_eq!(ctx.depth, 2);
93
- assert_eq!(ctx.index_in_parent, 3);
94
- assert_eq!(ctx.parent_tag, Some("body".to_string()));
95
- assert!(!ctx.is_inline);
96
- assert_eq!(ctx.attributes.len(), 2);
97
- assert_eq!(ctx.attributes.get("id"), Some(&"main".to_string()));
98
- }
99
-
100
- #[test]
101
- fn test_build_node_context_no_parent() {
102
- let attrs = BTreeMap::new();
103
-
104
- let ctx = build_node_context(NodeType::Html, "html", &attrs, 0, 0, None, false);
105
-
106
- assert_eq!(ctx.node_type, NodeType::Html);
107
- assert_eq!(ctx.parent_tag, None);
108
- assert!(ctx.attributes.is_empty());
109
- }
110
- }