class Middleman::HashiCorp::RedcarpetHTML
Our custom Markdown parser - extends middleman's customer parser so we pick up all the magic.
Constants
- REDCARPET_OPTIONS
Custom RedCarpet options.
Public Class Methods
# File lib/middleman-hashicorp/redcarpet.rb, line 21 def initialize(options = {}) super(options.merge(REDCARPET_OPTIONS)) end
Public Instance Methods
Override block_html
to support parsing nested markdown blocks.
@param [String] raw
# File lib/middleman-hashicorp/redcarpet.rb, line 67 def block_html(raw) raw = unindent(raw) if md = raw.match(/\<(.+?)\>(.*)\<(\/.+?)\>/m) open_tag, content, close_tag = md.captures rendered_content = recursive_render(content) # If the recursive render did more than simply wrap # the content within a paragraph, assume this is valid # markdown content and return the result if rendered_content != paragraph(content) return "<#{open_tag}>\n#{rendered_content}<#{close_tag}>" end end raw end
Override headers to add custom links.
# File lib/middleman-hashicorp/redcarpet.rb, line 28 def header(title, level) anchor = anchor_link(title) return <<-EOH.gsub(/^ {6}/, "") <h#{level} id="#{anchor}"> <a name="#{anchor}" class="anchor" href="##{anchor}">»</a> #{title} </h#{level}> EOH end
Override list_item
to automatically add links for documentation
@param [String] text @param [String] list_type
# File lib/middleman-hashicorp/redcarpet.rb, line 45 def list_item(text, list_type) @anchors ||= {} md = text.match(/\A(?:<p>)?(<code>(.+?)<\/code>)/) linked = !text.match(/\A(<p>)?<a(.+?)>(.+?)<\/a>\s*?[-:]?/).nil? if !md.nil? && !linked container, name = md.captures anchor = anchor_link(name) replace = %|<a name="#{anchor}" /><a href="##{anchor}">#{container}</a>| text.sub!(container, replace) end "<li>#{text}</li>\n" end
Override paragraph to support custom alerts.
@param [String] text @return [String]
# File lib/middleman-hashicorp/redcarpet.rb, line 89 def paragraph(text) add_alerts("<p>#{text.strip}</p>\n") end
Private Instance Methods
Add alert text to the given markdown.
@param [String] text @return [String]
# File lib/middleman-hashicorp/redcarpet.rb, line 139 def add_alerts(text) map = { "=>" => "success", "->" => "info", "~>" => "warning", "!>" => "danger", } regexp = map.map { |k, _| Regexp.escape(k) }.join("|") if md = text.match(/^<p>(#{regexp})/) key = md.captures[0] klass = map[key] text.gsub!(/#{Regexp.escape(key)}\s+?/, "") return <<-EOH.gsub(/^ {8}/, "") <div class="alert alert-#{klass}" role="alert"> #{text}</div> EOH else return text end end
Generate an anchor link from the generated raw value.
@return [String]
# File lib/middleman-hashicorp/redcarpet.rb, line 100 def anchor_link(raw) @anchors ||= {} name = raw .downcase .strip .gsub(/<\/?[^>]*>/, '') # Strip links .gsub(/\W+/, '-') # Whitespace to - .gsub(/\A\-/, '') # No leading - .squeeze('-') # Collapse -- i = 0 link = name while @anchors.key?(link) do i += 1 link = "#{name}-#{i}" end @anchors[link] = true return link end
This is jank, but Redcarpet does not provide a way to access the renderer from inside Redcarpet::Markdown. Since we know who we are, we can cheat a bit.
@param [String] markdown @return [String]
# File lib/middleman-hashicorp/redcarpet.rb, line 129 def recursive_render(markdown) Redcarpet::Markdown.new(self.class, REDCARPET_OPTIONS).render(markdown) end
# File lib/middleman-hashicorp/redcarpet.rb, line 163 def unindent(string) string.gsub(/^#{string.scan(/^[[:blank:]]+/).min_by { |l| l.length }}/, "") end