Haml (HTML 抽象标记语言)
Haml 是一种标记语言,用于简洁明了地描述任何网页文档的 HTML,无需使用内联代码。Haml 作为内联页面模板系统(如 PHP、ERB 和 ASP)的替代方案。但是,Haml 避免了在模板中显式编码 HTML 的需要,因为它实际上是 HTML 的抽象描述,带有一些用于生成动态内容的代码。
特性
- 空白符有效
- 格式良好的标记
- DRY
- 遵循 CSS 约定
- 集成 Ruby 代码
- 使用 .haml 扩展名实现 Rails 模板
使用 Haml
Haml 可以通过三种方式使用
- 作为命令行工具,
- 作为 Ruby on Rails 的插件,
- 以及作为独立的 Ruby 模块。
所有这些的第一步是安装 Haml gem
gem install haml
要从命令行运行 Haml,只需使用
haml render input.haml > output.html
使用 haml --help
获取完整文档。
要将 Haml 与 Rails 一起使用,请在 Gemfile 中添加以下行
gem "haml"
安装后,所有扩展名为 ".html.haml"
的视图文件都将使用 Haml 编译。
您可以在 Haml 模板中以与在 ERB 模板中相同的方式访问实例变量。辅助方法也适用于 Haml 模板。例如
# file: app/controllers/movies_controller.rb
class MoviesController < ApplicationController
def index
@title = "Teen Wolf"
end
end
-# file: app/views/movies/index.html.haml
#content
.title
%h1= @title
= link_to 'Home', home_url
可以编译为
<div id='content'>
<div class='title'>
<h1>Teen Wolf</h1>
<a href='/'>Home</a>
</div>
</div>
Ruby 模块
Haml 也可以完全独立于 Rails 和 ActionView 使用。为此,请使用 RubyGems 安装 gem
gem install haml
然后,您可以通过在 Ruby 代码中包含 haml
gem 并使用 Haml::Template 来使用它,如下所示
engine = Haml::Template.new { "%p Haml code!" }
engine.render #=> "<p>Haml code!</p>\n"
选项
Haml 理解各种配置选项,这些选项会影响其性能和输出。
在 Rails 中,可以通过在初始化程序中使用 Haml::RailsTemplate.set_options
来设置选项
ruby # config/initializers/haml.rb Haml::RailsTemplate.set_options(escape_html: false)
在 Rails 之外,您可以通过在 Haml::Template.options
中全局配置它们来设置它们
ruby Haml::Template.options[:escape_html] = false
特别是在 sinatra 中,您可以在全局配置中使用以下方式设置它们:ruby set :haml, { escape_html: false }
最后,您还可以通过将选项哈希传递给 Haml::Engine.new
或 Haml::Template.new
来设置它们。有关可用选项的完整列表,请参阅 Haml::Engine
。
纯文本
任何 HTML 文档的很大一部分是其内容,即纯文本。任何不被解释为其他内容的 Haml 行都被视为纯文本,并直接传递。例如
%gee
%whiz
Wow this is cool!
编译成
<gee>
<whiz>
Wow this is cool!
</whiz>
</gee>
请注意,HTML 标签也会直接传递。如果您有一些不想转换为 Haml 的 HTML,或者您正在逐行转换文件,您可以直接包含它。例如
%p
<div id="blah">Blah!</div>
编译成
<p>
<div id="blah">Blah!</div>
</p>
转义:\
反斜杠字符转义了行的第一个字符,允许将原本被解释的字符用作纯文本。例如
%title
= @title
\= @title
编译成
<title>
MyPage
= @title
</title>
HTML 元素
元素名称:%
百分号字符放在行的开头。它后面紧跟着元素的名称,然后可选地跟着修饰符(见下文)、一个空格,以及要在元素内渲染的文本。它创建了一个形式为<element></element>
的元素。例如
%one
%two
%three Hey there
编译成
<one>
<two>
<three>Hey there</three>
</two>
</one>
任何字符串都是有效的元素名称;Haml 将自动为任何元素生成开始和结束标签。
属性:{}
或 ()
大括号表示一个 Ruby 哈希,用于指定元素的属性。它实际上被评估为一个 Ruby 哈希,因此逻辑将在其中起作用,并且可以使用局部变量。属性中的引号字符将被替换为适当的转义序列。哈希放在定义标签之后。例如
%html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en"}
编译成
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'></html>
属性哈希也可以扩展到多行以容纳许多属性。
%script{
"type": text/javascript",
"src": javascripts/script_#{2 + 7}",
"data": {
"controller": "reporter",
},
}
编译成
<script src='javascripts/script_9' type='text/javascript' data-controller='reporter'></script>
:class
和 :id
属性
:class
和 :id
属性也可以指定为一个 Ruby 数组,其元素将被连接在一起。一个 :class
数组用 " "
连接,一个 :id
数组用 "_"
连接。例如
%div{:id => [@item.type, @item.number], :class => [@item.type, @item.urgency]}
等同于
%div{:id => "#{@item.type}_#{@item.number}", :class => "#{@item.type} #{@item.urgency}"}
数组将首先被扁平化,任何不测试为真的元素将被删除。剩余的元素将被转换为字符串。例如
%div{:class => [@item.type, @item == @sortcol && [:sort, @sortdir]] } Contents
可以渲染为以下任何一种
<div class="numeric sort ascending">Contents</div>
<div class="numeric">Contents</div>
<div class="sort descending">Contents</div>
<div>Contents</div>
取决于 @item.type
是否为 "numeric"
或 nil
,@item
是否等于 @sortcol
,以及 @sortdir
是否为 "ascending"
或 "descending"
。
如果指定单个值并且它评估为 false,则它将被忽略;否则它将被转换为字符串。例如
.item{:class => @item.is_empty? && "empty"}
可以渲染成以下两种形式:
class="item"
class="item empty"
HTML 风格属性:()
Haml 还支持一种更简洁、更少 Ruby 特定的属性语法,它基于 HTML 的属性。这些属性使用圆括号而不是花括号,如下所示
%html(xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en")
可以通过省略引号来使用 Ruby 变量。可以使用局部变量或实例变量。例如
%a(title=@title href=href) Stuff
这与以下代码相同:
%a{:title => @title, :href => href} Stuff
但是,由于没有逗号分隔属性,因此不允许使用更复杂的表达式。对于这些表达式,您必须使用 {}
语法。但是,您可以将两种语法一起使用
%a(title=@title){:href => @link.href} Stuff
您也可以使用 #{}
插值在 HTML 风格属性中插入复杂的表达式
%span(class="widget_#{@widget.number}")
HTML 风格属性可以像哈希风格属性一样跨多行扩展
%script(type="text/javascript"
src="javascripts/script_#{2 + 7}")
Ruby 1.9 风格的哈希
Haml 还支持 Ruby 的新哈希语法
%a{title: @title, href: href} Stuff
布尔属性
某些属性,例如 input
标签的“checked”或 option
标签的“selected”,在某种意义上是“布尔”的,因为它们的实际值并不重要,重要的是它们是否存在。在 HTML(但不是 XHTML)中,这些属性可以写成
<input selected>
要在 Haml 中使用哈希风格属性执行此操作,只需将 Ruby true
值分配给该属性
%input{:selected => true}
在 XHTML 中,这些属性的唯一有效值为属性名称。因此,这将在 XHTML 中渲染为
<input selected='selected'>
要将这些属性设置为 false,只需将它们分配给 Ruby false 值。在 XHTML 和 HTML 中,
%input{:selected => false}
将只渲染为
<input>
HTML 风格的布尔属性可以像 HTML 一样编写
%input(selected)
或使用 true
和 false
%input(selected=true)
此功能仅适用于包含在 Haml::AttributeBuilder::BOOLEAN_ATTRIBUTES
中的属性,以及 data-
和 aria-
属性。
%input{'data-hidden' => false}
%input{'aria-hidden' => false}
%input{'xyz-hidden' => false}
将渲染为
<input>
<input>
<input xyz-hidden='false'>
数据属性
HTML5 允许使用以 data-
开头的属性名称将 自定义不可见数据属性 添加到元素。 可访问的富互联网应用程序 规范使用以 aria-
开头的属性。
Haml 可以帮助生成具有相同前缀的属性集合,例如这些。data
或 aria
属性哈希中任何具有哈希值作为其值的条目都会扩展为一系列属性,每个键值对在哈希中对应一个属性,属性名称通过将“父”键名与键名连接起来形成,中间用连字符隔开。这仅适用于 data
或 aria
。
例如
%a{:href=>"/posts", :data => {:author_id => 123, :category => 7}} Posts By Author
将渲染为
<a data-author-id='123' data-category='7' href='/posts'>Posts By Author</a>
注意,author_id
中的下划线被替换为连字符。如果您希望抑制此行为,可以将 Haml 的 :hyphenate_data_attrs
选项设置为 false
,输出将呈现为
<a data-author_id='123' data-category='7' href='/posts'>Posts By Author</a>
哈希的这种扩展是递归的 - 子哈希的任何值为哈希本身都会为每个条目创建一个属性,属性名称以所有祖先键为前缀。例如
.book-info{:data => {:book => {:id => 123, :genre => 'programming'}, :category => 7}}
将渲染为
<div class='book-info' data-book-genre='programming' data-book-id='123' data-category='7'></div>
类和 ID:.
和 #
句点和井号借鉴自 CSS。它们用作分别指定元素的 class
和 id
属性的快捷方式。多个类名可以以类似于 CSS 的方式指定,通过将类名用句点连接在一起。它们放置在标签之后和属性哈希之前。例如
%div#things
%span#rice Chicken Fried
%p.beans{ :food => 'true' } The magical fruit
%h1.class.otherclass#id La La La
编译成
<div id='things'>
<span id='rice'>Chicken Fried</span>
<p class='beans' food='true'>The magical fruit</p>
<h1 class='class otherclass' id='id'>La La La</h1>
</div>
以及,
%div#content
%div.articles
%div.article.title Doogie Howser Comes Out
%div.article.date 2006-11-05
%div.article.entry
Neil Patrick Harris would like to dispel any rumors that he is straight
编译成
<div id='content'>
<div class='articles'>
<div class='article title'>Doogie Howser Comes Out</div>
<div class='article date'>2006-11-05</div>
<div class='article entry'>
Neil Patrick Harris would like to dispel any rumors that he is straight
</div>
</div>
</div>
这些快捷方式可以与长格式属性结合使用;这两个值将合并在一起,就像它们都放在数组中一样(参见 关于 :class
和 :id
属性的文档)。例如
%div#Article.article.entry{:id => @article.number, :class => @article.visibility}
等同于
%div{:id => ['Article', @article.number], :class => ['article', 'entry', @article.visibility]} Gabba Hey
并可能编译为
<div class="article entry visible" id="Article_27">Gabba Hey</div>
隐式 Div 元素
由于 div 的使用非常频繁,因此它们是默认元素。如果您只使用 .
或 #
定义类和/或 id,则会自动使用 div。例如
#collection
.item
.description What a cool item!
与
%div#collection
%div.item
%div.description What a cool item!
相同,并编译为
<div id='collection'>
<div class='item'>
<div class='description'>What a cool item!</div>
</div>
</div>
类名合并和排序
类名按以下方式排序
1) 标签标识符按顺序(即,“.alert.me” => “alert me”) 2) 出现在 HTML 样式属性中的类 3) 出现在哈希样式属性中的类
例如,这是一个复杂的、不直观的测试用例,说明了排序
.foo.moo{:class => ['bar', 'alpha']}(class='baz')
生成的 HTML 如下所示
<div class='foo moo baz bar alpha'></div>
5.0 之前的 Haml 版本会按字母顺序排序类名。
空(void)标签:/
在标签定义的末尾放置正斜杠字符,会导致 Haml 将其视为空(或 void)元素。根据格式,标签将以不带结束标签的方式呈现(:html4
或 :html5
),或以自闭合标签的方式呈现(:xhtml
)。
以下示例
%br/
%meta{'http-equiv' => 'Content-Type', :content => 'text/html'}/
当格式为 :html4
或 :html5
时,编译为
<br>
<meta content='text/html' http-equiv='Content-Type'>
当格式为 :xhtml
时,编译为
<br />
<meta content='text/html' http-equiv='Content-Type' />
某些标签会自动被视为空标签,只要它们在 Haml 源代码中没有内容。meta
、img
、link
、br
、hr
、input
、area
、param
、col
和 base
标签默认被视为空标签。此列表可以通过设置 :autoclose
选项进行自定义。
空白符移除:>
和 <
>
和 <
可以让你更好地控制标签附近的空白符。>
会移除标签周围的所有空白符,而 <
会移除标签内部的所有空白符。你可以将它们想象成吃掉空白符的鳄鱼:>
面向标签外部,吃掉外部的空白符,而 <
面向标签内部,吃掉内部的空白符。它们放在标签定义的末尾,在类、id 和属性声明之后,但在 /
或 =
之前。例如
%blockquote<
%div
Foo!
编译成
<blockquote><div>
Foo!
</div></blockquote>
以及
%img
%img>
%img
编译成
<img /><img /><img />
以及
%p<= "Foo\nBar"
编译成
<p>Foo
Bar</p>
最后
%img
%pre><
foo
bar
%img
编译成
<img /><pre>foo
bar</pre><img />
对象引用:[]
方括号紧跟在标签定义之后,包含一个用于设置该标签的类和 id 的 Ruby 对象。类被设置为对象的类(转换为使用下划线而不是驼峰式命名法),id 被设置为对象的类,后面跟着其 #to_key
或 #id
方法的值(按此顺序)。这对表示 Active Model 模型实例的元素最有用。此外,第二个参数(如果存在)将用作 id 和类属性的前缀。例如
# file: app/controllers/users_controller.rb
def show
@user = CrazyUser.find(15)
end
-# file: app/views/users/show.haml
%div[@user, :greeting]
%bar[290]/
Hello!
编译成
<div class='greeting_crazy_user' id='greeting_crazy_user_15'>
<bar class='fixnum' id='fixnum_581' />
Hello!
</div>
如果你需要将类设置为除下划线形式的对象类以外的其他值,可以在对象上实现 haml_object_ref
方法。
# file: app/models/crazy_user.rb
class CrazyUser < ActiveRecord::Base
def haml_object_ref
"a_crazy_user"
end
end
-# file: app/views/users/show.haml
%div[@user]
Hello!
编译成
<div class='a_crazy_user' id='a_crazy_user_15'>
Hello!
</div>
:class
属性可以与对象引用一起使用。编译后的元素将包含所有类的并集。
- user = User.find(1)
%p[user]{:class => 'alpha bravo'}
<p id="user_1" class="alpha bravo user"></p>
文档类型:!!!
使用 Haml 描述 HTML 文档时,可以通过包含字符 !!!
来自动生成文档类型或 XML 前言。例如
!!! XML
!!!
%html
%head
%title Myspace
%body
%h1 I am the international space station
%p Sign my guestbook
编译成
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Myspace</title>
</head>
<body>
<h1>I am the international space station</h1>
<p>Sign my guestbook</p>
</body>
</html>
当 :format
设置为 :xhtml
时,您也可以在 !!!
后指定特定的文档类型。支持以下文档类型
!!!
- XHTML 1.0 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
!!! Strict
- XHTML 1.0 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
!!! Frameset
- XHTML 1.0 Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
!!! 5
- XHTML 5
<!DOCTYPE html>
!!! 1.1
- XHTML 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
!!! Basic
- XHTML Basic 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
!!! Mobile
- XHTML Mobile 1.2
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
!!! RDFa
- XHTML+RDFa 1.0
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
当 :format
选项设置为 :html4
时,支持以下文档类型
!!!
- HTML 4.01 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
!!! Strict
- HTML 4.01 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
!!! Frameset
- HTML 4.01 Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
当 :format
选项设置为 :html5
时,!!!
始终为 <!DOCTYPE html>
。
如果您没有为文档使用 UTF-8 字符集,则可以以类似的方式指定 XML 前言中应出现的编码。例如
!!! XML iso-8859-1
编译成
<?xml version='1.0' encoding='iso-8859-1' ?>
如果正在渲染的模板的 mime_type 为 text/xml
,则即使全局输出格式设置为 :html4
或 :html5
,也会使用 :xhtml
格式。
注释
Haml 支持两种类型的注释:显示在 HTML 输出中的注释和不显示的注释。
HTML 注释:/
当正斜杠字符放在行首时,它会将它之后的所有文本包装在 HTML 注释中。例如
%peanutbutterjelly
/ This is the peanutbutterjelly element
I like sandwiches!
编译成
<peanutbutterjelly>
<!-- This is the peanutbutterjelly element -->
I like sandwiches!
</peanutbutterjelly>
正斜杠也可以用来包裹缩进的代码段。例如
/
%p This doesn't render...
%div
%h1 Because it's commented out!
编译成
<!--
<p>This doesn't render...</p>
<div>
<h1>Because it's commented out!</h1>
</div>
-->
条件注释:/[]
您也可以使用 Internet Explorer 条件注释,方法是在 /
后面的方括号中包含条件。例如
/[if IE]
%a{ :href => 'http://www.mozilla.com/en-US/firefox/' }
%h1 Get Firefox
编译成
<!--[if IE]>
<a href='http://www.mozilla.com/en-US/firefox/'>
<h1>Get Firefox</h1>
</a>
<![endif]-->
要生成“向下级显示”条件注释,其中内容对 IE 隐藏,但对其他浏览器不隐藏,请在方括号之前添加 !
:/![]
。Haml 在生成此类条件注释时将生成有效的 HTML。
例如
/![if !IE]
You are not using Internet Explorer, or are using version 10+.
编译成
<!--[if !IE]><!-->
You are not using Internet Explorer, or are using version 10+.
<!--<![endif]-->
Haml 注释:-#
连字符后紧跟井号表示静默注释。此后的任何文本都不会在生成的文档中呈现。
例如
%p foo
-# This is a comment
%p bar
编译成
<p>foo</p>
<p>bar</p>
您也可以在静默注释下方嵌套文本。所有这些文本都不会被渲染。例如
%p foo
-#
This won't be displayed
Nor will this
Nor will this.
%p bar
编译成
<p>foo</p>
<p>bar</p>
Ruby 评估
插入 Ruby:=
等号后跟 Ruby 代码。此代码将被评估,输出将插入文档中。例如
%p
= ['hi', 'there', 'reader!'].join " "
= "yo"
编译成
<p>
hi there reader!
yo
</p>
如果设置了 :escape_html
选项,=
将对脚本生成的任何 HTML 敏感字符进行清理。例如
= '<script>alert("I\'m evil!");</script>'
将编译为
<script>alert("I'm evil!");</script>
=
也可以用在标签的末尾,以在该标签内插入 Ruby 代码。例如
%p= "hello"
将编译为
<p>hello</p>
只要除了最后一行之外的每一行都以逗号结尾,Ruby 代码行就可以跨越多行。例如
= link_to_remote "Add to cart",
:url => { :action => "add", :id => product.id },
:update => { :success => "cart", :failure => "error" }
请注意,在以 =
结尾的标签内嵌套代码是非法的。
运行 Ruby:-
连字符后也跟 Ruby 代码。此代码将被评估,但不会插入文档中。
不建议您广泛使用此功能;几乎所有处理代码和逻辑都应限制在控制器、助手或局部视图中。
例如
- foo = "hello"
- foo << " there"
- foo << " you!"
%p= foo
编译成
<p>
hello there you!
</p>
只要除了最后一行之外的每一行都以逗号结尾,Ruby 代码行就可以跨越多行。例如
- links = {:home => "/",
:docs => "/docs",
:about => "/about"}
Ruby 块
Ruby 块与 XHTML 标签一样,不需要在 Haml 中显式关闭。相反,它们会根据缩进自动关闭。只要在 Ruby 评估命令之后缩进增加,块就会开始。当缩进减少时,块就会结束(只要它不是 else
子句或类似内容)。例如
- (42...47).each do |i|
%p= i
%p See, I can count!
编译成
<p>42</p>
<p>43</p>
<p>44</p>
<p>45</p>
<p>46</p>
<p>See, I can count!</p>
另一个例子
%p
- case 2
- when 1
= "1!"
- when 2
= "2?"
- when 3
= "3."
编译成
<p>
2?
</p>
保留空格:~
~
的工作方式与 =
相同,只是它对输入运行 Haml::Helpers.preserve。例如,
~ "Foo\n<pre>Bar\nBaz</pre>"
与
= find_and_preserve("Foo\n<pre>Bar\nBaz</pre>")
相同,并编译为
Foo
<pre>Bar
Baz</pre>
另请参见 保留空格。
Ruby 插值:#{}
Ruby 代码也可以使用 #{}
在纯文本中进行插值,类似于 Ruby 字符串插值。例如,
%p This is #{h quality} cake!
与
%p= "This is #{h quality} cake!"
并可能编译为
<p>This is scrumptious cake!</p>
可以使用反斜杠来转义 #{}
字符串,但它们在字符串中的其他任何地方都不会充当转义符。例如
%p
Look at \\#{h word} lack of backslash: \#{foo}
And yon presence thereof: \{foo}
可能编译成
<p>
Look at \yon lack of backslash: #{foo}
And yon presence thereof: \{foo}
</p>
插值也可以在 过滤器 中使用。例如
:javascript
$(document).ready(function() {
alert(#{@message.to_json});
});
可能编译成
<script type='text/javascript'>
//<![CDATA[
$(document).ready(function() {
alert("Hi there!");
});
//]]>
</script>
注意事项
Haml 使用一个过于简单的正则表达式来识别字符串插值,而不是一个完整的 Ruby 解析器。这很快,并且适用于大多数代码,但你可能会在以下代码中遇到错误
%span #{'{'}
这段代码将生成语法错误,抱怨括号不平衡。在这种情况下,推荐的解决方法是将代码作为 Ruby 字符串输出,以强制 Haml 使用 Ruby 解析代码。
%span= "#{'{'}"
转义 HTML:&=
一个与号后面跟着一个或两个等号,就像没有与号的等号一样,会评估 Ruby 代码,但会对代码结果中任何对 HTML 敏感的字符进行清理。例如
&= "I like cheese & crackers"
编译成
I like cheese & crackers
如果设置了 :escape_html
选项,&=
的行为与 =
相同。
&
也可以单独使用,以便对 #{}
插值进行转义。例如,
& I like #{"cheese & crackers"}
编译成
I like cheese & crackers
取消转义 HTML:!=
一个感叹号后面跟着一个或两个等号,就像等号一样,会评估 Ruby 代码,但永远不会对 HTML 进行清理。
默认情况下,单个等号也不会对 HTML 进行清理。但是,如果设置了 :escape_html
选项,=
将清理 HTML,但 !=
仍然不会。例如,如果设置了 :escape_html
= "I feel <strong>!"
!= "I feel <strong>!"
编译成
I feel <strong>!
I feel <strong>!
!
也可以单独使用,以便对 #{}
插值进行取消转义。例如,
! I feel #{"<strong>"}!
编译成
I feel <strong>!
过滤器
冒号字符表示一个过滤器。这允许你将一个缩进的文本块作为输入传递给另一个过滤程序,并将结果添加到 Haml 的输出中。语法很简单,就是一个冒号后面跟着过滤器的名称。例如
%p
:markdown
# Greetings
Hello, *World*
编译成
<p>
<h1>Greetings</h1>
<p>Hello, <em>World</em></p>
</p>
过滤器可以使用 #{}
对 Ruby 代码进行插值。例如
- flavor = "raspberry"
#content
:textile
I *really* prefer _#{flavor}_ jam.
编译成
<div id='content'>
<p>I <strong>really</strong> prefer <em>raspberry</em> jam.</p>
</div>
一些过滤器的功能,例如 Markdown,可以由许多不同的库提供。通常你不需要担心这个问题 - 你只需加载你选择的 gem,Haml 就会自动使用它。
但是,在某些情况下,你可能希望 Haml 明确使用一个特定的 gem 来被过滤器使用。在这种情况下,你可以通过 Tilt 来实现,Tilt 是 Haml 用于实现其许多过滤器的库
Tilt.prefer Tilt::RedCarpetTemplate
有关更多信息,请参阅 Tilt 文档。
Haml 附带了以下定义的过滤器
:cdata
用 CDATA 标签包围过滤后的文本。
:coffee
使用 CoffeeScript 将过滤后的文本编译成 JavaScript,并放在 <script>
标签中。你也可以将此过滤器引用为 :coffeescript
。此过滤器使用 Tilt 实现。
:css
将过滤后的文本用 `<style>` 标签(可选)和 CDATA 标签包围。这对于包含内联 CSS 很有用。使用 `:cdata` 选项控制何时添加 CDATA 标签。
:erb
使用 ERB 解析过滤后的文本,就像 RHTML 模板一样。如果 `:suppress_eval` 选项设置为 true,则不可用。嵌入的 Ruby 代码在与 Haml 模板相同的上下文中进行评估。此过滤器使用 Tilt 实现。
:escaped
与 plain 相同,但在将文本放入文档之前对其进行 HTML 转义。
:javascript
将过滤后的文本用 `<script>` 标签(可选)和 CDATA 标签包围。这对于包含内联 Javascript 很有用。使用 `:cdata` 选项控制何时添加 CDATA 标签。
:less
使用 Less 解析过滤后的文本,以在 `<style>` 标签中生成 CSS 输出。此过滤器使用 Tilt 实现。
:markdown
使用 Markdown 解析过滤后的文本。此过滤器使用 Tilt 实现。
:maruku
使用 Maruku 解析过滤后的文本,它对 Markdown 有一些非标准扩展。
从 Haml 4.0 开始,此过滤器在 Haml contrib 中定义,但出于历史原因会自动加载。在 Haml 的未来版本中,它可能不会默认加载。此过滤器使用 Tilt 实现。
:plain
不解析过滤后的文本。这对于没有 HTML 标签的大块文本很有用,当您不希望以 `.` 或 `-` 开头的行被解析时。
:preserve
将过滤后的文本插入模板中,保留空格。`preserve` 的文本块不会缩进,换行符将被替换为换行符的 HTML 转义代码,以保留美观的输出。另请参见 空格保留。
:ruby
使用正常的 Ruby 解释器解析过滤后的文本。Ruby 代码在与 Haml 模板相同的上下文中进行评估。
:sass
使用 Sass 解析过滤后的文本,以在 `<style>` 标签中生成 CSS 输出。此过滤器使用 Tilt 实现。
:scss
使用 Sass 解析过滤后的文本,就像 `:sass` 过滤器一样,但使用较新的 SCSS 语法在 `<style>` 标签中生成 CSS 输出。此过滤器使用 Tilt 实现。
:textile
使用 Textile 解析过滤后的文本。仅当安装了 RedCloth 时才有效。
从 Haml 4.0 开始,此过滤器在 Haml contrib 中定义,但出于历史原因会自动加载。在 Haml 的未来版本中,它可能不会默认加载。此过滤器使用 Tilt 实现。
自定义过滤器
您也可以定义自己的过滤器。`Haml::Filters::YourCustomFilter#compile` 应该返回 一个 Temple 表达式。
过滤器最简单的例子可能类似于
class HelloFilter < Haml::Filters::Base
def compile(_node)
[:static, "hello world"]
end
end
Haml::Filters.registered[:hello] ||= HelloFilter
一个更复杂的例子
class BetterFilter < Haml::Filters::Base
def compile(node)
temple = [:multi]
temple << [:static, "hello "]
temple << compile_text(node.value[:text])
temple << [:static, " world"]
temple
end
private
def compile_text(text)
if ::Haml::Util.contains_interpolation?(text)
[:dynamic, ::Haml::Util.unescape_interpolation(text)]
else
[:static, text]
end
end
end
Haml::Filters.registered[:better] ||= BetterFilter
参见 Haml::Filters 获取示例。
多行:|
管道字符表示多行字符串。它放置在行尾(在一些空格之后),表示所有以|
结尾的后续行将被视为在同一行上。注意,即使多行块中的最后一行也应该以|
结尾。 例如
%whoo
%hoo= h( |
"I think this might get " + |
"pretty long so I should " + |
"probably make it " + |
"multiline so it doesn't " + |
"look awful.") |
%p This is short.
编译成
<whoo>
<hoo>I think this might get pretty long so I should probably make it multiline so it doesn't look awful.</hoo>
<p>This is short</p>
</whoo>
在 Haml 中使用多行声明是故意很麻烦的。这是为了阻止人们在 Haml 模板中放置大量 Ruby 代码。如果你发现自己使用多行声明,请停下来思考:我可以用助手更好地完成这件事吗?
请注意,在某些情况下,允许某些内容以非尴尬的方式流到多行上是有用的。其中之一是 HTML 属性。某些元素只是有很多属性,因此你可以包装属性而无需使用|
(参见 属性)。
此外,有时你需要调用 Ruby 方法或声明需要大量模板信息的数据结构。因此,需要大量参数的数据结构和函数可以跨多行包装,只要除最后一行以外的每一行都以逗号结尾(参见 插入 Ruby)。
保留空格
有时你不想让 Haml 缩进所有文本。例如,pre
和 textarea
等标签对空格敏感;缩进文本会导致它们渲染错误。
Haml 通过在将换行符放入文档之前“保留”它们来处理这个问题 - 将它们转换为 HTML 空格转义代码

。然后 Haml 不会尝试重新格式化缩进。
文字textarea
和 pre
标签会自动保留通过=
给出的内容。动态生成的textarea
和 pre
无法自动保留,因此应该通过 Haml::Helpers.preserve 或 ~
命令 传递,它们具有相同的效果。
可以使用 :preserve
过滤器 保留文字块。
Turbo
对于使用 Turbo-rails 的用户,需要执行以下操作之一:* 遵循 HTML 格式的命名约定(例如,确保所有 .haml
文件以 .html.haml
结尾),或者 * 添加以下猴子补丁
```rb # config/initializers/haml.rb require “haml/rails_template”
module Haml class RailsTemplate def default_format :html end end end ```