動作檢視文字輔助程式
TextHelper
模組提供一組用於過濾、格式化和轉換字串的方法,這些方法可以減少檢視中內嵌 Ruby 程式碼的數量。這些輔助方法擴充了動作檢視,讓您可以在範本檔案內呼叫這些方法。
清理
大多數產生 HTML 輸出的文字輔助程式在預設情況下會清理指定的輸入,但不會逸出輸入。這表示 HTML 標籤會顯示在頁面上,但所有惡意程式碼都會被移除。讓我們來看幾個使用 simple_format
方法的範例
simple_format('<a href="http://example.com/">Example</a>')
# => "<p><a href=\"http://example.com/\">Example</a></p>"
simple_format('<a href="javascript:alert(\'no!\')">Example</a>')
# => "<p><a>Example</a></p>"
如果您想要逸出所有內容,您應該在呼叫文字輔助程式之前呼叫 h
方法。
simple_format h('<a href="http://example.com/">Example</a>')
# => "<p><a href=\"http://example.com/\">Example</a></p>"
- C
- E
- H
- P
- R
- S
- T
- W
- ActionView::Helpers::SanitizeHelper
- ActionView::Helpers::TagHelper
- ActionView::Helpers::OutputSafetyHelper
實例公開方法
concat(string) 連結
在檢視中輸出品示的首選方法是使用 <%= "text" %>
eRuby 語法。一般的 puts
和 print
方法無法在 eRuby 程式碼區塊中預期的運作。如果您真的必須要在非輸出程式碼區塊中 (即 <% %>
) 輸出品示,您可以使用 concat
方法。
<% concat "hello" %> is equivalent to <%= "hello" %>
<%
unless signed_in?
concat link_to("Sign In", action: :sign_in)
end
%>
is equivalent to
<% unless signed_in? %>
<%= link_to "Sign In", action: :sign_in %>
<% end %>
來源: 顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 63 def concat(string) output_buffer << string end
current_cycle(name = "default") 連結
在週期開始後,傳回當前的週期字串。對複雜的表格底色或其他在多個位置需要當前週期字串的設計需求而言非常有用。
<%# Alternate background colors %>
<% @items = [1,2,3,4] %>
<% @items.each do |item| %>
<div style="background-color:<%= cycle("red","white","blue") %>">
<span style="background-color:<%= current_cycle %>"><%= item %></span>
</div>
<% end %>
來源: 顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 454 def current_cycle(name = "default") cycle = get_cycle(name) cycle.current_value if cycle end
cycle(first_value, *values) 連結
建立一個週期物件,其 to_s
方法每次呼叫時會在陣列的元素中循環。例如,這可以用在表格列的交替類別。您可以使用命名週期來允許在迴圈中嵌套。傳遞一個具有 :name
鍵的
作為最後一個參數,將會建立一個命名週期。沒有 Hash
:name
鍵的週期預設名稱為 "default"
。您可以手動透過呼叫 reset_cycle
並傳遞週期的名稱來重設週期。可以在任何時候使用 current_cycle
方法來取得目前的週期字串。
<%# Alternate CSS classes for even and odd numbers... %>
<% @items = [1,2,3,4] %>
<table>
<% @items.each do |item| %>
<tr class="<%= cycle("odd", "even") -%>">
<td><%= item %></td>
</tr>
<% end %>
</table>
<%# Cycle CSS classes for rows, and text colors for values within each row %>
<% @items = [
{ first: "Robert", middle: "Daniel", last: "James" },
{ first: "Emily", middle: "Shannon", maiden: "Pike", last: "Hicks" },
{ first: "June", middle: "Dae", last: "Jones" },
] %>
<% @items.each do |item| %>
<tr class="<%= cycle("odd", "even", name: "row_class") -%>">
<td>
<% item.values.each do |value| %>
<%# Create a named cycle "colors" %>
<span style="color:<%= cycle("red", "green", "blue", name: "colors") -%>">
<%= value %>
</span>
<% end %>
<% reset_cycle("colors") %>
</td>
</tr>
<% end %>
來源: 顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 430 def cycle(first_value, *values) options = values.extract_options! name = options.fetch(:name, "default") values.unshift(*first_value) cycle = get_cycle(name) unless cycle && cycle.values == values cycle = set_cycle(name, Cycle.new(*values)) end cycle.to_s end
excerpt(text, phrase, options = {}) 連結
從 `text` 中擷取 `phrase` 第一次出現以及周圍文字。如果結果的開始或結束不與 `text` 的開始或結束一致,則會加上或附加省略標記。結果始終都會去除。如果找不到 `phrase`,則回傳 `nil`。
選項
:radius
-
包含在結果中的 `phrase` 周圍字元(或代碼 — 請參閱 `:separator` 選項)的數量。預設為 100。
:omission
-
當節錄的開始或結束不與 `text` 的開始或結束一致時,要加上或附加的標記。預設為
"..."
。 :separator
-
用於計算 `:radius` 的代碼之間的分隔符號。預設為
""
,將每個字元當成一個代碼。
範例
excerpt('This is an example', 'an', radius: 5)
# => "...s is an exam..."
excerpt('This is an example', 'is', radius: 5)
# => "This is a..."
excerpt('This is an example', 'is')
# => "This is an example"
excerpt('This next thing is an example', 'ex', radius: 2)
# => "...next..."
excerpt('This is also an example', 'an', radius: 8, omission: '<chop> ')
# => "<chop> is also an example"
excerpt('This is a very beautiful morning', 'very', separator: ' ', radius: 1)
# => "...a very beautiful..."
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 235 def excerpt(text, phrase, options = {}) return unless text && phrase separator = options.fetch(:separator, nil) || "" case phrase when Regexp regex = phrase else regex = /#{Regexp.escape(phrase)}/i end return unless matches = text.match(regex) phrase = matches[0] unless separator.empty? text.split(separator).each do |value| if value.match?(regex) phrase = value break end end end first_part, second_part = text.split(phrase, 2) prefix, first_part = cut_excerpt_part(:first, first_part, separator, options) postfix, second_part = cut_excerpt_part(:second, second_part, separator, options) affix = [first_part, separator, phrase, separator, second_part].join.strip [prefix, affix, postfix].join end
highlight(text, phrases, options = {}, &block) 連結
透過使用反光標示字串來反光標示 `text` 中 `phrases` 的出現。`phrases` 可以是一個或多個字串或正規表示式。結果會標記為 HTML 安全。預設情況下,`text` 會在反光標示前先進行清理,以防止可能的 XSS 攻擊。
如果指定一個區塊,它將用於取代反光標示字串。phrase 的每個出現都會傳遞到該區塊,而其回傳值會插入到最終結果中。
選項
:highlighter
-
反光標示字串。使用 `\1` 作為 phrase 的佔位符,類似於 +String#sub+。預設為
"<mark>\1</mark>"
。如果指定一個區塊,這個選項將會被忽略。 :sanitize
-
是否在反光標示之前清理 `text`。預設為 true。
範例
highlight('You searched for: rails', 'rails')
# => "You searched for: <mark>rails</mark>"
highlight('You searched for: rails', /for|rails/)
# => "You searched <mark>for</mark>: <mark>rails</mark>"
highlight('You searched for: ruby, rails, dhh', 'actionpack')
# => "You searched for: ruby, rails, dhh"
highlight('You searched for: rails', ['for', 'rails'], highlighter: '<em>\1</em>')
# => "You searched <em>for</em>: <em>rails</em>"
highlight('You searched for: rails', 'rails', highlighter: '<a href="search?q=\1">\1</a>')
# => "You searched for: <a href=\"search?q=rails\">rails</a>"
highlight('You searched for: rails', 'rails') { |match| link_to(search_path(q: match)) }
# => "You searched for: <a href=\"search?q=rails\">rails</a>"
highlight('<a href="javascript:alert(\'no!\')">ruby</a> on rails', 'rails', sanitize: false)
# => "<a href=\"javascript:alert('no!')\">ruby</a> on <mark>rails</mark>"
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 174 def highlight(text, phrases, options = {}, &block) text = sanitize(text) if options.fetch(:sanitize, true) if text.blank? || phrases.blank? text || "" else patterns = Array(phrases).map { |phrase| Regexp === phrase ? phrase : Regexp.escape(phrase) } pattern = /(#{patterns.join("|")})/i highlighter = options.fetch(:highlighter, '<mark>\1</mark>') unless block text.scan(/<[^>]*|[^<]+/).each do |segment| if !segment.start_with?("<") if block segment.gsub!(pattern, &block) else segment.gsub!(pattern, highlighter) end end end.join end.html_safe end
pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale) 連結
除非 `count` 為 1,否則嘗試將 `singular` 字詞複數化。如果提供了 `plural`,當 count > 1 時會使用它,否則會使用 Inflector 來決定給定語言環境的複數形式,其預設為 `I18n.locale`。
這個字詞將使用語言環境中定義的規則來複數化(你必須為英語以外的語言定義自己的變形規則)。請參閱 ActiveSupport::Inflector.pluralize
pluralize(1, 'person')
# => "1 person"
pluralize(2, 'person')
# => "2 people"
pluralize(3, 'person', plural: 'users')
# => "3 users"
pluralize(0, 'person')
# => "0 people"
pluralize(2, 'Person', locale: :de)
# => "2 Personen"
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 290 def pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale) word = if count == 1 || count.to_s.match?(/^1(\.0+)?$/) singular else plural || singular.pluralize(locale) end "#{count || 0} #{word}" end
reset_cycle(name = "default") 連結
重置循環,以便下次呼叫時從第一個元素開始。傳入 `name` 以重置命名循環。
<%# Alternate CSS classes for even and odd numbers... %>
<% @items = [[1,2,3,4], [5,6,3], [3,4,5,6,7,4]] %>
<table>
<% @items.each do |item| %>
<tr class="<%= cycle("even", "odd") -%>">
<% item.each do |value| %>
<span style="color:<%= cycle("#333", "#666", "#999", name: "colors") -%>">
<%= value %>
</span>
<% end %>
<% reset_cycle("colors") %>
</tr>
<% end %>
</table>
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 477 def reset_cycle(name = "default") cycle = get_cycle(name) cycle.reset if cycle end
safe_concat(string) 連結
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 67 def safe_concat(string) output_buffer.respond_to?(:safe_concat) ? output_buffer.safe_concat(string) : concat(string) end
simple_format(text, html_options = {}, options = {}) 連結
傳回以簡單格式規則轉換成 HTML 的text
。兩個或更多個連續的新行(\n\n
或\r\n\r\n
)會被視為一段落並包覆在<p>
標籤中。一個新行(\n
或\r\n
)會被視為換行符,並附加上<br />
標籤。這個方法不會從text
中移除新行。
您可以將任何 HTML 屬性傳遞到html_options
。這些屬性會新增到所有建立的段落。
選項
-
:sanitize
- 如果為false
,不會清除text
。 -
:sanitize_options
- 任何您要附加到清除動作的額外選項。 -
:wrapper_tag
- 代表包覆標籤的字串
,預設為"p"
範例
my_text = "Here is some basic text...\n...with a line break."
simple_format(my_text)
# => "<p>Here is some basic text...\n<br />...with a line break.</p>"
simple_format(my_text, {}, wrapper_tag: "div")
# => "<div>Here is some basic text...\n<br />...with a line break.</div>"
more_text = "We want to put a paragraph...\n\n...right there."
simple_format(more_text)
# => "<p>We want to put a paragraph...</p>\n\n<p>...right there.</p>"
simple_format("Look ma! A class!", class: 'description')
# => "<p class='description'>Look ma! A class!</p>"
simple_format("<blink>Unblinkable.</blink>")
# => "<p>Unblinkable.</p>"
simple_format("<blink>Blinkable!</blink> It's true.", {}, sanitize: false)
# => "<p><blink>Blinkable!</blink> It's true.</p>"
simple_format("<a target=\"_blank\" href=\"http://example.com\">Continue</a>", {}, { sanitize_options: { attributes: %w[target href] } })
# => "<p><a target=\"_blank\" href=\"http://example.com\">Continue</a></p>"
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 376 def simple_format(text, html_options = {}, options = {}) wrapper_tag = options[:wrapper_tag] || "p" text = sanitize(text, options.fetch(:sanitize_options, {})) if options.fetch(:sanitize, true) paragraphs = split_paragraphs(text) if paragraphs.empty? content_tag(wrapper_tag, nil, html_options) else paragraphs.map! { |paragraph| content_tag(wrapper_tag, raw(paragraph), html_options) }.join("\n\n").html_safe end end
truncate(text, options = {}, &block) 連結
如果text
長度超過指定的:length
,就會將其截斷。如果截斷text
,會將省略記號附加到結果,總長度不超過:length
。
您也可以傳遞一個區塊,以便在截斷text
時附加內容到省略記號後面並加以呈現。但是,這個內容可以讓總長度超過:length
個字元。
除非指定escape: false
,否則會對結果進行跳脫。無論如何,結果都會標記為 HTML 安全。如果text
可能包含 HTML 標籤或實體,應小心謹慎,因為截斷可能會產生無效的 HTML,例如不平衡或不完整的標籤。
選項
:length
-
應傳回的字元最大數量,不包括區塊中任何額外的內容。預設為 30。
:omission
-
截斷後要附加的字串。預設為
"..."
。 :separator
-
用於尋找截斷斷點的字串或正規表示式。預設情況下,可以在
text
中的任何字元截斷。 :escape
-
是否跳脫結果。預設為 true。
範例
truncate("Once upon a time in a world far far away")
# => "Once upon a time in a world..."
truncate("Once upon a time in a world far far away", length: 17)
# => "Once upon a ti..."
truncate("Once upon a time in a world far far away", length: 17, separator: ' ')
# => "Once upon a..."
truncate("And they found that many people were sleeping better.", length: 25, omission: '... (continued)')
# => "And they f... (continued)"
truncate("<p>Once upon a time in a world far far away</p>")
# => "<p>Once upon a time in a wo..."
truncate("<p>Once upon a time in a world far far away</p>", escape: false)
# => "<p>Once upon a time in a wo..."
truncate("Once upon a time in a world far far away") { link_to "Continue", "#" }
# => "Once upon a time in a world...<a href=\"#\">Continue</a>"
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 122 def truncate(text, options = {}, &block) if text length = options.fetch(:length, 30) content = text.truncate(length, options) content = options[:escape] == false ? content.html_safe : ERB::Util.html_escape(content) content << capture(&block) if block_given? && text.length > length content end end
word_wrap(text, line_width: 80, break_sequence: "\n") 連結
將text
換行,每行的寬度不超過line_width
寬度。這個方法會在第一個不超過line_width
寬度的空白字元處換行(預設為 80)。
word_wrap('Once upon a time')
# => "Once upon a time"
word_wrap('Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding a successor to the throne turned out to be more trouble than anyone could have imagined...')
# => "Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding\na successor to the throne turned out to be more trouble than anyone could have\nimagined..."
word_wrap('Once upon a time', line_width: 8)
# => "Once\nupon a\ntime"
word_wrap('Once upon a time', line_width: 1)
# => "Once\nupon\na\ntime"
您也可以指定自訂的break_sequence
(預設為「n」)
word_wrap('Once upon a time', line_width: 1, break_sequence: "\r\n")
# => "Once\r\nupon\r\na\r\ntime"
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 320 def word_wrap(text, line_width: 80, break_sequence: "\n") return +"" if text.empty? # Match up to `line_width` characters, followed by one of # (1) non-newline whitespace plus an optional newline # (2) the end of the string, ignoring any trailing newlines # (3) a newline # # -OR- # # Match an empty line pattern = /(.{1,#{line_width}})(?:[^\S\n]+\n?|\n*\Z|\n)|\n/ text.gsub(pattern, "\\1#{break_sequence}").chomp!(break_sequence) end