Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to pass custom renderer to MarkdownFilter #318

Merged
merged 1 commit into from
Oct 9, 2019

Conversation

gjtorikian
Copy link
Owner

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:

  • Define a method called header, which only acts on the headers found in the Markdown document
  • Takes the contents of that header (node.first_child.string_content)
  • Takes the header level (node.header_level)
  • Writes back some information back out to the Markdown string ({level: #{level}, text: #{text}})
  • Continues processing the header as normal (super)

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
Copy link
Contributor

This is great! Thank you

@gjtorikian gjtorikian merged commit b084127 into master Oct 9, 2019
@gjtorikian gjtorikian deleted the allow-for-renderer branch October 9, 2019 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants