Shopify / liquid

Liquid markup language. Safe, customer facing template language for flexible web apps.
https://shopify.github.io/liquid/
MIT License
11.01k stars 1.38k forks source link

Custom tags: what’s the preferred method of providing arguments containing quotes #507

Open paulrobertlloyd opened 9 years ago

paulrobertlloyd commented 9 years ago

TL;DR: How should I provide/parse arguments that may contain a single or double quote(s) in a custom tag?


Not sure if this is the correct place to ask a question, but couldn't find documentation elsewhere…

I’ve created a custom liquid tag block, to render a figure with optional caption. Here’s an example:

{% figure class:'class1 class2', caption:''Cloud Gate' by Anish Kapoor' %}
![](/assets/images/cloudgate.jpg)
{% endfigure %}

Firstly, is this the correct method of supplying arguments to a custom block? I see that pipe delimited arguments are for filters, the = symbol for assignments.

I'm using Liquid::TagAttributes, to parse each argument. I’m then having to remove (with gsub) the first and last ' or " else these get output in the HTML. But the generated content is malformed if strings contain quotes. I’ve documented some examples here:

https://gist.github.com/paulrobertlloyd/dff85e8af0f039255760

This is the code for my custom tag:

module Jekyll
  class FigureTag < Liquid::Block
    def initialize(tag_name, markup, tokens)
      super
      @attributes = {}

      markup.scan(Liquid::TagAttributes) do |key, value|
        @attributes[key] = value.gsub(/^'|"/, '').gsub(/'|"$/, '')
      end
    end

    def render(context)
      site = context.registers[:site]
      converter = site.getConverterImpl(::Jekyll::Converters::Markdown)

      figure_classes = @attributes['class'].to_s
      figure_main = converter.convert(super(context))
      figure_caption = converter.convert(@attributes['caption'].to_s)

      # Render <figure>
      if @attributes['class']
        source = "<figure class=\"figure #{figure_classes}\">"
      else
        source = "<figure class=\"figure\">"
      end

      source += "<div class=\"figure__main\">#{figure_main}</div>"

      if @attributes['caption']
        source += "<figcaption class=\"figure__caption\">#{figure_caption}</figcaption>"
        source += "</figure>"
      else
        source += "</figure>"
      end
    end
  end
end

Liquid::Template.register_tag('figure', Jekyll::FigureTag)

Hope this makes sense!

pushrax commented 9 years ago

https://github.com/Shopify/liquid/issues/560 is relevant