san*_*ark 5 ruby tags dry liquid jekyll
如果一个类有多个可选标记作为参数传入,是否可以嵌套用 ruby 编写的自定义 Liquid 标签?如果不提供相关示例,我很难描述这个问题。如果这个问题看起来过于具体,请原谅我。
给定以下来自 Octopress(一个 jekyll fork)的 ruby 代码,它创建了一个自定义 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)
Run Code Online (Sandbox Code Playgroud)
创建另一个自定义标记以展示 [ <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>
Run Code Online (Sandbox Code Playgroud)
假设可以嵌套自定义 Liquid 标签是错误的吗?我确信我可以再次重写现有代码并稍微修改它以处理 [ <figcaption>]的附加属性,但这似乎相当多余并且违反了 DRY 原则。就目前而言,鉴于现有类本身采用可选标记,我对如何考虑可能的附加标记感到困惑。
我需要做的是创建一个液体块,而不是一个液体标签。这个解决方案允许人们在理论上嵌套其他 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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1898 次 |
| 最近记录: |