//! Golden parser regression cases for panache-parser.
//!
//! Each test case is a directory under
//! `crates/panache-parser/tests/fixtures/cases/` containing:
//! - `input.*` - Source file (`.md`, `.qmd`, or `.Rmd`)
//! - `parser-options.toml` - (Optional) parser-only options (`flavor`, `[extensions]`)
//!
//! CST snapshots are stored via insta in
//! `crates/panache-parser/tests/snapshots/`.
//! Run `INSTA_UPDATE=always cargo test -p panache-parser --test golden_parser_cases`
//! to update snapshots intentionally.

use panache_parser::{Dialect, Extensions, Flavor, ParserOptions, parse};
use std::{
    collections::HashMap,
    fs,
    path::{Path, PathBuf},
};

/// Find a file with given base name and any supported extension.
fn find_file_with_extension(dir: &Path, base: &str) -> Option<PathBuf> {
    for ext in &["md", "qmd", "Rmd"] {
        let path = dir.join(format!("{}.{}", base, ext));
        if path.exists() {
            return Some(path);
        }
    }
    None
}

/// Load parser options from test case directory if parser-options.toml exists.
fn load_test_parser_options(dir: &Path) -> Option<ParserOptions> {
    let config_path = dir.join("parser-options.toml");
    if !config_path.exists() {
        return None;
    }

    let content = fs::read_to_string(config_path).ok()?;
    let value: toml::Value = toml::from_str(&content).ok()?;

    let mut options = ParserOptions::default();

    if let Some(flavor_str) = value.get("flavor").and_then(toml::Value::as_str) {
        let flavor = match flavor_str {
            "pandoc" => Flavor::Pandoc,
            "quarto" => Flavor::Quarto,
            "rmarkdown" => Flavor::RMarkdown,
            "gfm" => Flavor::Gfm,
            "commonmark" => Flavor::CommonMark,
            "multimarkdown" => Flavor::MultiMarkdown,
            _ => Flavor::default(),
        };
        options.flavor = flavor;
        options.dialect = Dialect::for_flavor(flavor);
        options.extensions = Extensions::for_flavor(flavor);
    }

    if let Some(ext_table) = value.get("extensions").and_then(toml::Value::as_table) {
        let mut overrides: HashMap<String, bool> = HashMap::new();
        for (key, val) in ext_table {
            if let Some(v) = val.as_bool() {
                overrides.insert(key.clone(), v);
            }
        }
        options.extensions = Extensions::merge_with_flavor(overrides, options.flavor);
    }

    Some(options)
}

/// Run parser-only checks for a single golden case.
fn run_golden_case(case_name: &str) {
    let dir = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("fixtures")
        .join("cases")
        .join(case_name);

    let input_path = find_file_with_extension(&dir, "input")
        .unwrap_or_else(|| panic!("No input file found in {}", case_name));
    let parser_options = load_test_parser_options(&dir);

    let input = fs::read_to_string(&input_path).unwrap();

    let tree = parse(&input, parser_options);
    let tree_text = tree.text().to_string();

    assert_eq!(
        input,
        tree_text,
        "losslessness check failed for {} (tree text does not match input, diff: {:+} bytes)",
        case_name,
        tree_text.len() as i64 - input.len() as i64
    );

    let cst_output = format!("{:#?}\n", tree);
    insta::assert_snapshot!(format!("parser_cst_{}", case_name), cst_output);
}

#[test]
fn issue_195_canonical_shape_delta() {
    let once_path = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("fixtures")
        .join("cases")
        .join("issue_195_blockquote_lazy_continuation_shape")
        .join("input.Rmd");
    let canonical_path = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("..")
        .join("..")
        .join("tests")
        .join("fixtures")
        .join("cases")
        .join("issue_177_list_blockquote_idempotency")
        .join("expected.Rmd");

    let once_input = fs::read_to_string(once_path).unwrap();
    let canonical_input = fs::read_to_string(canonical_path).unwrap();

    let once_tree = parse(&once_input, None);
    let canonical_tree = parse(&canonical_input, None);

    let once_cst = format!("{:#?}\n", once_tree);
    let canonical_cst = format!("{:#?}\n", canonical_tree);

    assert!(
        once_cst.contains("BLOCK_QUOTE_MARKER@417..418 \">\""),
        "expected issue_195 CST to keep shifted continuation marker as a structural token"
    );
    assert!(
        canonical_cst.contains("INLINE_CODE_CONTENT") && canonical_cst.contains("\"env\""),
        "expected canonical CST to retain inline-code content for env"
    );
}

