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.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +347 -0
- data/Steepfile +10 -2
- data/ext/html_to_markdown_rb/Cargo.toml +3 -2
- data/ext/html_to_markdown_rb/extconf.rb +5 -5
- data/ext/html_to_markdown_rb/native/Cargo.lock +962 -0
- data/ext/html_to_markdown_rb/native/Cargo.toml +6 -11
- data/ext/html_to_markdown_rb/native/extconf.rb +14 -0
- data/ext/html_to_markdown_rb/src/lib.rs +1715 -646
- data/lib/html_to_markdown/native.rb +913 -37
- data/lib/html_to_markdown/version.rb +3 -3
- data/lib/html_to_markdown.rb +9 -4
- data/lib/html_to_markdown_rb.so +0 -0
- data/sig/types.rbs +59 -292
- metadata +32 -179
- data/ext/html_to_markdown_rb/Makefile +0 -592
- data/lib/bin/html-to-markdown +0 -0
- data/vendor/Cargo.toml +0 -33
- data/vendor/html-to-markdown-rs/Cargo.toml +0 -54
- data/vendor/html-to-markdown-rs/README.md +0 -278
- data/vendor/html-to-markdown-rs/examples/basic.rs +0 -24
- data/vendor/html-to-markdown-rs/examples/table.rs +0 -25
- data/vendor/html-to-markdown-rs/examples/test_deser.rs +0 -12
- data/vendor/html-to-markdown-rs/examples/test_escape.rs +0 -58
- data/vendor/html-to-markdown-rs/examples/test_inline_formatting.rs +0 -113
- data/vendor/html-to-markdown-rs/examples/test_lists.rs +0 -39
- data/vendor/html-to-markdown-rs/examples/test_semantic_tags.rs +0 -89
- data/vendor/html-to-markdown-rs/examples/test_tables.rs +0 -100
- data/vendor/html-to-markdown-rs/examples/test_task_lists.rs +0 -61
- data/vendor/html-to-markdown-rs/examples/test_whitespace.rs +0 -34
- data/vendor/html-to-markdown-rs/src/convert_api.rs +0 -349
- data/vendor/html-to-markdown-rs/src/converter/block/blockquote.rs +0 -178
- data/vendor/html-to-markdown-rs/src/converter/block/container.rs +0 -114
- data/vendor/html-to-markdown-rs/src/converter/block/div.rs +0 -149
- data/vendor/html-to-markdown-rs/src/converter/block/heading.rs +0 -428
- data/vendor/html-to-markdown-rs/src/converter/block/horizontal_rule.rs +0 -103
- data/vendor/html-to-markdown-rs/src/converter/block/line_break.rs +0 -89
- data/vendor/html-to-markdown-rs/src/converter/block/mod.rs +0 -10
- data/vendor/html-to-markdown-rs/src/converter/block/paragraph.rs +0 -140
- data/vendor/html-to-markdown-rs/src/converter/block/preformatted.rs +0 -298
- data/vendor/html-to-markdown-rs/src/converter/block/table/builder.rs +0 -453
- data/vendor/html-to-markdown-rs/src/converter/block/table/caption.rs +0 -44
- data/vendor/html-to-markdown-rs/src/converter/block/table/cell.rs +0 -276
- data/vendor/html-to-markdown-rs/src/converter/block/table/cells.rs +0 -336
- data/vendor/html-to-markdown-rs/src/converter/block/table/layout.rs +0 -58
- data/vendor/html-to-markdown-rs/src/converter/block/table/mod.rs +0 -266
- data/vendor/html-to-markdown-rs/src/converter/block/table/scanner.rs +0 -146
- data/vendor/html-to-markdown-rs/src/converter/block/table/utils.rs +0 -34
- data/vendor/html-to-markdown-rs/src/converter/block/unknown.rs +0 -138
- data/vendor/html-to-markdown-rs/src/converter/context.rs +0 -208
- data/vendor/html-to-markdown-rs/src/converter/dom_context.rs +0 -337
- data/vendor/html-to-markdown-rs/src/converter/form/elements.rs +0 -770
- data/vendor/html-to-markdown-rs/src/converter/form/mod.rs +0 -82
- data/vendor/html-to-markdown-rs/src/converter/format/djot.rs +0 -64
- data/vendor/html-to-markdown-rs/src/converter/format/markdown.rs +0 -59
- data/vendor/html-to-markdown-rs/src/converter/format/mod.rs +0 -43
- data/vendor/html-to-markdown-rs/src/converter/handlers/blockquote.rs +0 -173
- data/vendor/html-to-markdown-rs/src/converter/handlers/code_block.rs +0 -434
- data/vendor/html-to-markdown-rs/src/converter/handlers/graphic.rs +0 -234
- data/vendor/html-to-markdown-rs/src/converter/handlers/image.rs +0 -282
- data/vendor/html-to-markdown-rs/src/converter/handlers/link.rs +0 -316
- data/vendor/html-to-markdown-rs/src/converter/handlers/mod.rs +0 -26
- data/vendor/html-to-markdown-rs/src/converter/inline/code.rs +0 -306
- data/vendor/html-to-markdown-rs/src/converter/inline/emphasis.rs +0 -345
- data/vendor/html-to-markdown-rs/src/converter/inline/link.rs +0 -428
- data/vendor/html-to-markdown-rs/src/converter/inline/mod.rs +0 -237
- data/vendor/html-to-markdown-rs/src/converter/inline/ruby.rs +0 -337
- data/vendor/html-to-markdown-rs/src/converter/inline/semantic/marks.rs +0 -566
- data/vendor/html-to-markdown-rs/src/converter/inline/semantic/mod.rs +0 -86
- data/vendor/html-to-markdown-rs/src/converter/inline/semantic/typography.rs +0 -558
- data/vendor/html-to-markdown-rs/src/converter/list/definition.rs +0 -232
- data/vendor/html-to-markdown-rs/src/converter/list/item.rs +0 -332
- data/vendor/html-to-markdown-rs/src/converter/list/mod.rs +0 -70
- data/vendor/html-to-markdown-rs/src/converter/list/ordered.rs +0 -201
- data/vendor/html-to-markdown-rs/src/converter/list/unordered.rs +0 -195
- data/vendor/html-to-markdown-rs/src/converter/list/utils.rs +0 -314
- data/vendor/html-to-markdown-rs/src/converter/main.rs +0 -710
- data/vendor/html-to-markdown-rs/src/converter/main_helpers.rs +0 -452
- data/vendor/html-to-markdown-rs/src/converter/media/embedded.rs +0 -393
- data/vendor/html-to-markdown-rs/src/converter/media/graphic.rs +0 -4
- data/vendor/html-to-markdown-rs/src/converter/media/image.rs +0 -183
- data/vendor/html-to-markdown-rs/src/converter/media/mod.rs +0 -87
- data/vendor/html-to-markdown-rs/src/converter/media/svg.rs +0 -280
- data/vendor/html-to-markdown-rs/src/converter/metadata.rs +0 -220
- data/vendor/html-to-markdown-rs/src/converter/mod.rs +0 -156
- data/vendor/html-to-markdown-rs/src/converter/plain_text.rs +0 -516
- data/vendor/html-to-markdown-rs/src/converter/preprocessing_helpers.rs +0 -201
- data/vendor/html-to-markdown-rs/src/converter/reference_collector.rs +0 -69
- data/vendor/html-to-markdown-rs/src/converter/semantic/attributes.rs +0 -269
- data/vendor/html-to-markdown-rs/src/converter/semantic/definition_list.rs +0 -266
- data/vendor/html-to-markdown-rs/src/converter/semantic/figure.rs +0 -391
- data/vendor/html-to-markdown-rs/src/converter/semantic/mod.rs +0 -112
- data/vendor/html-to-markdown-rs/src/converter/semantic/sectioning.rs +0 -85
- data/vendor/html-to-markdown-rs/src/converter/semantic/summary.rs +0 -324
- data/vendor/html-to-markdown-rs/src/converter/text/mod.rs +0 -8
- data/vendor/html-to-markdown-rs/src/converter/text/processing.rs +0 -56
- data/vendor/html-to-markdown-rs/src/converter/text_node.rs +0 -269
- data/vendor/html-to-markdown-rs/src/converter/utility/attributes.rs +0 -151
- data/vendor/html-to-markdown-rs/src/converter/utility/caching.rs +0 -74
- data/vendor/html-to-markdown-rs/src/converter/utility/content.rs +0 -271
- data/vendor/html-to-markdown-rs/src/converter/utility/mod.rs +0 -17
- data/vendor/html-to-markdown-rs/src/converter/utility/preprocessing.rs +0 -1002
- data/vendor/html-to-markdown-rs/src/converter/utility/serialization.rs +0 -126
- data/vendor/html-to-markdown-rs/src/converter/utility/siblings.rs +0 -97
- data/vendor/html-to-markdown-rs/src/converter/visitor_hooks.rs +0 -189
- data/vendor/html-to-markdown-rs/src/error.rs +0 -43
- data/vendor/html-to-markdown-rs/src/exports.rs +0 -24
- data/vendor/html-to-markdown-rs/src/inline_images.rs +0 -336
- data/vendor/html-to-markdown-rs/src/lib.rs +0 -139
- data/vendor/html-to-markdown-rs/src/metadata/collector.rs +0 -457
- data/vendor/html-to-markdown-rs/src/metadata/config.rs +0 -394
- data/vendor/html-to-markdown-rs/src/metadata/extraction.rs +0 -398
- data/vendor/html-to-markdown-rs/src/metadata/mod.rs +0 -288
- data/vendor/html-to-markdown-rs/src/metadata/types.rs +0 -477
- data/vendor/html-to-markdown-rs/src/options/conversion.rs +0 -559
- data/vendor/html-to-markdown-rs/src/options/inline_image.rs +0 -111
- data/vendor/html-to-markdown-rs/src/options/mod.rs +0 -20
- data/vendor/html-to-markdown-rs/src/options/preprocessing.rs +0 -201
- data/vendor/html-to-markdown-rs/src/options/validation.rs +0 -416
- data/vendor/html-to-markdown-rs/src/prelude.rs +0 -1
- data/vendor/html-to-markdown-rs/src/rcdom.rs +0 -487
- data/vendor/html-to-markdown-rs/src/text.rs +0 -358
- data/vendor/html-to-markdown-rs/src/types/document.rs +0 -191
- data/vendor/html-to-markdown-rs/src/types/mod.rs +0 -17
- data/vendor/html-to-markdown-rs/src/types/result.rs +0 -54
- data/vendor/html-to-markdown-rs/src/types/structure_builder.rs +0 -791
- data/vendor/html-to-markdown-rs/src/types/structure_collector.rs +0 -483
- data/vendor/html-to-markdown-rs/src/types/tables.rs +0 -52
- data/vendor/html-to-markdown-rs/src/types/warnings.rs +0 -33
- data/vendor/html-to-markdown-rs/src/validation.rs +0 -158
- data/vendor/html-to-markdown-rs/src/visitor/default_impl.rs +0 -63
- data/vendor/html-to-markdown-rs/src/visitor/mod.rs +0 -41
- data/vendor/html-to-markdown-rs/src/visitor/traits.rs +0 -370
- data/vendor/html-to-markdown-rs/src/visitor/types.rs +0 -319
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/callbacks/mod.rs +0 -1
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/content.rs +0 -126
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/mod.rs +0 -27
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/state.rs +0 -110
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/traversal.rs +0 -250
- data/vendor/html-to-markdown-rs/src/visitor_helpers.rs +0 -597
- data/vendor/html-to-markdown-rs/src/wrapper/sync.rs +0 -413
- data/vendor/html-to-markdown-rs/src/wrapper/utils.rs +0 -290
- data/vendor/html-to-markdown-rs/src/wrapper.rs +0 -9
- data/vendor/html-to-markdown-rs/tests/br_in_inline_test.rs +0 -87
- data/vendor/html-to-markdown-rs/tests/commonmark_compliance_test.rs +0 -297
- data/vendor/html-to-markdown-rs/tests/djot_output_test.rs +0 -153
- data/vendor/html-to-markdown-rs/tests/exclude_selectors_test.rs +0 -132
- data/vendor/html-to-markdown-rs/tests/integration_test.rs +0 -631
- data/vendor/html-to-markdown-rs/tests/issue_121_regressions.rs +0 -49
- data/vendor/html-to-markdown-rs/tests/issue_127_regressions.rs +0 -58
- data/vendor/html-to-markdown-rs/tests/issue_128_regressions.rs +0 -17
- data/vendor/html-to-markdown-rs/tests/issue_131_regressions.rs +0 -41
- data/vendor/html-to-markdown-rs/tests/issue_134_regressions.rs +0 -40
- data/vendor/html-to-markdown-rs/tests/issue_139_regressions.rs +0 -26
- data/vendor/html-to-markdown-rs/tests/issue_140_regressions.rs +0 -185
- data/vendor/html-to-markdown-rs/tests/issue_143_regressions.rs +0 -100
- data/vendor/html-to-markdown-rs/tests/issue_145_regressions.rs +0 -133
- data/vendor/html-to-markdown-rs/tests/issue_146_regressions.rs +0 -144
- data/vendor/html-to-markdown-rs/tests/issue_176_regressions.rs +0 -62
- data/vendor/html-to-markdown-rs/tests/issue_190_regressions.rs +0 -128
- data/vendor/html-to-markdown-rs/tests/issue_199_regressions.rs +0 -20
- data/vendor/html-to-markdown-rs/tests/issue_200_regressions.rs +0 -62
- data/vendor/html-to-markdown-rs/tests/issue_212_regressions.rs +0 -68
- data/vendor/html-to-markdown-rs/tests/issue_216_217_regressions.rs +0 -87
- data/vendor/html-to-markdown-rs/tests/issue_336_regressions.rs +0 -74
- data/vendor/html-to-markdown-rs/tests/issue_339_regressions.rs +0 -92
- data/vendor/html-to-markdown-rs/tests/issue_347_regressions.rs +0 -154
- data/vendor/html-to-markdown-rs/tests/issue_348_visitor_plain.rs +0 -93
- data/vendor/html-to-markdown-rs/tests/json_ld_script_extraction.rs +0 -44
- data/vendor/html-to-markdown-rs/tests/lists_test.rs +0 -199
- data/vendor/html-to-markdown-rs/tests/plain_output_test.rs +0 -273
- data/vendor/html-to-markdown-rs/tests/preprocessing_tests.rs +0 -61
- data/vendor/html-to-markdown-rs/tests/reference_links_test.rs +0 -169
- data/vendor/html-to-markdown-rs/tests/sectioning_elements_test.rs +0 -137
- data/vendor/html-to-markdown-rs/tests/skip_images_test.rs +0 -522
- data/vendor/html-to-markdown-rs/tests/tables_test.rs +0 -743
- data/vendor/html-to-markdown-rs/tests/test_custom_elements.rs +0 -41
- data/vendor/html-to-markdown-rs/tests/test_issue_187.rs +0 -204
- data/vendor/html-to-markdown-rs/tests/test_issue_218.rs +0 -68
- data/vendor/html-to-markdown-rs/tests/test_issue_277.rs +0 -77
- data/vendor/html-to-markdown-rs/tests/test_max_depth.rs +0 -82
- data/vendor/html-to-markdown-rs/tests/test_nested_simple.rs +0 -45
- data/vendor/html-to-markdown-rs/tests/test_script_style_stripping.rs +0 -396
- data/vendor/html-to-markdown-rs/tests/test_spa_bisect.rs +0 -34
- data/vendor/html-to-markdown-rs/tests/visitor_code_integration_test.rs +0 -121
- data/vendor/html-to-markdown-rs/tests/visitor_integration_test.rs +0 -1190
- data/vendor/html-to-markdown-rs/tests/xml_tables_test.rs +0 -372
|
@@ -1,743 +0,0 @@
|
|
|
1
|
-
#![allow(missing_docs)]
|
|
2
|
-
|
|
3
|
-
fn convert(
|
|
4
|
-
html: &str,
|
|
5
|
-
opts: Option<html_to_markdown_rs::ConversionOptions>,
|
|
6
|
-
) -> html_to_markdown_rs::error::Result<String> {
|
|
7
|
-
html_to_markdown_rs::convert(html, opts).map(|r| r.content.unwrap_or_default())
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
use html_to_markdown_rs::ConversionOptions;
|
|
11
|
-
|
|
12
|
-
#[test]
|
|
13
|
-
fn test_basic_table() {
|
|
14
|
-
let html = r"<table>
|
|
15
|
-
<tr><th>Header 1</th><th>Header 2</th></tr>
|
|
16
|
-
<tr><td>Cell 1</td><td>Cell 2</td></tr>
|
|
17
|
-
</table>";
|
|
18
|
-
|
|
19
|
-
let result = convert(html, None).unwrap();
|
|
20
|
-
assert!(result.contains("| Header 1"), "header row missing: {result}");
|
|
21
|
-
assert!(result.contains("| Header 2"), "header row missing: {result}");
|
|
22
|
-
assert!(result.contains("| Cell 1"), "cell row missing: {result}");
|
|
23
|
-
assert!(result.contains("| Cell 2"), "cell row missing: {result}");
|
|
24
|
-
// Separator must exist; dashes are padded to column width so just check presence.
|
|
25
|
-
assert!(result.contains("| ---"), "separator row missing: {result}");
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
#[test]
|
|
29
|
-
fn test_table_with_sections() {
|
|
30
|
-
let html = r"<table>
|
|
31
|
-
<thead>
|
|
32
|
-
<tr><th>Name</th><th>Age</th></tr>
|
|
33
|
-
</thead>
|
|
34
|
-
<tbody>
|
|
35
|
-
<tr><td>John</td><td>25</td></tr>
|
|
36
|
-
<tr><td>Jane</td><td>30</td></tr>
|
|
37
|
-
</tbody>
|
|
38
|
-
<tfoot>
|
|
39
|
-
<tr><td>Total</td><td>2</td></tr>
|
|
40
|
-
</tfoot>
|
|
41
|
-
</table>";
|
|
42
|
-
|
|
43
|
-
let result = convert(html, None).unwrap();
|
|
44
|
-
assert!(result.contains("| Name"), "Name column missing: {result}");
|
|
45
|
-
assert!(result.contains("| Age"), "Age column missing: {result}");
|
|
46
|
-
assert!(result.contains("| John"), "John row missing: {result}");
|
|
47
|
-
assert!(result.contains("| 25"), "25 cell missing: {result}");
|
|
48
|
-
assert!(result.contains("| Jane"), "Jane row missing: {result}");
|
|
49
|
-
assert!(result.contains("| 30"), "30 cell missing: {result}");
|
|
50
|
-
assert!(result.contains("| Total"), "Total row missing: {result}");
|
|
51
|
-
assert!(result.contains("| 2"), "2 cell missing: {result}");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
#[test]
|
|
55
|
-
fn test_table_caption() {
|
|
56
|
-
let html = r"<table><caption>Table Caption</caption><tr><td>Data</td></tr></table>";
|
|
57
|
-
let result = convert(html, None).unwrap();
|
|
58
|
-
assert!(result.contains("*Table Caption*"));
|
|
59
|
-
assert!(result.contains("| Data |"));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
#[test]
|
|
63
|
-
fn test_table_rowspan() {
|
|
64
|
-
// Test table rowspan with multi-line content in cells
|
|
65
|
-
// With br_in_tables enabled, divs are converted to br separators
|
|
66
|
-
let html = r#"<table>
|
|
67
|
-
<tr><th>Header 1</th><th>Header 2</th></tr>
|
|
68
|
-
<tr><td rowspan="2">Spanning cell</td><td>
|
|
69
|
-
<div>First row content</div>
|
|
70
|
-
<div>Second line</div>
|
|
71
|
-
</td></tr>
|
|
72
|
-
<tr><td>
|
|
73
|
-
<div>Next row</div>
|
|
74
|
-
<div>More content</div>
|
|
75
|
-
</td></tr>
|
|
76
|
-
</table>"#;
|
|
77
|
-
|
|
78
|
-
let options = ConversionOptions {
|
|
79
|
-
br_in_tables: true,
|
|
80
|
-
..Default::default()
|
|
81
|
-
};
|
|
82
|
-
let result = convert(html, Some(options)).unwrap();
|
|
83
|
-
|
|
84
|
-
// Content should be present; exact br format may vary
|
|
85
|
-
assert!(
|
|
86
|
-
result.contains("Spanning cell")
|
|
87
|
-
&& result.contains("First row content")
|
|
88
|
-
&& result.contains("Second line")
|
|
89
|
-
&& result.contains("Next row")
|
|
90
|
-
&& result.contains("More content"),
|
|
91
|
-
"All rowspan content should be present: {result}"
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
#[test]
|
|
96
|
-
fn test_table_colspan() {
|
|
97
|
-
let html = r#"<table>
|
|
98
|
-
<tr><th colspan="2">Wide Header</th></tr>
|
|
99
|
-
<tr><td>Cell 1</td><td>Cell 2</td></tr>
|
|
100
|
-
</table>"#;
|
|
101
|
-
|
|
102
|
-
let result = convert(html, None).unwrap();
|
|
103
|
-
assert!(result.contains("| Wide Header"), "Wide Header missing: {result}");
|
|
104
|
-
assert!(result.contains("| Cell 1"), "Cell 1 missing: {result}");
|
|
105
|
-
assert!(result.contains("| Cell 2"), "Cell 2 missing: {result}");
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
#[test]
|
|
109
|
-
fn test_table_cell_multiline_content() {
|
|
110
|
-
// Test table cells with multiple divs (multiline content)
|
|
111
|
-
// With br_in_tables enabled, divs should be separated by breaks
|
|
112
|
-
let html = r"<table>
|
|
113
|
-
<tr><th>Header 1</th><th>Header 2</th></tr>
|
|
114
|
-
<tr><td>Cell 3</td><td>
|
|
115
|
-
<div>Cell 4-1</div>
|
|
116
|
-
<div>Cell 4-2</div>
|
|
117
|
-
</td></tr>
|
|
118
|
-
</table>";
|
|
119
|
-
|
|
120
|
-
let options = ConversionOptions {
|
|
121
|
-
br_in_tables: true,
|
|
122
|
-
..Default::default()
|
|
123
|
-
};
|
|
124
|
-
let result = convert(html, Some(options)).unwrap();
|
|
125
|
-
|
|
126
|
-
// All content should be present
|
|
127
|
-
assert!(
|
|
128
|
-
result.contains("Header 1")
|
|
129
|
-
&& result.contains("Header 2")
|
|
130
|
-
&& result.contains("Cell 3")
|
|
131
|
-
&& result.contains("Cell 4-1")
|
|
132
|
-
&& result.contains("Cell 4-2"),
|
|
133
|
-
"All cell content should be present: {result}"
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
#[test]
|
|
138
|
-
fn test_table_first_row_in_tbody_without_header() {
|
|
139
|
-
let html = r"<table>
|
|
140
|
-
<tbody>
|
|
141
|
-
<tr><td>Cell 1</td><td>Cell 2</td></tr>
|
|
142
|
-
</tbody>
|
|
143
|
-
</table>";
|
|
144
|
-
|
|
145
|
-
let result = convert(html, None).unwrap();
|
|
146
|
-
// Column width is 6 chars ("Cell 1"/"Cell 2"), so separator has 6 dashes.
|
|
147
|
-
assert!(result.contains("| Cell 1"), "Cell 1 missing: {result}");
|
|
148
|
-
assert!(result.contains("| Cell 2"), "Cell 2 missing: {result}");
|
|
149
|
-
assert!(result.contains("| ---"), "separator missing: {result}");
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
#[test]
|
|
153
|
-
fn test_tbody_only() {
|
|
154
|
-
let html = "<table><tbody><tr><td>Data</td></tr></tbody></table>";
|
|
155
|
-
let result = convert(html, None).unwrap();
|
|
156
|
-
assert!(result.contains("| Data |"));
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
#[test]
|
|
160
|
-
fn test_tfoot_basic() {
|
|
161
|
-
let html = "<table><tfoot><tr><td>Footer</td></tr></tfoot><tbody><tr><td>Data</td></tr></tbody></table>";
|
|
162
|
-
let result = convert(html, None).unwrap();
|
|
163
|
-
assert!(result.contains("| Footer"), "Footer cell missing: {result}");
|
|
164
|
-
assert!(result.contains("| Data"), "Data cell missing: {result}");
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
#[test]
|
|
168
|
-
fn test_caption_with_formatting() {
|
|
169
|
-
let html = r"<table><caption>Sales <strong>Report</strong> 2023</caption><tr><td>Data</td></tr></table>";
|
|
170
|
-
let result = convert(html, None).unwrap();
|
|
171
|
-
assert!(result.contains("*Sales **Report** 2023*"));
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
#[test]
|
|
175
|
-
fn test_table_with_links() {
|
|
176
|
-
let html = r#"<table>
|
|
177
|
-
<tr><th>Name</th><th>Website</th></tr>
|
|
178
|
-
<tr><td>Example</td><td><a href="https://example.com">Link</a></td></tr>
|
|
179
|
-
</table>"#;
|
|
180
|
-
|
|
181
|
-
let result = convert(html, None).unwrap();
|
|
182
|
-
assert!(result.contains("| Name"), "Name column missing: {result}");
|
|
183
|
-
assert!(result.contains("| Website"), "Website column missing: {result}");
|
|
184
|
-
assert!(result.contains("[Link](https://example.com)"), "link missing: {result}");
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
#[test]
|
|
188
|
-
fn test_table_with_code() {
|
|
189
|
-
let html = r"<table>
|
|
190
|
-
<tr><th>Command</th></tr>
|
|
191
|
-
<tr><td><code>ls -la</code></td></tr>
|
|
192
|
-
</table>";
|
|
193
|
-
|
|
194
|
-
let result = convert(html, None).unwrap();
|
|
195
|
-
assert!(result.contains("| Command"), "Command column missing: {result}");
|
|
196
|
-
assert!(result.contains("`ls -la`"), "code cell missing: {result}");
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
#[test]
|
|
200
|
-
fn test_table_empty_cells() {
|
|
201
|
-
let html = r"<table>
|
|
202
|
-
<tr><td>Data</td><td></td></tr>
|
|
203
|
-
</table>";
|
|
204
|
-
|
|
205
|
-
let result = convert(html, None).unwrap();
|
|
206
|
-
assert!(result.contains("| Data | |"));
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
#[test]
|
|
210
|
-
fn test_table_single_column() {
|
|
211
|
-
let html = r"<table>
|
|
212
|
-
<tr><th>Header</th></tr>
|
|
213
|
-
<tr><td>Cell 1</td></tr>
|
|
214
|
-
<tr><td>Cell 2</td></tr>
|
|
215
|
-
</table>";
|
|
216
|
-
|
|
217
|
-
let result = convert(html, None).unwrap();
|
|
218
|
-
assert!(result.contains("| Header |"), "Header row missing: {result}");
|
|
219
|
-
// Separator dashes are padded to column width; just verify separator exists.
|
|
220
|
-
assert!(result.contains("| ---"), "separator missing: {result}");
|
|
221
|
-
assert!(result.contains("| Cell 1 |"), "Cell 1 row missing: {result}");
|
|
222
|
-
assert!(result.contains("| Cell 2 |"), "Cell 2 row missing: {result}");
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
#[test]
|
|
226
|
-
fn test_blogger_table_with_image() {
|
|
227
|
-
// Regression test for Issue #175: Image tags inside Blogger table wrappers not being processed
|
|
228
|
-
let html = r#"
|
|
229
|
-
<table class="tr-caption-container">
|
|
230
|
-
<a href="https://example.com/full-image.jpg">
|
|
231
|
-
<img border="0" height="480"
|
|
232
|
-
src="https://blogger.googleusercontent.com/img/test/IMG_0427.JPG"
|
|
233
|
-
width="640" alt="Test Image" />
|
|
234
|
-
</a>
|
|
235
|
-
</table>
|
|
236
|
-
"#;
|
|
237
|
-
|
|
238
|
-
let result = convert(html, None).unwrap();
|
|
239
|
-
|
|
240
|
-
// The image should be converted to markdown (wrapped in a link)
|
|
241
|
-
assert!(
|
|
242
|
-
result.contains("!["),
|
|
243
|
-
"Result should contain markdown image syntax: {result}"
|
|
244
|
-
);
|
|
245
|
-
assert!(
|
|
246
|
-
result.contains("blogger.googleusercontent.com"),
|
|
247
|
-
"Result should contain image URL: {result}"
|
|
248
|
-
);
|
|
249
|
-
assert!(
|
|
250
|
-
result.contains("example.com/full-image.jpg"),
|
|
251
|
-
"Result should contain link URL: {result}"
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
#[test]
|
|
256
|
-
fn test_table_with_image_no_rows() {
|
|
257
|
-
// Test that images in tables without proper rows are still processed
|
|
258
|
-
let html = r#"<table><img src="https://example.com/image.jpg" alt="test image"></table>"#;
|
|
259
|
-
let result = convert(html, None).unwrap();
|
|
260
|
-
|
|
261
|
-
assert!(
|
|
262
|
-
result.contains(""),
|
|
263
|
-
"Image should be converted to markdown: {result}"
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
#[test]
|
|
268
|
-
fn test_table_with_link_and_image_no_rows() {
|
|
269
|
-
// Test that link-wrapped images in tables without proper rows are processed
|
|
270
|
-
let html =
|
|
271
|
-
r#"<table><a href="https://example.com"><img src="https://example.com/image.jpg" alt="test"></a></table>"#;
|
|
272
|
-
let result = convert(html, None).unwrap();
|
|
273
|
-
|
|
274
|
-
assert!(
|
|
275
|
-
result.contains("[](https://example.com)"),
|
|
276
|
-
"Link-wrapped image should be converted to markdown: {result}"
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// ==============================================================================
|
|
281
|
-
// Comprehensive tests for <br> tags in table cells
|
|
282
|
-
// ==============================================================================
|
|
283
|
-
// These tests cover the issue where literal <br> HTML tags were being output
|
|
284
|
-
// in table cells instead of being converted to proper Markdown line breaks.
|
|
285
|
-
//
|
|
286
|
-
// ISSUE: When br_in_tables option is enabled, <br> tags in table cells should
|
|
287
|
-
// be converted to proper Markdown line breaks (spaces-style: " \n" or
|
|
288
|
-
// backslash-style: "\\\n") rather than being output as literal "<br>" tags.
|
|
289
|
-
|
|
290
|
-
#[test]
|
|
291
|
-
fn test_br_in_table_cell_basic_spaces_style() {
|
|
292
|
-
let html = r"<table>
|
|
293
|
-
<tr><th>Header</th></tr>
|
|
294
|
-
<tr><td>Line 1<br>Line 2</td></tr>
|
|
295
|
-
</table>";
|
|
296
|
-
|
|
297
|
-
let options = ConversionOptions {
|
|
298
|
-
br_in_tables: true,
|
|
299
|
-
..Default::default()
|
|
300
|
-
};
|
|
301
|
-
let result = convert(html, Some(options)).unwrap();
|
|
302
|
-
|
|
303
|
-
// Should convert to two spaces + newline style (default)
|
|
304
|
-
// EXPECTED: "Line 1 \nLine 2"
|
|
305
|
-
// ACTUAL BUG: "Line 1 <br>Line 2" (literal <br> tag)
|
|
306
|
-
assert!(
|
|
307
|
-
result.contains("Line 1 \nLine 2") || result.contains("Line 1 <br>Line 2"),
|
|
308
|
-
"Expected spaces-style line break in table cell: {result}"
|
|
309
|
-
);
|
|
310
|
-
// For now, we document the bug exists (contains <br>)
|
|
311
|
-
// This assertion will pass until the bug is fixed
|
|
312
|
-
let has_literal_br = result.contains("<br>");
|
|
313
|
-
let properly_converted = result.contains("Line 1 \nLine 2");
|
|
314
|
-
assert!(
|
|
315
|
-
has_literal_br || properly_converted,
|
|
316
|
-
"Should either have literal <br> (bug) or proper break: {result}"
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
#[test]
|
|
321
|
-
fn test_br_in_table_cell_backslash_style() {
|
|
322
|
-
let html = r"<table>
|
|
323
|
-
<tr><th>Header</th></tr>
|
|
324
|
-
<tr><td>Line 1<br>Line 2</td></tr>
|
|
325
|
-
</table>";
|
|
326
|
-
|
|
327
|
-
let options = ConversionOptions {
|
|
328
|
-
br_in_tables: true,
|
|
329
|
-
newline_style: html_to_markdown_rs::NewlineStyle::Backslash,
|
|
330
|
-
..Default::default()
|
|
331
|
-
};
|
|
332
|
-
let result = convert(html, Some(options)).unwrap();
|
|
333
|
-
|
|
334
|
-
// Should convert to backslash + newline style
|
|
335
|
-
// EXPECTED: "Line 1\\\nLine 2"
|
|
336
|
-
// ACTUAL BUG: "Line 1\<br>Line 2" (literal <br> tag with backslash escape)
|
|
337
|
-
assert!(
|
|
338
|
-
result.contains("Line 1\\\nLine 2") || result.contains("Line 1\\<br>Line 2"),
|
|
339
|
-
"Expected backslash-style line break in table cell: {result}"
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
#[test]
|
|
344
|
-
fn test_br_in_table_cell_case_variations() {
|
|
345
|
-
// Tests that various case variations of <br> tags are handled consistently
|
|
346
|
-
// EXPECTED: All variations should convert to proper line breaks
|
|
347
|
-
// ACTUAL BUG: Only lowercase <br> tags are recognized; uppercase/mixed case are ignored
|
|
348
|
-
let test_cases = vec![
|
|
349
|
-
("<br>", "lowercase br", true),
|
|
350
|
-
("<BR>", "uppercase BR", false), // Not recognized - stripped completely
|
|
351
|
-
("<br/>", "self-closing lowercase", true),
|
|
352
|
-
("<BR/>", "self-closing uppercase", false), // Not recognized
|
|
353
|
-
("<br />", "self-closing with space", true),
|
|
354
|
-
("<BR />", "self-closing uppercase with space", false), // Not recognized
|
|
355
|
-
("<Br>", "mixed case Br", false), // Not recognized
|
|
356
|
-
("<bR />", "mixed case bR with space", false), // Not recognized
|
|
357
|
-
];
|
|
358
|
-
|
|
359
|
-
for (html_br, case_name, should_work) in test_cases {
|
|
360
|
-
let html = format!(
|
|
361
|
-
r"<table>
|
|
362
|
-
<tr><th>Header</th></tr>
|
|
363
|
-
<tr><td>Line 1{html_br}Line 2</td></tr>
|
|
364
|
-
</table>"
|
|
365
|
-
);
|
|
366
|
-
|
|
367
|
-
let options = ConversionOptions {
|
|
368
|
-
br_in_tables: true,
|
|
369
|
-
..Default::default()
|
|
370
|
-
};
|
|
371
|
-
let result = convert(&html, Some(options)).unwrap();
|
|
372
|
-
|
|
373
|
-
if should_work {
|
|
374
|
-
// Lowercase br tags should produce both lines
|
|
375
|
-
assert!(
|
|
376
|
-
result.contains("Line 1") && result.contains("Line 2"),
|
|
377
|
-
"Failed for {case_name}: Both lines should be in output: {result}"
|
|
378
|
-
);
|
|
379
|
-
} else {
|
|
380
|
-
// Uppercase/mixed case tags are not recognized, but content should still exist
|
|
381
|
-
// (they're treated as unrecognized tags and stripped)
|
|
382
|
-
assert!(
|
|
383
|
-
result.contains("Line 1"),
|
|
384
|
-
"Failed for {case_name}: At least first line should be in output: {result}"
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
#[test]
|
|
391
|
-
fn test_br_in_table_cell_with_consecutive_paragraphs() {
|
|
392
|
-
// Consecutive paragraphs in table cells generate <br> separators.
|
|
393
|
-
// EXPECTED: These should be converted to proper line breaks
|
|
394
|
-
// ACTUAL BUG: Output as literal <br> tags in the markdown table
|
|
395
|
-
let html = r"<table>
|
|
396
|
-
<tr><th>Header</th></tr>
|
|
397
|
-
<tr><td>
|
|
398
|
-
<p>First paragraph</p>
|
|
399
|
-
<p>Second paragraph</p>
|
|
400
|
-
</td></tr>
|
|
401
|
-
</table>";
|
|
402
|
-
|
|
403
|
-
let options = ConversionOptions {
|
|
404
|
-
br_in_tables: true,
|
|
405
|
-
..Default::default()
|
|
406
|
-
};
|
|
407
|
-
let result = convert(html, Some(options)).unwrap();
|
|
408
|
-
|
|
409
|
-
// The content should be on separate lines in the table cell
|
|
410
|
-
assert!(
|
|
411
|
-
result.contains("First paragraph"),
|
|
412
|
-
"Should contain first paragraph: {result}"
|
|
413
|
-
);
|
|
414
|
-
assert!(
|
|
415
|
-
result.contains("Second paragraph"),
|
|
416
|
-
"Should contain second paragraph: {result}"
|
|
417
|
-
);
|
|
418
|
-
// For now, we just verify both paragraphs are present
|
|
419
|
-
// (exact format depends on whether bug is fixed)
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
#[test]
|
|
423
|
-
fn test_br_in_table_cell_with_consecutive_divs() {
|
|
424
|
-
// Consecutive divs in table cells also generate <br> separators
|
|
425
|
-
// EXPECTED: Should convert to proper line breaks
|
|
426
|
-
// ACTUAL BUG: Output as literal <br> tags in the markdown table
|
|
427
|
-
let html = r"<table>
|
|
428
|
-
<tr><th>Header</th></tr>
|
|
429
|
-
<tr><td>
|
|
430
|
-
<div>First line</div>
|
|
431
|
-
<div>Second line</div>
|
|
432
|
-
<div>Third line</div>
|
|
433
|
-
</td></tr>
|
|
434
|
-
</table>";
|
|
435
|
-
|
|
436
|
-
let options = ConversionOptions {
|
|
437
|
-
br_in_tables: true,
|
|
438
|
-
..Default::default()
|
|
439
|
-
};
|
|
440
|
-
let result = convert(html, Some(options)).unwrap();
|
|
441
|
-
|
|
442
|
-
// All three lines should be present in the output
|
|
443
|
-
assert!(result.contains("First line"), "Should contain first line: {result}");
|
|
444
|
-
assert!(result.contains("Second line"), "Should contain second line: {result}");
|
|
445
|
-
assert!(result.contains("Third line"), "Should contain third line: {result}");
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
#[test]
|
|
449
|
-
fn test_br_in_table_cell_with_formatting() {
|
|
450
|
-
// Test <br> tags between formatted text in table cells
|
|
451
|
-
// EXPECTED: "**Text1** \n**Text2**"
|
|
452
|
-
// ACTUAL BUG: "**Text1** <br>**Text2**"
|
|
453
|
-
let html = r"<table>
|
|
454
|
-
<tr><th>Header</th></tr>
|
|
455
|
-
<tr><td><b>Text1</b><br><b>Text2</b></td></tr>
|
|
456
|
-
</table>";
|
|
457
|
-
|
|
458
|
-
let options = ConversionOptions {
|
|
459
|
-
br_in_tables: true,
|
|
460
|
-
..Default::default()
|
|
461
|
-
};
|
|
462
|
-
let result = convert(html, Some(options)).unwrap();
|
|
463
|
-
|
|
464
|
-
// Both formatted texts should be present
|
|
465
|
-
assert!(result.contains("**Text1**"), "Expected first formatted text: {result}");
|
|
466
|
-
assert!(result.contains("**Text2**"), "Expected second formatted text: {result}");
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
#[test]
|
|
470
|
-
fn test_br_in_table_cell_multiple_breaks() {
|
|
471
|
-
// Test multiple <br> tags in the same table cell
|
|
472
|
-
// EXPECTED: All breaks converted to proper Markdown line breaks
|
|
473
|
-
// ACTUAL BUG: All breaks output as literal <br> tags
|
|
474
|
-
let html = r"<table>
|
|
475
|
-
<tr><th>Header</th></tr>
|
|
476
|
-
<tr><td>Line 1<br>Line 2<br>Line 3<br>Line 4</td></tr>
|
|
477
|
-
</table>";
|
|
478
|
-
|
|
479
|
-
let options = ConversionOptions {
|
|
480
|
-
br_in_tables: true,
|
|
481
|
-
..Default::default()
|
|
482
|
-
};
|
|
483
|
-
let result = convert(html, Some(options)).unwrap();
|
|
484
|
-
|
|
485
|
-
// All four lines should be present
|
|
486
|
-
assert!(
|
|
487
|
-
result.contains("Line 1")
|
|
488
|
-
&& result.contains("Line 2")
|
|
489
|
-
&& result.contains("Line 3")
|
|
490
|
-
&& result.contains("Line 4"),
|
|
491
|
-
"All lines should be in output: {result}"
|
|
492
|
-
);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
#[test]
|
|
496
|
-
fn test_br_in_table_cell_with_surrounding_text() {
|
|
497
|
-
// Test <br> inside formatted text with surrounding text
|
|
498
|
-
// EXPECTED: "Before **middle** \n**line** after"
|
|
499
|
-
// ACTUAL BUG: "Before **middle <br>line** after"
|
|
500
|
-
let html = r"<table>
|
|
501
|
-
<tr><th>Header</th></tr>
|
|
502
|
-
<tr><td>Before <b>middle<br>line</b> after</td></tr>
|
|
503
|
-
</table>";
|
|
504
|
-
|
|
505
|
-
let options = ConversionOptions {
|
|
506
|
-
br_in_tables: true,
|
|
507
|
-
..Default::default()
|
|
508
|
-
};
|
|
509
|
-
let result = convert(html, Some(options)).unwrap();
|
|
510
|
-
|
|
511
|
-
// All parts should be present
|
|
512
|
-
assert!(
|
|
513
|
-
result.contains("Before")
|
|
514
|
-
&& result.contains("**middle")
|
|
515
|
-
&& result.contains("line**")
|
|
516
|
-
&& result.contains("after"),
|
|
517
|
-
"Should contain all text parts: {result}"
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
#[test]
|
|
522
|
-
fn test_multiple_cells_with_br_tags() {
|
|
523
|
-
// Test <br> tags in multiple cells across a row
|
|
524
|
-
// EXPECTED: All cells should have breaks converted to proper Markdown
|
|
525
|
-
// ACTUAL BUG: All cells output with literal <br> tags
|
|
526
|
-
let html = r"<table>
|
|
527
|
-
<tr><th>Col1</th><th>Col2</th><th>Col3</th></tr>
|
|
528
|
-
<tr><td>A1<br>A2</td><td>B1<br>B2</td><td>C1<br>C2</td></tr>
|
|
529
|
-
</table>";
|
|
530
|
-
|
|
531
|
-
let options = ConversionOptions {
|
|
532
|
-
br_in_tables: true,
|
|
533
|
-
..Default::default()
|
|
534
|
-
};
|
|
535
|
-
let result = convert(html, Some(options)).unwrap();
|
|
536
|
-
|
|
537
|
-
// All content should be present
|
|
538
|
-
assert!(
|
|
539
|
-
result.contains("A1")
|
|
540
|
-
&& result.contains("A2")
|
|
541
|
-
&& result.contains("B1")
|
|
542
|
-
&& result.contains("B2")
|
|
543
|
-
&& result.contains("C1")
|
|
544
|
-
&& result.contains("C2"),
|
|
545
|
-
"All cell contents should be in output: {result}"
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
#[test]
|
|
550
|
-
fn test_br_in_header_and_data_cells() {
|
|
551
|
-
// Test <br> tags in both header and data cells
|
|
552
|
-
// EXPECTED: All cells should have breaks converted to proper Markdown
|
|
553
|
-
// ACTUAL BUG: All cells output with literal <br> tags
|
|
554
|
-
let html = r"<table>
|
|
555
|
-
<tr><th>Header1<br>Line2</th><th>Header3</th></tr>
|
|
556
|
-
<tr><td>Data1<br>Line2</td><td>Data3</td></tr>
|
|
557
|
-
</table>";
|
|
558
|
-
|
|
559
|
-
let options = ConversionOptions {
|
|
560
|
-
br_in_tables: true,
|
|
561
|
-
..Default::default()
|
|
562
|
-
};
|
|
563
|
-
let result = convert(html, Some(options)).unwrap();
|
|
564
|
-
|
|
565
|
-
// All header and data content should be present
|
|
566
|
-
assert!(
|
|
567
|
-
result.contains("Header1")
|
|
568
|
-
&& result.contains("Line2")
|
|
569
|
-
&& result.contains("Header3")
|
|
570
|
-
&& result.contains("Data1")
|
|
571
|
-
&& result.contains("Data3"),
|
|
572
|
-
"All cell contents should be in output: {result}"
|
|
573
|
-
);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
#[test]
|
|
577
|
-
fn test_br_in_nested_formatting_in_table_cell() {
|
|
578
|
-
// Test <br> tags inside nested formatting (bold + italic)
|
|
579
|
-
// EXPECTED: "***Bold italic*** \n***next line***"
|
|
580
|
-
// ACTUAL BUG: "***Bold italic <br>next line***"
|
|
581
|
-
let html = r"<table>
|
|
582
|
-
<tr><th>Header</th></tr>
|
|
583
|
-
<tr><td><strong><em>Bold italic<br>next line</em></strong></td></tr>
|
|
584
|
-
</table>";
|
|
585
|
-
|
|
586
|
-
let options = ConversionOptions {
|
|
587
|
-
br_in_tables: true,
|
|
588
|
-
..Default::default()
|
|
589
|
-
};
|
|
590
|
-
let result = convert(html, Some(options)).unwrap();
|
|
591
|
-
|
|
592
|
-
// Both parts of the nested formatted text should be present
|
|
593
|
-
assert!(
|
|
594
|
-
result.contains("Bold italic") && result.contains("next line"),
|
|
595
|
-
"Nested formatting content should be preserved: {result}"
|
|
596
|
-
);
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
#[test]
|
|
600
|
-
fn test_br_in_table_cell_with_link() {
|
|
601
|
-
// Test <br> tags between links in table cells
|
|
602
|
-
// EXPECTED: "[Link1](url) \n[Link2](url)"
|
|
603
|
-
// ACTUAL BUG: "[Link1](url) <br>[Link2](url)"
|
|
604
|
-
let html = r#"<table>
|
|
605
|
-
<tr><th>Header</th></tr>
|
|
606
|
-
<tr><td><a href="https://example.com">Link1</a><br><a href="https://example.org">Link2</a></td></tr>
|
|
607
|
-
</table>"#;
|
|
608
|
-
|
|
609
|
-
let options = ConversionOptions {
|
|
610
|
-
br_in_tables: true,
|
|
611
|
-
..Default::default()
|
|
612
|
-
};
|
|
613
|
-
let result = convert(html, Some(options)).unwrap();
|
|
614
|
-
|
|
615
|
-
// Both links should be present with their URLs
|
|
616
|
-
assert!(
|
|
617
|
-
result.contains("Link1")
|
|
618
|
-
&& result.contains("example.com")
|
|
619
|
-
&& result.contains("Link2")
|
|
620
|
-
&& result.contains("example.org"),
|
|
621
|
-
"Links should be preserved: {result}"
|
|
622
|
-
);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
#[test]
|
|
626
|
-
fn test_br_with_no_br_in_tables_option() {
|
|
627
|
-
// When br_in_tables is false or not set, verify default behavior
|
|
628
|
-
let html = r"<table>
|
|
629
|
-
<tr><th>Header</th></tr>
|
|
630
|
-
<tr><td>Line 1<br>Line 2</td></tr>
|
|
631
|
-
</table>";
|
|
632
|
-
|
|
633
|
-
let options = ConversionOptions {
|
|
634
|
-
br_in_tables: false,
|
|
635
|
-
..Default::default()
|
|
636
|
-
};
|
|
637
|
-
let result = convert(html, Some(options)).unwrap();
|
|
638
|
-
|
|
639
|
-
// With br_in_tables disabled, the content should still be reasonable
|
|
640
|
-
// (exact output depends on implementation)
|
|
641
|
-
assert!(
|
|
642
|
-
result.contains("Line 1") && result.contains("Line 2"),
|
|
643
|
-
"Both lines should appear in output: {result}"
|
|
644
|
-
);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
#[test]
|
|
648
|
-
fn test_br_in_table_with_code_in_cell() {
|
|
649
|
-
// Test <br> tags between code elements in table cells
|
|
650
|
-
// EXPECTED: "`command1` \n`command2`"
|
|
651
|
-
// ACTUAL BUG: "`command1` <br>`command2`"
|
|
652
|
-
let html = r"<table>
|
|
653
|
-
<tr><th>Header</th></tr>
|
|
654
|
-
<tr><td><code>command1</code><br><code>command2</code></td></tr>
|
|
655
|
-
</table>";
|
|
656
|
-
|
|
657
|
-
let options = ConversionOptions {
|
|
658
|
-
br_in_tables: true,
|
|
659
|
-
..Default::default()
|
|
660
|
-
};
|
|
661
|
-
let result = convert(html, Some(options)).unwrap();
|
|
662
|
-
|
|
663
|
-
// Both code blocks should be present
|
|
664
|
-
assert!(
|
|
665
|
-
result.contains("command1") && result.contains("command2"),
|
|
666
|
-
"Code blocks should be preserved: {result}"
|
|
667
|
-
);
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
#[test]
|
|
671
|
-
fn test_br_in_table_empty_cell_with_break() {
|
|
672
|
-
// Test <br> tag as sole content of table cell
|
|
673
|
-
// EXPECTED: Cell should be empty or have proper line break representation
|
|
674
|
-
// ACTUAL BUG: May output literal <br> tag
|
|
675
|
-
let html = r"<table>
|
|
676
|
-
<tr><th>Header</th></tr>
|
|
677
|
-
<tr><td><br></td></tr>
|
|
678
|
-
</table>";
|
|
679
|
-
|
|
680
|
-
let options = ConversionOptions {
|
|
681
|
-
br_in_tables: true,
|
|
682
|
-
..Default::default()
|
|
683
|
-
};
|
|
684
|
-
let result = convert(html, Some(options)).unwrap();
|
|
685
|
-
|
|
686
|
-
// Basic sanity check - should still be valid markdown table
|
|
687
|
-
assert!(
|
|
688
|
-
result.contains('|'),
|
|
689
|
-
"Should still generate valid table structure: {result}"
|
|
690
|
-
);
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
#[test]
|
|
694
|
-
fn test_br_in_table_with_mixed_content() {
|
|
695
|
-
// Test complex cell with multiple <br> tags and mixed formatting
|
|
696
|
-
// EXPECTED: All content separated by proper Markdown line breaks
|
|
697
|
-
// ACTUAL BUG: Output contains literal <br> tags mixed with formatted text
|
|
698
|
-
let html = r"<table>
|
|
699
|
-
<tr><th>Status</th><th>Description</th></tr>
|
|
700
|
-
<tr>
|
|
701
|
-
<td>Active</td>
|
|
702
|
-
<td>First step<br><strong>Bold text</strong><br>Final step</td>
|
|
703
|
-
</tr>
|
|
704
|
-
</table>";
|
|
705
|
-
|
|
706
|
-
let options = ConversionOptions {
|
|
707
|
-
br_in_tables: true,
|
|
708
|
-
..Default::default()
|
|
709
|
-
};
|
|
710
|
-
let result = convert(html, Some(options)).unwrap();
|
|
711
|
-
|
|
712
|
-
// All content should be present
|
|
713
|
-
assert!(
|
|
714
|
-
result.contains("First step")
|
|
715
|
-
&& result.contains("**Bold text**")
|
|
716
|
-
&& result.contains("Final step")
|
|
717
|
-
&& result.contains("Active"),
|
|
718
|
-
"Should contain all content: {result}"
|
|
719
|
-
);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
#[test]
|
|
723
|
-
fn test_table_colspan_no_header_issue_233() {
|
|
724
|
-
let html = r#"<table>
|
|
725
|
-
<tr>
|
|
726
|
-
<td colspan="2">Cell spanning 2 columns</td>
|
|
727
|
-
</tr>
|
|
728
|
-
<tr>
|
|
729
|
-
<td>Cell 1</td>
|
|
730
|
-
<td>Cell 2</td>
|
|
731
|
-
</tr>
|
|
732
|
-
</table>"#;
|
|
733
|
-
let result = html_to_markdown_rs::convert(html, None)
|
|
734
|
-
.unwrap()
|
|
735
|
-
.content
|
|
736
|
-
.unwrap_or_default();
|
|
737
|
-
assert!(
|
|
738
|
-
result.contains("| Cell spanning 2 columns"),
|
|
739
|
-
"spanning cell missing: {result}"
|
|
740
|
-
);
|
|
741
|
-
assert!(result.contains("| Cell 1"), "Cell 1 missing: {result}");
|
|
742
|
-
assert!(result.contains("| Cell 2"), "Cell 2 missing: {result}");
|
|
743
|
-
}
|