如果一个类有多个可选的标记作为参数传入,是否可以嵌套用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!(/"/, '"') 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>
我认为可以嵌套自定义Liquid标签是错误的吗?我确信我可以再次重写现有代码并稍微修改它以处理[<figcaption>
]的附加属性,但这似乎是多余的并且与DRY原则相反。就目前情况而言,考虑到现有的类本身采用可选标记,我对如何考虑可能的额外标记感到困惑。
答案 0 :(得分:4)
我需要做的是创建一个Liquid Block,而不是Liquid Tag。这个解决方案允许人们在理论上嵌套其他Liquid标签甚至其他Liquid块,这正是人们对[<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)