macro_rules! golden_test_cases {
    ($($case:ident),+ $(,)?) => {
        $(
            #[test]
            fn $case() {
                run_golden_case(stringify!($case));
            }
        )+
    };
}

// Generate test functions for each case directory.
// To add a new test case:
// 1. Create a new directory under crates/panache-parser/tests/fixtures/cases/
// 2. Add the directory name to this list
golden_test_cases!(
    alerts,
    alerts_disabled,
    all_punctuation_escapes_commonmark,
    all_punctuation_escapes_pandoc,
    atx_empty_with_closing_fence,
    atx_interrupts_paragraph_commonmark,
    atx_interrupts_paragraph_pandoc,
    autolink_strict_validation_commonmark,
    autolink_strict_validation_pandoc,
    blankline_concatenation,
    blockquote_depth_change,
    blockquote_fenced_html_blocks_commonmark,
    blockquote_indented_code_tabs_commonmark,
    blockquote_lazy_continuation_reduced_markers,
    blockquote_list_blanks,
    blockquote_list_blockquote,
    blockquote_list_item_first_line_heading_pandoc,
    blockquote_list_item_first_line_hr_pandoc,
    blockquote_list_item_first_line_html_div_multiline_pandoc,
    blockquote_list_item_first_line_html_div_pandoc,
    blockquote_list_lazy_continuation_no_marker,
    blockquote_list_no_marker_closes_commonmark,
    blockquote_list_no_marker_continues_pandoc,
    blockquotes,
    bracketed_spans,
    bookdown,
    chunk_options_complex,
    code_blocks_executable,
    code_blocks_executable_with_classes,
    code_blocks_raw,
    code_fence_multiword_info_commonmark,
    code_fence_multiword_info_pandoc,
    code_spans,
    code_spans_unmatched_backtick_run_commonmark,
    code_spans_unmatched_backtick_run_pandoc,
    commonmark_entity_references_preserved,
    commonmark_image_paragraph_no_figure,
    crlf_basic,
    crlf_code_blocks,
    crlf_definition_lists,
    crlf_display_math,
    crlf_fenced_divs,
    crlf_headerless_table,
    crlf_horizontal_rules,
    crlf_line_endings,
    crlf_raw_blocks,
    crlf_yaml_metadata,
    citations,
    citation_prefix_paren_escape_278,
    definition_list,
    definition_list_blockquote_continuation,
    definition_list_in_list_blockquote,
    definition_list_inner_list_no_blank,
    definition_list_nesting,
    definition_list_pandoc_bare_leading_list,
    definition_list_pandoc_loose_compact,
    definition_list_wrapping,
    display_math,
    display_math_blank_line_termination,
    display_math_content_on_fence_line,
    display_math_escaped_dollar,
    display_math_trailing_text,
    double_backslash_math,
    emphasis,
    emphasis_asterisk_flanking_commonmark,
    emphasis_asterisk_flanking_pandoc,
    emphasis_complex,
    emphasis_same_delim_nested_commonmark,
    emphasis_same_delim_nested_pandoc,
    emphasis_skips_raw_html_and_autolink_commonmark,
    emphasis_skips_raw_html_and_autolink_pandoc,
    emphasis_split_runs_commonmark,
    emphasis_split_runs_pandoc,
    emphasis_intraword_underscore_closer,
    emphasis_intraword_underscore_strong_commonmark,
    emphasis_lazy_opener_preference_commonmark,
    emphasis_nested_inlines,
    emphasis_run_split_multiple_of_three_commonmark,
    emphasis_run_split_single_closer_commonmark,
    emphasis_skips_shortcut_reference_link,
    emphasis_underscore_run_5_commonmark,
    empty_list_marker_blank_then_content_commonmark,
    empty_list_marker_blank_then_content_pandoc,
    equation_attributes,
    equation_attributes_disabled,
    equation_attributes_no_blank_line,
    equation_attributes_single_line,
    escapes,
    fence_interrupts_blockquote_paragraph_commonmark,
    tilde_fence_mid_paragraph_pandoc,
    blockquote_paragraph_tilde_continuation_pandoc,
    blockquote_marker_does_not_interrupt_paragraph_pandoc,
    fenced_code,
    fenced_code_in_definition,
    fenced_code_in_list_blockquote,
    fenced_code_quarto,
    fenced_code_unclosed_commonmark,
    fenced_code_unclosed_pandoc,
    fenced_divs,
    fenced_div_attributes_structured,
    fenced_math_in_list_blockquote,
    fenced_div_list_idempotency_setup,
    fenced_div_close_grid_table,
    footnote_continuation_idempotency,
    footnote_continuation_idempotency_reflow,
    footnote_def_paragraph,
    footnote_definition_list,
    footnote_paragraph_no_list_interrupt,
    footnote_ref_in_footnote_def_is_text,
    footnote_with_blockquote,
    four_space_rule_continuation_2sp,
    four_space_rule_continuation_2sp_default,
    four_space_rule_continuation_4sp,
    four_space_rule_nested_2sp,
    four_space_rule_nested_4sp,
    four_space_rule_ordered_4sp,
    four_space_rule_wide_marker,
    headings,
    hr_as_list_item_content_commonmark,
    hr_as_list_item_content_pandoc,
    hr_closes_list_commonmark,
    hr_closes_list_pandoc,
    hr_interrupts_lazy_blockquote_paragraph_commonmark,
    hr_interrupts_lazy_blockquote_paragraph_pandoc,
    setext_headings,
    setext_heading_in_list_item_commonmark,
    setext_multiline_commonmark,
    setext_multiline_pandoc,
    setext_underline_crosses_blockquote_commonmark,
    setext_short_underline_commonmark,
    setext_short_underline_pandoc,
    setext_text_thematic_break_commonmark,
    setext_text_thematic_break_pandoc,
    thematic_break_interrupts_paragraph_commonmark,
    thematic_break_interrupts_paragraph_pandoc,
    headerless_table,
    horizontal_rules,
    html_block,
    html_block_button_inline_block_commonmark,
    html_block_button_inline_block_pandoc,
    html_block_article_indented_close_commonmark,
    html_block_article_indented_close_pandoc,
    html_block_article_leading_indent_commonmark,
    html_block_article_leading_indent_pandoc,
    html_block_commonmark_type6_type7_commonmark,
    html_block_commonmark_type6_type7_pandoc,
    html_block_comment_trailing_split_commonmark,
    html_block_comment_trailing_split_pandoc,
    html_block_comment_trailing_split_blockquote_pandoc,
    html_block_comment_trailing_split_list_item_commonmark,
    html_block_comment_trailing_split_list_item_pandoc,
    html_block_comment_multiline_trailing_split_pandoc,
    html_block_comment_multiline_trailing_split_blockquote_pandoc,
    html_block_pi_trailing_split_pandoc,
    html_block_pi_trailing_split_blockquote_pandoc,
    html_block_dialog_inline_commonmark,
    html_block_dialog_inline_pandoc,
    html_block_indented_style_commonmark,
    html_block_indented_style_pandoc,
    html_block_div_butted_close_commonmark,
    html_block_div_butted_close_pandoc,
    html_block_div_close_standalone_commonmark,
    html_block_div_close_standalone_pandoc,
    html_block_div_empty_commonmark,
    html_block_div_empty_pandoc,
    html_block_div_inner_blocks_commonmark,
    html_block_div_inner_blocks_pandoc,
    html_block_div_blockquote_depth_2_commonmark,
    html_block_div_blockquote_depth_2_pandoc,
    html_block_div_blockquote_messy_commonmark,
    html_block_div_blockquote_messy_pandoc,
    html_block_div_blockquote_multiline_open_commonmark,
    html_block_div_blockquote_multiline_open_pandoc,
    html_block_div_blockquote_multiline_open_trailing_commonmark,
    html_block_div_blockquote_multiline_open_trailing_pandoc,
    html_block_div_blockquote_multiline_same_line_close_commonmark,
    html_block_div_blockquote_multiline_same_line_close_pandoc,
    html_block_div_blockquote_multiline_trailing_close_text_commonmark,
    html_block_div_blockquote_multiline_trailing_close_text_pandoc,
    html_block_div_blockquote_nested_blocks_commonmark,
    html_block_div_blockquote_nested_blocks_pandoc,
    html_block_div_blockquote_same_line_commonmark,
    html_block_div_blockquote_same_line_pandoc,
    html_block_div_inside_blockquote_commonmark,
    html_block_div_inside_blockquote_pandoc,
    html_block_div_multiline_open_pandoc,
    html_block_div_multiline_open_trailing_commonmark,
    html_block_div_multiline_open_trailing_pandoc,
    html_block_div_multiline_same_line_close_commonmark,
    html_block_div_multiline_same_line_close_pandoc,
    html_block_div_multiline_trailing_close_text_commonmark,
    html_block_div_multiline_trailing_close_text_pandoc,
    html_block_div_nested_commonmark,
    html_block_div_nested_pandoc,
    html_block_div_nested_trailing_commonmark,
    html_block_div_nested_trailing_pandoc,
    html_block_div_same_line_commonmark,
    html_block_div_same_line_pandoc,
    html_block_div_same_line_trailing_commonmark,
    html_block_div_same_line_trailing_pandoc,
    html_block_div_trailing_close_commonmark,
    html_block_div_trailing_close_pandoc,
    html_block_div_trailing_open_commonmark,
    html_block_div_trailing_open_pandoc,
    html_block_div_unclosed_commonmark,
    html_block_div_unclosed_pandoc,
    html_block_div_uppercase_pandoc,
    html_block_div_with_id_commonmark,
    html_block_div_with_id_pandoc,
    html_block_doctype_commonmark,
    html_block_embed_void_commonmark,
    html_block_embed_void_pandoc,
    html_block_doctype_lowercase_commonmark,
    html_block_doctype_lowercase_pandoc,
    html_block_doctype_pandoc,
    html_block_form_blockquote_multiline_same_line_close_commonmark,
    html_block_form_blockquote_multiline_same_line_close_pandoc,
    html_block_form_multiline_same_line_close_commonmark,
    html_block_form_multiline_same_line_close_pandoc,
    html_block_incomplete_open_commonmark,
    html_block_incomplete_open_pandoc,
    html_block_multiline_embed_open_commonmark,
    html_block_multiline_embed_open_pandoc,
    html_block_p_close_standalone_commonmark,
    html_block_p_close_standalone_pandoc,
    html_block_paragraph_demote_strict_commonmark,
    html_block_paragraph_demote_strict_pandoc,
    html_block_paragraph_demote_div_pandoc,
    html_block_paragraph_then_pi_commonmark,
    html_block_paragraph_then_pi_pandoc,
    html_block_paragraph_then_script_close_commonmark,
    html_block_paragraph_then_script_close_pandoc,
    html_block_paragraph_then_script_mathtex_open_commonmark,
    html_block_paragraph_then_script_mathtex_open_pandoc,
    html_block_paragraph_then_style_commonmark,
    html_block_paragraph_then_style_pandoc,
    html_block_pre_close_standalone_commonmark,
    html_block_pre_close_standalone_pandoc,
    html_block_pre_close_tag_inline_commonmark,
    html_block_inline_block_blockquote_commonmark,
    html_block_inline_block_blockquote_pandoc,
    html_block_inline_block_blockquote_messy_commonmark,
    html_block_inline_block_blockquote_messy_pandoc,
    html_block_inline_block_blockquote_same_line_commonmark,
    html_block_inline_block_blockquote_same_line_pandoc,
    html_block_strict_block_blockquote_commonmark,
    html_block_strict_block_blockquote_pandoc,
    html_block_strict_block_blockquote_messy_commonmark,
    html_block_strict_block_blockquote_messy_pandoc,
    html_block_strict_block_blockquote_same_line_commonmark,
    html_block_strict_block_blockquote_same_line_pandoc,
    html_block_section_blockquote_multiline_open_commonmark,
    html_block_section_blockquote_multiline_open_pandoc,
    html_block_strict_block_inner_lift_commonmark,
    html_block_strict_block_inner_lift_pandoc,
    html_block_strict_block_lift_shapes_commonmark,
    html_block_strict_block_lift_shapes_pandoc,
    html_block_strict_block_multiline_open_commonmark,
    html_block_strict_block_multiline_open_pandoc,
    html_block_video_close_standalone_commonmark,
    html_block_video_close_standalone_pandoc,
    html_block_video_matched_pair_commonmark,
    html_block_video_matched_pair_pandoc,
    html_block_video_source_fallback_pandoc,
    html_block_video_uppercase_commonmark,
    html_block_video_uppercase_pandoc,
    html_inline_span_with_id_commonmark,
    html_inline_span_with_id_pandoc,
    html_comment_after_paragraph_commonmark,
    html_comment_after_paragraph_pandoc,
    ignore_directives,
    images,
    indented_code,
    indented_code_after_atx_heading_commonmark,
    indented_code_after_atx_heading_pandoc,
    indented_code_mixed_tab_space,
    inline_html_basic_commonmark,
    inline_link_code_span_precedence,
    inline_link_dest_angle_brackets_with_parens,
    inline_link_dest_strict_commonmark,
    inline_link_dest_strict_pandoc,
    inline_code,
    inline_code_attributes_lossless,
    inline_footnotes,
    inline_math,
    inline_math_operators,
    grid_table,
    grid_table_in_list_blockquote,
    grid_table_indented_is_paragraph,
    grid_table_nordics,
    grid_table_planets,
    latex_environment,
    lazy_continuation_deep,
    leading_blanklines,
    line_block_in_list_blockquote,
    line_blocks,
    line_ending_crlf,
    line_ending_lf,
    gfm_image_inside_link_text,
    gfm_inline_image,
    image_inside_link_text_pandoc,
    link_in_link_reference_commonmark,
    link_inside_link_text_commonmark,
    link_inside_link_text_pandoc,
    link_inside_reference_link_text_pandoc,
    link_text_skips_autolink_commonmark,
    link_text_skips_autolink_pandoc,
    link_text_skips_raw_html_commonmark,
    link_text_skips_raw_html_pandoc,
    links,
    list_interrupts_paragraph_commonmark,
    list_interrupts_paragraph_pandoc,
    list_item_bare_marker_empty_commonmark,
    list_item_blank_line_inside,
    list_item_blank_then_refdef_commonmark,
    list_item_blockquote_internal_blank_commonmark,
    list_item_blockquote_nested_list_issue_292,
    list_item_empty_marker_indented_code_next_line,
    list_item_empty_marker_setext_blocked_commonmark,
    list_item_fenced_code_first_line_commonmark,
    list_item_fenced_div_marker_line_pandoc,
    list_item_fenced_div_marker_line_unclosed_pandoc,
    list_item_grid_table_continuation_blank_pandoc,
    list_item_grid_table_marker_line_pandoc,
    list_item_html_div_multiline_open_commonmark,
    list_item_html_div_multiline_open_pandoc,
    list_item_html_div_multiline_para_commonmark,
    list_item_html_div_multiline_para_pandoc,
    list_item_html_div_same_line_commonmark,
    list_item_html_div_same_line_pandoc,
    list_item_html_div_same_line_trailing_commonmark,
    list_item_html_div_same_line_trailing_pandoc,
    list_item_html_div_tab_indent_commonmark,
    list_item_html_div_tab_indent_pandoc,
    list_item_html_pre_multiline_commonmark,
    list_item_html_pre_multiline_pandoc,
    list_item_html_pre_tab_indent_commonmark,
    list_item_html_pre_tab_indent_pandoc,
    list_item_html_section_multiline_commonmark,
    list_item_html_section_multiline_pandoc,
    list_item_indented_code,
    list_item_indented_code_marker_line_partial_overflow,
    list_item_indented_code_tabs_commonmark,
    list_item_pipe_table_continuation_blank_pandoc,
    list_item_pipe_table_marker_line_no_separator_pandoc,
    list_item_pipe_table_marker_line_pandoc,
    list_alpha_roman_continuation_pandoc,
    list_item_blockquote_inner_list,
    list_item_same_line_blockquote_marker_commonmark,
    list_item_same_line_blockquote_marker_pandoc,
    list_bullet_outdent_after_blank_no_outer_list,
    list_marker_indent_4_below_content_col,
    list_empty_marker_indent_four_past_content_col,
    list_orphan_indent4_marker_after_blank_becomes_codeblock,
    list_mixed_bullets_commonmark,
    list_mixed_bullets_pandoc,
    list_nested_same_line_marker_commonmark,
    list_nested_same_line_marker_pandoc,
    lists_bullet,
    lists_code,
    lists_example,
    lists_fancy,
    lists_fancy_uppercase_roman_period_pandoc,
    lists_nested,
    lists_ordered,
    lists_task,
    lists_wrapping_nested,
    lists_wrapping_simple,
    ordered_marker_max_digits_commonmark,
    ordered_marker_max_digits_pandoc,
    ordered_paren_marker_decimal_commonmark,
    multiline_table_basic,
    multiline_table_caption,
    multiline_table_caption_after,
    multiline_table_headerless,
    multiline_table_in_list_blockquote,
    multiline_table_inline_formatting,
    mmd_title_block,
    mmd_link_attributes,
    mmd_link_attributes_disabled,
    native_span_html_attrs_commonmark,
    nested_headings_in_containers,
    nested_list_blank_between_outer_items_commonmark,
    multiline_table_single_row,
    mmd_header_identifiers,
    pandoc_title_block,
    paragraph_continuation,
    paragraph_leading_whitespace,
    paragraph_plain_mixed,
    paragraph_wrapping,
    paragraphs,
    pipe_table,
    pipe_table_caption_attribute,
    pipe_table_in_list_blockquote,
    pipe_table_unicode,
    plain_continuation_edge_cases,
    quarto_code_blocks,
    quarto_hashpipe,
    quarto_hashpipe_list_item,
    quarto_shortcodes,
    raw_blocks,
    raw_inline_format_attr,
    raw_tex_commands,
    reference_definition_attached_title_commonmark,
    reference_definition_attached_title_pandoc,
    reference_definition_inside_blockquote,
    reference_definition_label_with_escaped_bracket,
    reference_definition_multiline_destination,
    reference_definition_multiline_label,
    reference_definition_no_interrupt_paragraph,
    reference_definition_structured_url_title,
    setext_vs_reference_definition_commonmark,
    setext_vs_reference_definition_pandoc,
    reference_footnotes,
    reference_images,
    reference_link_code_span_precedence,
    reference_links,
    spaced_reference_links,
    unresolved_collapsed_reference_pandoc,
    unresolved_full_reference_pandoc,
    unresolved_image_reference_pandoc,
    unresolved_reference_intraword_underscore_pandoc,
    unresolved_shortcut_reference_pandoc,
    bug_2_emphasis_crosses_brackets_pandoc,
    rmarkdown_math,
    simple_table,
    simple_table_in_list_blockquote,
    standardize_bullets,
    subscript_unclosed_double_tilde_pandoc,
    sentence_wrap_basic,
    sentence_wrap_abbreviations,
    sentence_wrap_contextual_abbrev,
    sentence_wrap_lang_metadata,
    sentence_wrap_list_blockquote,
    sentence_wrap_lazy_continuation,
    sentence_wrap_links_figures,
    sentence_wrap_lists,
    sentence_wrap_ellipsis,
    sentence_wrap_inline_code_sentence_end,
    sentence_wrap_quote_multisentence,
    sentence_wrap_inline_code_question,
    sentence_wrap_table_caption,
    table_caption_close_fence_after,
    table_with_caption,
    tables_adjacent,
    tables_in_divs,
    tab_handling,
    tab_preserve,
    trailing_blanklines,
    umlauts,
    unicode,
    issue_164_unicode_autolink_panic,
    issue_174_blockquote_list_reorder_losslessness,
    issue_175_native_span_unicode_panic,
    issue_186_list_blockquote_lazy_idempotency,
    issue_195_blockquote_lazy_continuation_shape,
    issue_197_gfm_non_idempotent_bare_uri_escape,
    issue_209_definition_list_blockquote_continuation,
    issue_224_simple_table_short_header_losslessness,
    issue_235_gfm_bare_uri_in_link_text,
    issue_249_indented_paragraph_line_atx_shape,
    issue_310_blockquote_flush_fenced_div_pandoc,
    issue_314_advance_columns_multibyte,
    issue_336_gfm_strong_colon_bare_uri,
    writer_autolinks,
    writer_blockquote_not,
    writer_definition_lists_multiblock,
    writer_headers,
    writer_html_blocks,
    writer_paragraphs,
    writer_indented_code_escapes,
    wikilinks_after_pipe_basic,
    wikilinks_before_pipe_basic,
    wikilinks_image,
    wikilinks_edge_cases,
    wikilinks_disabled,
    wikilinks_both_enabled,
    yaml_metadata,
    yaml_metadata_dots_closer,
    yaml_metadata_embedded_subtree,
    yaml_metadata_normalization,
    yaml_metadata_opening_blank_not_metadata,
);
