HTML
The HTML parser uses Nokogiri to tolerate malformed HTML and produces the same AST the other parsers feed into.
Requirements
Section titled “Requirements”Add nokogiri to your Gemfile. It’s a runtime dependency for the HTML parser:
gem "nokogiri"Quick start
Section titled “Quick start”require "markbridge/html"
result = Markbridge.html_to_markdown("<p>Hello <strong>world</strong>!</p>")result.markdown# => "Hello **world**!"result is a Markbridge::Conversion — .markdown, plus .unknown_tags, .errors for migration use.
To get the AST:
parse = Markbridge.parse_html("<a href='https://example.com'>link</a>")parse.ast# => AST::Document(Url("link", href: "https://example.com"))Supported tags
Section titled “Supported tags”<thead>, <tbody>, <tfoot> are transparent — their children are processed as if the wrapper weren’t there. Unregistered tags are skipped, but their children are still processed (graceful degradation).
For the authoritative list, see HandlerRegistry.default.
Code languages
Section titled “Code languages”For syntax highlighting, the parser uses the first valid language from:
- A
language-*class on the element. - A
language-*class on its direct<code>child. - The element’s
langattribute. - A single class on the element or its direct
<code>child.
The language must contain only letters, digits, underscores, plus signs, or hyphens, and start with a letter or digit. A class list such as hljs codeblock does not become a language.
require "markbridge/html"
result = Markbridge.html_to_markdown('<pre><code class="language-ruby">puts 1</code></pre>')result.markdown# => "```ruby\nputs 1\n```"Parser characteristics
Section titled “Parser characteristics”- Uses Nokogiri’s HTML fragment parser — handles malformed input without raising.
- Stateless handlers — simpler than BBCode’s open/close callback API. A handler is an object responding to
#process(element:, parent:).
class AsideHandler < Markbridge::Parsers::HTML::Handlers::BaseHandler def initialize @element_class = AST::Quote end
attr_reader :element_class
def process(element:, parent:) note = AST::Quote.new parent << note note # return node to recurse into for children endend
handlers = Markbridge::Parsers::HTML::HandlerRegistry.build_from_default do |registry| registry.register("aside", AsideHandler.new) end
Markbridge.html_to_markdown("<aside>heads up</aside>", handlers:)Using the parser directly
Section titled “Using the parser directly”parser = Markbridge::Parsers::HTML::Parser.newast = parser.parse("<p>rich <em>content</em></p>")
renderer = Markbridge::Renderers::Discourse::Renderer.newrenderer.render(ast)What’s not supported
Section titled “What’s not supported”The default registry is intentionally scoped to the Discourse-facing subset. Notably:
- Inline styles and
<span>/<div>without handlers pass through transparently (children only). <script>,<style>,<iframe>and similar tags are not registered; children are still processed.- If you need semantic mappings for something richer (for example
<details>→ spoiler), register a handler — see Extending Markbridge.