"""Raw HTML block. Build with `Node(HtmlBlock, html_string)`."""
mutable struct HtmlBlock <: AbstractBlock
    html_block_type::Int
    raw::Bool
    HtmlBlock(; raw = false) = new(0, raw)
end

accepts_lines(::HtmlBlock) = true

function continue_(::HtmlBlock, parser::Parser, container::Node)
    return (parser.blank && container.t.html_block_type in 6:7) ? 1 : 0
end

function finalize(::HtmlBlock, parser::Parser, block::Node)
    finalize_literal!(block)
    block.literal = replace(block.literal, r"(\n *)+$" => "")
    return nothing
end

can_contain(::HtmlBlock, t) = false

function Node(::Type{HtmlBlock}, html::AbstractString)
    node = Node(HtmlBlock())
    node.literal = html
    return node
end

function html_block(parser::Parser, container::Node)
    if !parser.indented && peek_nonspace(parser) == '<'
        s = rest_from_nonspace(parser)
        for (block_type, regex) in enumerate(reHtmlBlockOpen)
            if occursin(regex, s) && (block_type < 7 || !(container.t isa Paragraph))
                close_unmatched_blocks(parser)
                # Don't adjust parser.pos; spaces are part of HTML block.
                b = add_child(parser, HtmlBlock(), parser.pos)
                b.t.html_block_type = block_type
                return 2
            end
        end
    end
    return 0
end

"""
    HtmlBlockRule()

Parse raw HTML blocks.

Enabled by default. Recognizes common HTML tags and passes them through unchanged.

```markdown
<div class="warning">
  <p>Raw HTML content</p>
</div>
```
"""
struct HtmlBlockRule end
block_rule(::HtmlBlockRule) = Rule(html_block, 4, "<>")
