Assign metadata to blockquotes in markdown

103 Views Asked by At

I need to associate markdown blockquotes with certain meta information (author/source, date, and link).

That information is then included in data attributes, and CSS displays a footer using the information in those attributes:

<blockquote data-source="some source" data-date="some date" data-link="some link">some quote...</blockquote>

The question is how to format my markdown syntax to populate those data attributes.

My current answer is to prepend the regular blockquote syntax with an additional line:

> <source={some source} date={some date} link={some link}>
> some quote...

This string is then passed to a custom renderer for the markdown library Red Carpet (Ruby), which recognizes it as a blockquote. Using a regular expression, I extract the metadata and render the corresponding <blockquote> tag.

class CustomRenderer < Redcarpet::Render::HTML
  include Rouge::Plugins::Redcarpet

  def block_quote(quote)
    pattern = /&lt;source={(?<source>[^}]+)} date={(?<date>[^}]+)}( link={(?<link>[^}]+)?})?&gt;(<br>)?(\n)?/m
    match = pattern.match(quote)

    if match
      quote.sub!(pattern, '')

      %{<blockquote data-source="#{match[:source]}" data-date="#{match[:date]}" data-link="#{match[:link]}">#{quote}</blockquote>}
    else
      %{<blockquote>#{quote}</blockquote>}
    end
  end
end

This approach does the job, but it feels ugly. Specifically, it's a rather unwieldy regular expression. More generally, I can't shake the feeling that there's gotta be an easier way.

I have considered preprocessing the string before parsing it, but no matter how I might preprocess it, I think I will need the block_quote method to be called eventually, and the metadata will need to be extracted there somehow.

I am also aware that there are ways of having metadata for the entire markdown string. But that doesn't include the metadata in the output.

Any better way to do this?

1

There are 1 best solutions below

0
Dennis Hackethal On

I have since found that the Kramdown gem seems to offer what I need.

They support custom attributes for block-level elements. Using their syntax, I could presumably do something like:

> A nice blockquote
{: data-source="..." data-date="..." data-link="..."}

And that should produce:

<blockquote data-source="..." data-date="..." data-link="...">
  A nice blockquote
</blockquote>

I won't be able to use this gem since I have incompatible pre-existing markdown syntax. Also, I think it's dangerous to let users set arbitrary custom attributes (XSS), so would need a whitelist. But I'm leaving this here in case it helps someone else.