redcarpet gem renderer that makes links out of `[[` blocks

81 Views Asked by At

I'm trying to use redcarpet to make a custom renderer that transforms [[id]] blocks into links to other pages in my app.

Documentation of custom renderers is rather concise, so I'm not sure how to use this.

here's what I got so far (which doesn't work)

class LinksRenderer < Redcarpet::Render::HTML
  def link(link, title, content)
    # Look for text enclosed in double square brackets and wrap it in an <a> tag
    if content =~ /\[\[(.*?)\]\]/
      text = $1
      "<a href='#{link}' title='#{title}'>#{text}</a>"
    else
      # Use the default link rendering behavior for other links
      super
    end
  end
end

which I call via a helper:

  def md(text)
    markdown = Redcarpet::Markdown.new(LinksRenderer.new)

    markdown.render(text).html_safe
  end

any ideas?

2

There are 2 best solutions below

0
Dāvis Namsons On

The link method will only be called when a link (a tag) is found.

To accomplish what you want, you would have to use the preprocess(full_document) or postprocess(full_document) described here. These methods will provide the entire content and you'll be able to replace the tags.

0
Don Giulio On

I had to override a number of renderers from redcarpet, so that they can correctly render links where appropriate, in particular the paragraph and list_item renderers, so that they can look for [[...]] and create links as appropriate. here's my code for the renderer:

class LinksRenderer < Redcarpet::Render::HTML
  def paragraph(text)
    process_custom_tags("<p>#{text.strip}</p>\n")
  end

  def list_item(text, params)
    "<li>#{process_custom_tags(text)}</li>\n"
  end

  def internal_link(page_timestamp)
    page = Page.find_by timestamp: page_timestamp
    return 'missing link' unless page

    url = Rails.application.routes.url_helpers.page_path(page)
    title = page.title
    content = page.title

    link(url, title, content)
  end

  def link(link, title, content)
    "<a href='#{link}' title='#{title}'>#{content}</a>"
  end

  private

  def process_custom_tags(text)
    matches = text.match(/\[\[(.*?)\]\]/)
    matches ? internal_link(matches[1]) : text
  end
end