Rendering Markdown with Multiple Modes

Curated ago by @jeremysmithco

Description

Sometimes when I’m working with Markdown in a Rails app, I’ll be using different sets of redcarpet flags for different types of content. For example, I have images and links turned on for blog posts, but turned off for comments. Keeping track of all the variations can be difficult. I now prefer to define a set of render “modes” that I can pass into a single renderer class, with clear comments for what is allowed and disallowed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class MarkdownRenderer
  class DefaultRenderer < Redcarpet::Render::HTML
    include Redcarpet::Render::SmartyPants
  end

  def initialize(content, mode)
    @content = content
    @mode = mode
  end

  def render
    return "" if content.blank?

    markdown_mode.render(content)
  end

  private

  attr_reader :content, :mode

  def markdown_mode
    case mode
    when :full
      # Allow: links, images, tables, autolinking, blockcode, fenced code blocks
      Redcarpet::Markdown.new(
        DefaultRenderer.new(**default_markdown_settings.merge(no_links: false, no_images: false)),
        default_renderer_settings.merge(tables: true, autolink: true, gh_blockcode: true, fenced_code_blocks: true)
      )
    when :notes
      # Allow: links, tables, autolinking, blockcode, fenced code blocks
      Redcarpet::Markdown.new(
        DefaultRenderer.new(**default_markdown_settings.merge(no_links: false)),
        default_renderer_settings.merge(tables: true, autolink: true, gh_blockcode: true, fenced_code_blocks: true)
      )
    when :default
      # Use default settings
      Redcarpet::Markdown.new(
        DefaultRenderer.new(**default_markdown_settings),
        default_renderer_settings
      )
    end
  end

  # Default settings
  # Allow: hard wrap
  # Disallow: toc data, links, images, intra emphasis, tables, autlinking, blockcode, fenced code blocks

  def default_markdown_settings
    { hard_wrap: true, with_toc_data: false, no_links: true, no_images: true }
  end

  def default_renderer_settings
    { no_intra_emphasis: true, tables: false, autolink: false, gh_blockcode: false, fenced_code_blocks: false,
      disable_indented_code_blocks: true }
  end
end