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 hash,用於指定元素的屬性。它會逐字評估為一個 Ruby hash,因此邏輯會在其中運作,而且可以使用局部變數。屬性內的引號字元會被替換為適當的跳脫序列。hash 會在定義標籤後放置。例如
%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>
屬性 hash 也可以延伸到多行,以容納許多屬性。
%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}"}
陣列會先被扁平化,而且任何測試結果為 false 的元素都會被移除。剩下的元素會被轉換為字串。例如
%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 也支援基於 HTML 屬性的簡潔、較不特定於 Ruby 的屬性語法。這些語法會與大括號一起使用,如下所示
%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 版本會按字母順序對類別名稱進行排序。
空 (無效) 標籤:/
當正斜線字元放在標籤定義的結尾時,Haml 會將其視為空 (或無效) 元素。根據格式,標籤將在沒有閉合標籤 (: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 過渡
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
!!! 嚴格
- XHTML 1.0 嚴格
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
!!! 框架集
- XHTML 1.0 框架集
<!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">
!!! 基本
- XHTML 基本 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
!!! 行動
- XHTML 行動 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
時,支援下列 doctype
!!!
- HTML 4.01 過渡期
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
!!! 嚴格
- HTML 4.01 嚴格
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
!!! 框架集
- HTML 4.01 框架集
<!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 註解:/
當正斜線字元置於一行開頭時,會將其後的所有文字包覆在 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 等某些濾鏡的功能可由許多不同的函式庫提供。通常您不必擔心這一點,您只需載入您選擇的寶石,Haml 便會自動使用它。
然而,在某些情況下,您可能希望讓 Haml 明確使用特定寶石,以供濾鏡使用。在這些情況下,您可以透過 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 ```