gjtorikian / html-pipeline

HTML processing filters and utilities
MIT License
2.27k stars 380 forks source link

Add ability to pass custom renderer to MarkdownFilter #318

Closed gjtorikian closed 4 years ago

gjtorikian commented 4 years ago

This PR implements a feature request from Heroku. ✨

Commonmarker allows you to pass a custom renderer. This can be useful in instances where you want to halt the traditional Markdown to HTML conversion and do something else with that information. However, the MarkdownFilter here would not accept a custom renderer.

This PR allows one to provide a custom renderer. A user would need to write their own custom renderer class, and then pass it into the filter as an option:

MarkdownFilter.new(@header, commonmarker_renderer: CustomRenderer).call

In the provided test case, CustomRenderer looks like this:

  class CustomRenderer < CommonMarker::HtmlRenderer
    def header(node)
      block do
        text = node.first_child.string_content
        level = node.header_level
        out("{level: #{level}, text: #{text}}")
        super
      end
    end
  end

Unfortunately, writing a custom renderer is not very well documented. In essence, every Markdown "type"--links, headers, images, and so forth--can have a method matching that name. The custom renderer will call that method before continuing the regular Markdown-> HTML conversion. For example, here, we:

For a file that looks like this:

    # Words
    Some words
    ## Words
    More words?

The following HTML would be produced:

    {level: 1, text: Words}
    <h1>Words</h1>
    <p>Some words</p>
    {level: 2, text: Words}
    <h2>Words</h2>
    <p>More words?</p>

/cc @hannesfostie do let me know if this suffices!

hannesfostie commented 4 years ago

This is great! Thank you