2012-03-05 10 views
4

Можно ли встраивать пользовательские теги Liquid, написанные в ruby, если один класс имеет несколько необязательных токенов, прошедших в качестве параметров? Этот вопрос довольно сложно описать без предоставления соответствующего примера. Пожалуйста, извините меня, если этот вопрос представляется слишком конкретным вариантом использования.Вложение двух пользовательских тегов Liquid, которые имеют необязательные параметры

Учитывая следующий код ruby, полученный из Octopress (вилка jekyll), который создает пользовательский тег Liquid для разбора тегов.

# Title: Simple Image tag for Jekyll 
# Authors: Brandon Mathis http://brandonmathis.com 
#   Felix Schäfer, Frederic Hemberger 
# Description: Easily output images with optional class names, width, height, title and alt attributes 
# 
# Syntax {% img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | "title text" ["alt text"]] %} 
# 
# Examples: 
# {% img /images/ninja.png Ninja Attack! %} 
# {% img left half http://site.com/images/ninja.png Ninja Attack! %} 
# {% img left half http://site.com/images/ninja.png 150 150 "Ninja Attack!" "Ninja in attack posture" %} 
# 
# Output: 
# <img src="/images/ninja.png"> 
# <img class="left half" src="http://site.com/images/ninja.png" title="Ninja Attack!" alt="Ninja Attack!"> 
# <img class="left half" src="http://site.com/images/ninja.png" width="150" height="150" title="Ninja Attack!" alt="Ninja in attack posture"> 
# 

module Jekyll 

class ImageTag < Liquid::Tag 
    @img = nil 

    def initialize(tag_name, markup, tokens) 
    attributes = ['class', 'src', 'width', 'height', 'title'] 

    if markup =~ /(?<class>\S.*\s+)?(?<src>(?:https?:\/\/|\/|\S+\/)\S+)(?:\s+(?<width>\d+))?(?:\s+(?<height>\d+))?(?<title>\s+.+)?/i 
     @img = attributes.reduce({}) { |img, attr| img[attr] = $~[attr].strip if $~[attr]; img } 
     if /(?:"|')(?<title>[^"']+)?(?:"|')\s+(?:"|')(?<alt>[^"']+)?(?:"|')/ =~ @img['title'] 
     @img['title'] = title 
     @img['alt'] = alt 
     else 
     @img['alt'] = @img['title'].gsub!(/"/, '&#34;') if @img['title'] 
     end 
     @img['class'].gsub!(/"/, '') if @img['class'] 
    end 
    super 
    end 

    def render(context) 
    if @img 
     "<img #{@img.collect {|k,v| "#{k}=\"#{v}\"" if v}.join(" ")}>" 
    else 
     "Error processing input, expected syntax: {% img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | \"title text\" [\"alt text\"]] %}" 
    end 
    end 
end 
end 
Liquid::Template.register_tag('img', Jekyll::ImageTag) 

Что является лучшим способом, чтобы создать другой пользовательский тег для экспонирования той же функциональности для элемента [<img>], но вложенное в [<figure>] элемент и, возможно, отображая описание изображения альта или дополнительный маркер в виде [<figcaption>] элемент, который потенциально может содержать свою собственную ссылку? Или, возможно, даже ряд имен классов для элемента, который говорит, следует ли центрировать или нет.

Другими словами, я мог бы выход быть что-то вроде:

<figure class=center> 
    <img src="/contra.jpg" alt="One of the greatest nintendo games of all time"> 
    <figcaption>Up Up Down Down Left Right Left Right B A B A <a href="http://www.youtube.com/contramoves/">Watch on Youtube</a></figcaption> 
</figure> 

ли я неправильно полагать, что это возможно гнездо пользовательские Жидкие теги? Я уверен, что я мог бы переписать существующий код во второй раз и немного изменить его, чтобы обработать дополнительный атрибут для [<figcaption>], но это кажется излишним и против DRY-принципов. И по мере того как он в настоящее время стоит, я довольно смущен относительно того, как я могу объяснить возможный дополнительный токен, учитывая, что существующий класс принимает необязательно самих токенов.

+0

Если никто не хочет взломать его, может кто-нибудь, пожалуйста, посоветуйте, как я могу сделать вопрос более ясным хотя бы? Очень признателен! – saneshark

ответ

4

Что мне нужно было сделать, это создать жидкий блок, а не жидкий тег. Это решение позволяет в принципе фиксировать другие жидкие теги и даже другие жидкие блоки в пределах фигуры, что и следовало ожидать для метки [<figure>].

Поскольку Markdown в настоящее время не поддерживает HTML5, это решение на основе Liquid является хорошим компромиссом.

# Example: 
# 
# {% fig This is my caption! http://site.com/link.html Link Caption %} 
# {% img center http://site.com/images/mylinks.png A collection of my favorite links %} 
# {% endfig %} 
# 
# Output: 
# 
# <figure class='center'> 
# <img class="center" src="http://site.com/images/mylinks.png" title="A collection of my favorite links" > 
# <figcaption>This is my caption!<a href='http://site.com/link.html'>Link Caption </a></figcaption> 
#</figure> 
# 
# 

module Jekyll 

    class FigureTag < Liquid::Block 
    include TemplateWrapper 
    CaptionUrl = /(\S[\S\s]*)\s+(https?:\/\/\S+)\s+(.+)/i 
    Caption = /(\S[\S\s]*)/ 
    def initialize(tag_name, markup, tokens) 
     @title = nil 
     @caption = nil 
     if markup =~ CaptionUrl 
     @caption = "\n\t\t<figcaption>#{$1}<a href='#{$2}'>#{$3}</a></figcaption>\n\t" 
     elsif markup =~ Caption 
     @caption = "\n\t\t<figcaption>#{$1}</figcaption>\n\t" 
     end 
     super 
    end 

    def render(context) 
     output = super 
     fig = super.join 
     source = "\t<figure class='center'>\n\t\t" 
     markdown = RDiscount.new(fig.lstrip).to_html[/<p>(.+)<\/p>/i] 
     source += $1 
     source += @caption if @caption 
     source += "</figure>" 
     source = safe_wrap(source) 
     source 
    end 
    end 
end 

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