2012-03-05 74 views
4

如果一個類有多個可選標記作爲參數傳入,是否可以嵌套用ruby編寫的自定義Liquid標籤?沒有提供相關示例,這個問題對我來說很難描述。請原諒,如果這個問題似乎太具體的用例。嵌套兩個具有可選參數的自定義液體標籤

鑑於以下ruby代碼來自Octopress(一個jekyll fork),它創建了一個定製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>]元素內,並且也許顯示圖像ALT描述或附加令牌作爲一個[<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 2012-03-05 22:47:47

回答

4

我需要做的是創建一個液體塊,而不是液體標籤。該解決方案允許人們在理論上嵌套其他液體標籤,甚至其他液體塊,這在圖中正是人們對標籤所期望的。

由於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)