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.newHaml::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)

或使用 truefalse

%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 可以協助產生具有這些前綴的屬性集合。dataaria 屬性雜湊中任何具有雜湊作為其值的項目都會擴充為一系列屬性,每個屬性對應雜湊中的一個金鑰/值對,屬性名稱是由「父層」金鑰名稱與金鑰名稱以連字號結合而成。這僅適用於 dataaria

例如

%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。它們用作分別指定元素的 classid 屬性的捷徑。可以透過將類別名稱與句點串連在一起的方式,指定多個類別名稱,類似於 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 來源中沒有內容,某些標籤會自動視為是空的。預設會將 metaimglinkbrhrinputareaparamcolbase 標籤視為是空的。可以透過設定 :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>'

會編譯成

&lt;script&gt;alert(&quot;I'm evil!&quot;);&lt;/script&gt;

= 也可以用在標籤的結尾,以在該標籤內插入 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&#x000A;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 &amp; crackers

如果設定 :escape_html 選項,&= 的行為將與 = 相同。

& 也可以單獨使用,這樣 #{} 插補就會被轉譯。例如,

& I like #{"cheese & crackers"}

編譯為

I like cheese &amp; crackers

取消轉譯 HTML:!=

一個驚嘆號後接一個或兩個等號會評估 Ruby 程式碼,就像等號一樣,但永遠不會清除 HTML。

預設情況下,單等號也不會清除 HTML。然而,如果設定 :escape_html 選項,= 將會清除 HTML,但 != 仍然不會。例如,如果設定 :escape_html

= "I feel <strong>!"
!= "I feel <strong>!"

編譯為

I feel &lt;strong&gt;!
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 縮排所有文字。例如,pretextarea 等標籤對空白很敏感;縮排文字會導致它們錯誤呈現。

Haml 透過在換行符號放入文件中之前「保留」它們來處理這個問題,並將它們轉換為 HTML 空白轉譯碼 &#x000A;。然後,Haml 就不會嘗試重新格式化縮排。

文字 textareapre 標籤會自動保留透過 = 提供的內容。動態產生的 textareapre 無法自動保留,因此應透過 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 ```