use ferromark::Options;
use ferromark::to_html;
use ferromark::to_html_with_options;
#[test]
fn gfm_example_198_basic_table() {
let input = "| foo | bar |\n| --- | --- |\n| baz | bim |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>foo</th>\n<th>bar</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>baz</td>\n<td>bim</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn gfm_example_199_alignment() {
let input = "| abc | defghi |\n:-: | -----------:\nbar | baz\n";
let expected = "<table>\n<thead>\n<tr>\n<th align=\"center\">abc</th>\n<th align=\"right\">defghi</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\">bar</td>\n<td align=\"right\">baz</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn gfm_example_200_escaped_pipes() {
let input = "| f\\|oo |\n| ------ |\n| b `\\|` az |\n| b **\\|** im |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>f|oo</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>b <code>|</code> az</td>\n</tr>\n<tr>\n<td>b <strong>|</strong> im</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn gfm_example_201_blockquote_terminates() {
let input = "| abc | def |\n| --- | --- |\n| bar | baz |\n> bar\n";
let expected = "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr>\n</tbody>\n</table>\n<blockquote>\n<p>bar</p>\n</blockquote>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn gfm_example_202_blank_line_terminates() {
let input = "| abc | def |\n| --- | --- |\n| bar | baz |\nbar\n\nbar\n";
let expected = "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr>\n<tr>\n<td>bar</td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>bar</p>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn gfm_example_203_cell_count_mismatch() {
let input = "| abc | def |\n| --- |\n| bar |\n";
let expected = "<p>| abc | def |\n| --- |\n| bar |</p>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn gfm_example_204_variable_row_lengths() {
let input = "| abc | def |\n| --- | --- |\n| bar |\n| bar | baz | boo |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td></td>\n</tr>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn gfm_example_205_empty_body() {
let input = "| abc | def |\n| --- | --- |\n";
let expected =
"<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_in_blockquote() {
let input = "> | a | b |\n> | - | - |\n> | c | d |\n";
let expected = "<blockquote>\n<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n</blockquote>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_in_list_item() {
let input = "- | a | b |\n | - | - |\n | c | d |\n";
let expected = "<ul>\n<li>\n<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n</li>\n</ul>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_with_inline_content() {
let input =
"| *em* | **strong** | `code` |\n| --- | --- | --- |\n| [link](url) |  | a |\n";
let expected = "<table>\n<thead>\n<tr>\n<th><em>em</em></th>\n<th><strong>strong</strong></th>\n<th><code>code</code></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a href=\"url\">link</a></td>\n<td><img src=\"src\" alt=\"img\" /></td>\n<td>a</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_preceded_by_paragraph() {
let input = "Paragraph text\nHeader\n| --- |\ndata\n";
let expected = "<p>Paragraph text</p>\n<table>\n<thead>\n<tr>\n<th>Header</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>data</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn single_column_table() {
let input = "| a |\n| - |\n| b |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>b</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn all_alignment_types() {
let input = "| a | b | c | d |\n| --- | :--- | :---: | ---: |\n| 1 | 2 | 3 | 4 |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th align=\"left\">b</th>\n<th align=\"center\">c</th>\n<th align=\"right\">d</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td align=\"left\">2</td>\n<td align=\"center\">3</td>\n<td align=\"right\">4</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_terminated_by_heading() {
let input = "| a | b |\n| - | - |\n| c | d |\n# Heading\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n<h1 id=\"heading\">Heading</h1>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_terminated_by_code_fence() {
let input = "| a | b |\n| - | - |\n| c | d |\n```\ncode\n```\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n<pre><code>code\n</code></pre>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_terminated_by_thematic_break() {
let input = "| a | b |\n| - | - |\n| c | d |\n---\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n<hr />\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_disabled_via_options() {
let input = "| a | b |\n| - | - |\n| c | d |\n";
let options = Options {
tables: false,
..Options::default()
};
let result = to_html_with_options(input, &options);
assert!(
!result.contains("<table>"),
"Should not contain table: {result}"
);
}
#[test]
fn escaped_pipe_at_end() {
let input = "| a\\| | b |\n| --- | --- |\n| c\\| | d |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a|</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>c|</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn table_at_eof() {
let input = "| a | b |\n| - | - |\n| c | d |";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn multiple_tables() {
let input = "| a |\n| - |\n| b |\n\nText\n\n| c |\n| - |\n| d |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>b</td>\n</tr>\n</tbody>\n</table>\n<p>Text</p>\n<table>\n<thead>\n<tr>\n<th>c</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn delimiter_all_none_alignment() {
let input = "| a | b |\n| --- | --- |\n| c | d |\n";
let result = to_html(input);
assert!(result.contains("<th>a</th>"));
assert!(result.contains("<td>c</td>"));
assert!(!result.contains("align="));
}
#[test]
fn delimiter_left_alignment() {
let input = "| a |\n| :--- |\n| b |\n";
let result = to_html(input);
assert!(result.contains("<th align=\"left\">a</th>"));
assert!(result.contains("<td align=\"left\">b</td>"));
}
#[test]
fn cmark_ext_multi_row_body() {
let input = "| abc | def |\n| --- | --- |\n| ghi | jkl |\n| mno | pqr |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ghi</td>\n<td>jkl</td>\n</tr>\n<tr>\n<td>mno</td>\n<td>pqr</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_inline_formatting_in_cells() {
let input = "Hello!\n\n| _abc_ | \u{30BB}\u{30F3} |\n| ----- | ---- |\n| 1. Block elements inside cells don't work. | |\n| But _**inline elements do**_. | x |\n\nHi!\n";
let expected = "<p>Hello!</p>\n<table>\n<thead>\n<tr>\n<th><em>abc</em></th>\n<th>\u{30BB}\u{30F3}</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1. Block elements inside cells don't work.</td>\n<td></td>\n</tr>\n<tr>\n<td>But <em><strong>inline elements do</strong></em>.</td>\n<td>x</td>\n</tr>\n</tbody>\n</table>\n<p>Hi!</p>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_table_recognition_edge_cases() {
assert_eq!(
to_html("| Not enough table | to be considered table |\n"),
"<p>| Not enough table | to be considered table |</p>\n"
);
assert_eq!(
to_html(
"| Not enough table | to be considered table |\n| Not enough table | to be considered table |\n"
),
"<p>| Not enough table | to be considered table |\n| Not enough table | to be considered table |</p>\n"
);
let input = "| Just enough table | to be considered table |\n| ----------------- | ---------------------- |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>Just enough table</th>\n<th>to be considered table</th>\n</tr>\n</thead>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_delimiter_row_alone() {
let input = "| ---- | --- |\n";
let result = to_html(input);
assert!(
!result.contains("<table>"),
"Delimiter row alone should not be a table: {result}"
);
}
#[test]
fn cmark_ext_minimal_single_cell() {
let input = "|x|\n|-|\n";
let expected = "<table>\n<thead>\n<tr>\n<th>x</th>\n</tr>\n</thead>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_no_leading_pipes() {
let input = "abc | def\n--- | ---\nxyz | ghi\n";
let expected = "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>xyz</td>\n<td>ghi</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_five_column_alignment() {
let input =
"aaa | bbb | ccc | ddd | eee\n:-- | --- | :-: | --- | --:\nfff | ggg | hhh | iii | jjj\n";
let expected = "<table>\n<thead>\n<tr>\n<th align=\"left\">aaa</th>\n<th>bbb</th>\n<th align=\"center\">ccc</th>\n<th>ddd</th>\n<th align=\"right\">eee</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"left\">fff</td>\n<td>ggg</td>\n<td align=\"center\">hhh</td>\n<td>iii</td>\n<td align=\"right\">jjj</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_header_delimiter_mismatch() {
let input = "| a | b | c |\n| --- | --- |\n| this | isn't | okay |\n";
let expected = "<p>| a | b | c |\n| --- | --- |\n| this | isn't | okay |</p>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_body_cell_count_flexibility() {
let input = "| a | b | c |\n| --- | --- | ---\n| x\n| a | b\n| 1 | 2 | 3 | 4 | 5 |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>x</td>\n<td></td>\n<td></td>\n</tr>\n<tr>\n<td>a</td>\n<td>b</td>\n<td></td>\n</tr>\n<tr>\n<td>1</td>\n<td>2</td>\n<td>3</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_escaped_pipes_in_body() {
let input = "| a | b |\n| --- | --- |\n| Escaped pipes are \\|okay\\|. | Like \\| this. |\n| Within `\\|code\\| is okay` too. |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Escaped pipes are |okay|.</td>\n<td>Like | this.</td>\n</tr>\n<tr>\n<td>Within <code>|code| is okay</code> too.</td>\n<td></td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_oddly_formatted_delimiter() {
let input = "| a |\n--- |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n</tr>\n</thead>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_escaping_behavior() {
let input = "| a | b |\n| --- | --- |\n| \\\\ | `\\\\` |\n| \\\\\\\\ | `\\\\\\\\` |\n| \\_ | `\\_` |\n| \\| | `\\|` |\n| \\a | `\\a` |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>\\</td>\n<td><code>\\\\</code></td>\n</tr>\n<tr>\n<td>\\\\</td>\n<td><code>\\\\\\\\</code></td>\n</tr>\n<tr>\n<td>_</td>\n<td><code>\\_</code></td>\n</tr>\n<tr>\n<td>|</td>\n<td><code>|</code></td>\n</tr>\n<tr>\n<td>\\a</td>\n<td><code>\\a</code></td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_embedded_html_in_cells() {
let input = "| a |\n| --- |\n| <strong>hello</strong> |\n| ok <br> sure |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>hello</strong></td>\n</tr>\n<tr>\n<td>ok <br> sure</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_reference_links_in_cells() {
let input = "Here's a link to [Freedom Planet 2][].\n\n| Here's a link to [Freedom Planet 2][] in a table header. |\n| --- |\n| Here's a link to [Freedom Planet 2][] in a table row. |\n\n[Freedom Planet 2]: http://www.freedomplanet2.com/\n";
let expected = "<p>Here's a link to <a href=\"http://www.freedomplanet2.com/\">Freedom Planet 2</a>.</p>\n<table>\n<thead>\n<tr>\n<th>Here's a link to <a href=\"http://www.freedomplanet2.com/\">Freedom Planet 2</a> in a table header.</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Here's a link to <a href=\"http://www.freedomplanet2.com/\">Freedom Planet 2</a> in a table row.</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_sequential_empty_cells() {
let input = "| a | b | c |\n| --- | --- | --- |\n| d || e |\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>d</td>\n<td></td>\n<td>e</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_emphasis_interaction() {
let input = "| a | b |\n| --- | --- |\n|***(a)***|\n";
let expected = "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><em><strong>(a)</strong></em></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_ext_table_after_multiline_paragraph() {
let input = "123\n456\n| a | b |\n| ---| --- |\nd | e\n";
let expected = "<p>123\n456</p>\n<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>d</td>\n<td>e</td>\n</tr>\n</tbody>\n</table>\n";
assert_eq!(to_html(input), expected);
}
#[test]
fn cmark_regression_bare_pipe_dash() {
let input = "|\n-|\n";
let result = to_html(input);
assert!(
!result.contains("<table>"),
"Bare pipe+dash should not be table: {result}"
);
}