erb 4.0.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/test.yml +36 -0
- data/.gitignore +12 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/NEWS.md +39 -0
- data/README.md +255 -0
- data/Rakefile +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/erb.gemspec +38 -0
- data/ext/erb/escape/escape.c +95 -0
- data/ext/erb/escape/extconf.rb +7 -0
- data/lib/erb/compiler.rb +471 -0
- data/lib/erb/def_method.rb +46 -0
- data/lib/erb/util.rb +62 -0
- data/lib/erb/version.rb +5 -0
- data/lib/erb.rb +506 -0
- data/libexec/erb +164 -0
- metadata +81 -0
data/lib/erb/compiler.rb
ADDED
@@ -0,0 +1,471 @@
|
|
1
|
+
#--
|
2
|
+
# ERB::Compiler
|
3
|
+
#
|
4
|
+
# Compiles ERB templates into Ruby code; the compiled code produces the
|
5
|
+
# template result when evaluated. ERB::Compiler provides hooks to define how
|
6
|
+
# generated output is handled.
|
7
|
+
#
|
8
|
+
# Internally ERB does something like this to generate the code returned by
|
9
|
+
# ERB#src:
|
10
|
+
#
|
11
|
+
# compiler = ERB::Compiler.new('<>')
|
12
|
+
# compiler.pre_cmd = ["_erbout=+''"]
|
13
|
+
# compiler.put_cmd = "_erbout.<<"
|
14
|
+
# compiler.insert_cmd = "_erbout.<<"
|
15
|
+
# compiler.post_cmd = ["_erbout"]
|
16
|
+
#
|
17
|
+
# code, enc = compiler.compile("Got <%= obj %>!\n")
|
18
|
+
# puts code
|
19
|
+
#
|
20
|
+
# <i>Generates</i>:
|
21
|
+
#
|
22
|
+
# #coding:UTF-8
|
23
|
+
# _erbout=+''; _erbout.<< "Got ".freeze; _erbout.<<(( obj ).to_s); _erbout.<< "!\n".freeze; _erbout
|
24
|
+
#
|
25
|
+
# By default the output is sent to the print method. For example:
|
26
|
+
#
|
27
|
+
# compiler = ERB::Compiler.new('<>')
|
28
|
+
# code, enc = compiler.compile("Got <%= obj %>!\n")
|
29
|
+
# puts code
|
30
|
+
#
|
31
|
+
# <i>Generates</i>:
|
32
|
+
#
|
33
|
+
# #coding:UTF-8
|
34
|
+
# print "Got ".freeze; print(( obj ).to_s); print "!\n".freeze
|
35
|
+
#
|
36
|
+
# == Evaluation
|
37
|
+
#
|
38
|
+
# The compiled code can be used in any context where the names in the code
|
39
|
+
# correctly resolve. Using the last example, each of these print 'Got It!'
|
40
|
+
#
|
41
|
+
# Evaluate using a variable:
|
42
|
+
#
|
43
|
+
# obj = 'It'
|
44
|
+
# eval code
|
45
|
+
#
|
46
|
+
# Evaluate using an input:
|
47
|
+
#
|
48
|
+
# mod = Module.new
|
49
|
+
# mod.module_eval %{
|
50
|
+
# def get(obj)
|
51
|
+
# #{code}
|
52
|
+
# end
|
53
|
+
# }
|
54
|
+
# extend mod
|
55
|
+
# get('It')
|
56
|
+
#
|
57
|
+
# Evaluate using an accessor:
|
58
|
+
#
|
59
|
+
# klass = Class.new Object
|
60
|
+
# klass.class_eval %{
|
61
|
+
# attr_accessor :obj
|
62
|
+
# def initialize(obj)
|
63
|
+
# @obj = obj
|
64
|
+
# end
|
65
|
+
# def get_it
|
66
|
+
# #{code}
|
67
|
+
# end
|
68
|
+
# }
|
69
|
+
# klass.new('It').get_it
|
70
|
+
#
|
71
|
+
# Good! See also ERB#def_method, ERB#def_module, and ERB#def_class.
|
72
|
+
class ERB::Compiler # :nodoc:
|
73
|
+
class PercentLine # :nodoc:
|
74
|
+
def initialize(str)
|
75
|
+
@value = str
|
76
|
+
end
|
77
|
+
attr_reader :value
|
78
|
+
alias :to_s :value
|
79
|
+
end
|
80
|
+
|
81
|
+
class Scanner # :nodoc:
|
82
|
+
@scanner_map = {}
|
83
|
+
class << self
|
84
|
+
def register_scanner(klass, trim_mode, percent)
|
85
|
+
@scanner_map[[trim_mode, percent]] = klass
|
86
|
+
end
|
87
|
+
alias :regist_scanner :register_scanner
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.default_scanner=(klass)
|
91
|
+
@default_scanner = klass
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.make_scanner(src, trim_mode, percent)
|
95
|
+
klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
|
96
|
+
klass.new(src, trim_mode, percent)
|
97
|
+
end
|
98
|
+
|
99
|
+
DEFAULT_STAGS = %w(<%% <%= <%# <%).freeze
|
100
|
+
DEFAULT_ETAGS = %w(%%> %>).freeze
|
101
|
+
def initialize(src, trim_mode, percent)
|
102
|
+
@src = src
|
103
|
+
@stag = nil
|
104
|
+
@stags = DEFAULT_STAGS
|
105
|
+
@etags = DEFAULT_ETAGS
|
106
|
+
end
|
107
|
+
attr_accessor :stag
|
108
|
+
attr_reader :stags, :etags
|
109
|
+
|
110
|
+
def scan; end
|
111
|
+
end
|
112
|
+
|
113
|
+
class TrimScanner < Scanner # :nodoc:
|
114
|
+
def initialize(src, trim_mode, percent)
|
115
|
+
super
|
116
|
+
@trim_mode = trim_mode
|
117
|
+
@percent = percent
|
118
|
+
if @trim_mode == '>'
|
119
|
+
@scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
|
120
|
+
@scan_line = self.method(:trim_line1)
|
121
|
+
elsif @trim_mode == '<>'
|
122
|
+
@scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
|
123
|
+
@scan_line = self.method(:trim_line2)
|
124
|
+
elsif @trim_mode == '-'
|
125
|
+
@scan_reg = /(.*?)(^[ \t]*<%\-|<%\-|-%>\r?\n|-%>|#{(stags + etags).join('|')}|\z)/m
|
126
|
+
@scan_line = self.method(:explicit_trim_line)
|
127
|
+
else
|
128
|
+
@scan_reg = /(.*?)(#{(stags + etags).join('|')}|\n|\z)/m
|
129
|
+
@scan_line = self.method(:scan_line)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def scan(&block)
|
134
|
+
@stag = nil
|
135
|
+
if @percent
|
136
|
+
@src.each_line do |line|
|
137
|
+
percent_line(line, &block)
|
138
|
+
end
|
139
|
+
else
|
140
|
+
@scan_line.call(@src, &block)
|
141
|
+
end
|
142
|
+
nil
|
143
|
+
end
|
144
|
+
|
145
|
+
def percent_line(line, &block)
|
146
|
+
if @stag || line[0] != ?%
|
147
|
+
return @scan_line.call(line, &block)
|
148
|
+
end
|
149
|
+
|
150
|
+
line[0] = ''
|
151
|
+
if line[0] == ?%
|
152
|
+
@scan_line.call(line, &block)
|
153
|
+
else
|
154
|
+
yield(PercentLine.new(line.chomp))
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def scan_line(line)
|
159
|
+
line.scan(@scan_reg) do |tokens|
|
160
|
+
tokens.each do |token|
|
161
|
+
next if token.empty?
|
162
|
+
yield(token)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def trim_line1(line)
|
168
|
+
line.scan(@scan_reg) do |tokens|
|
169
|
+
tokens.each do |token|
|
170
|
+
next if token.empty?
|
171
|
+
if token == "%>\n" || token == "%>\r\n"
|
172
|
+
yield('%>')
|
173
|
+
yield(:cr)
|
174
|
+
else
|
175
|
+
yield(token)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def trim_line2(line)
|
182
|
+
head = nil
|
183
|
+
line.scan(@scan_reg) do |tokens|
|
184
|
+
tokens.each do |token|
|
185
|
+
next if token.empty?
|
186
|
+
head = token unless head
|
187
|
+
if token == "%>\n" || token == "%>\r\n"
|
188
|
+
yield('%>')
|
189
|
+
if is_erb_stag?(head)
|
190
|
+
yield(:cr)
|
191
|
+
else
|
192
|
+
yield("\n")
|
193
|
+
end
|
194
|
+
head = nil
|
195
|
+
else
|
196
|
+
yield(token)
|
197
|
+
head = nil if token == "\n"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def explicit_trim_line(line)
|
204
|
+
line.scan(@scan_reg) do |tokens|
|
205
|
+
tokens.each do |token|
|
206
|
+
next if token.empty?
|
207
|
+
if @stag.nil? && /[ \t]*<%-/ =~ token
|
208
|
+
yield('<%')
|
209
|
+
elsif @stag && (token == "-%>\n" || token == "-%>\r\n")
|
210
|
+
yield('%>')
|
211
|
+
yield(:cr)
|
212
|
+
elsif @stag && token == '-%>'
|
213
|
+
yield('%>')
|
214
|
+
else
|
215
|
+
yield(token)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
ERB_STAG = %w(<%= <%# <%)
|
222
|
+
def is_erb_stag?(s)
|
223
|
+
ERB_STAG.member?(s)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
Scanner.default_scanner = TrimScanner
|
228
|
+
|
229
|
+
begin
|
230
|
+
require 'strscan'
|
231
|
+
rescue LoadError
|
232
|
+
else
|
233
|
+
class SimpleScanner < Scanner # :nodoc:
|
234
|
+
def scan
|
235
|
+
stag_reg = (stags == DEFAULT_STAGS) ? /(.*?)(<%[%=#]?|\z)/m : /(.*?)(#{stags.join('|')}|\z)/m
|
236
|
+
etag_reg = (etags == DEFAULT_ETAGS) ? /(.*?)(%%?>|\z)/m : /(.*?)(#{etags.join('|')}|\z)/m
|
237
|
+
scanner = StringScanner.new(@src)
|
238
|
+
while ! scanner.eos?
|
239
|
+
scanner.scan(@stag ? etag_reg : stag_reg)
|
240
|
+
yield(scanner[1])
|
241
|
+
yield(scanner[2])
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
Scanner.register_scanner(SimpleScanner, nil, false)
|
246
|
+
|
247
|
+
class ExplicitScanner < Scanner # :nodoc:
|
248
|
+
def scan
|
249
|
+
stag_reg = /(.*?)(^[ \t]*<%-|<%-|#{stags.join('|')}|\z)/m
|
250
|
+
etag_reg = /(.*?)(-%>|#{etags.join('|')}|\z)/m
|
251
|
+
scanner = StringScanner.new(@src)
|
252
|
+
while ! scanner.eos?
|
253
|
+
scanner.scan(@stag ? etag_reg : stag_reg)
|
254
|
+
yield(scanner[1])
|
255
|
+
|
256
|
+
elem = scanner[2]
|
257
|
+
if /[ \t]*<%-/ =~ elem
|
258
|
+
yield('<%')
|
259
|
+
elsif elem == '-%>'
|
260
|
+
yield('%>')
|
261
|
+
yield(:cr) if scanner.scan(/(\r?\n|\z)/)
|
262
|
+
else
|
263
|
+
yield(elem)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
Scanner.register_scanner(ExplicitScanner, '-', false)
|
269
|
+
end
|
270
|
+
|
271
|
+
class Buffer # :nodoc:
|
272
|
+
def initialize(compiler, enc=nil, frozen=nil)
|
273
|
+
@compiler = compiler
|
274
|
+
@line = []
|
275
|
+
@script = +''
|
276
|
+
@script << "#coding:#{enc}\n" if enc
|
277
|
+
@script << "#frozen-string-literal:#{frozen}\n" unless frozen.nil?
|
278
|
+
@compiler.pre_cmd.each do |x|
|
279
|
+
push(x)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
attr_reader :script
|
283
|
+
|
284
|
+
def push(cmd)
|
285
|
+
@line << cmd
|
286
|
+
end
|
287
|
+
|
288
|
+
def cr
|
289
|
+
@script << (@line.join('; '))
|
290
|
+
@line = []
|
291
|
+
@script << "\n"
|
292
|
+
end
|
293
|
+
|
294
|
+
def close
|
295
|
+
return unless @line
|
296
|
+
@compiler.post_cmd.each do |x|
|
297
|
+
push(x)
|
298
|
+
end
|
299
|
+
@script << (@line.join('; '))
|
300
|
+
@line = nil
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def add_put_cmd(out, content)
|
305
|
+
out.push("#{@put_cmd} #{content.dump}.freeze#{"\n" * content.count("\n")}")
|
306
|
+
end
|
307
|
+
|
308
|
+
def add_insert_cmd(out, content)
|
309
|
+
out.push("#{@insert_cmd}((#{content}).to_s)")
|
310
|
+
end
|
311
|
+
|
312
|
+
# Compiles an ERB template into Ruby code. Returns an array of the code
|
313
|
+
# and encoding like ["code", Encoding].
|
314
|
+
def compile(s)
|
315
|
+
enc = s.encoding
|
316
|
+
raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
|
317
|
+
s = s.b # see String#b
|
318
|
+
magic_comment = detect_magic_comment(s, enc)
|
319
|
+
out = Buffer.new(self, *magic_comment)
|
320
|
+
|
321
|
+
self.content = +''
|
322
|
+
scanner = make_scanner(s)
|
323
|
+
scanner.scan do |token|
|
324
|
+
next if token.nil?
|
325
|
+
next if token == ''
|
326
|
+
if scanner.stag.nil?
|
327
|
+
compile_stag(token, out, scanner)
|
328
|
+
else
|
329
|
+
compile_etag(token, out, scanner)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
add_put_cmd(out, content) if content.size > 0
|
333
|
+
out.close
|
334
|
+
return out.script, *magic_comment
|
335
|
+
end
|
336
|
+
|
337
|
+
def compile_stag(stag, out, scanner)
|
338
|
+
case stag
|
339
|
+
when PercentLine
|
340
|
+
add_put_cmd(out, content) if content.size > 0
|
341
|
+
self.content = +''
|
342
|
+
out.push(stag.to_s)
|
343
|
+
out.cr
|
344
|
+
when :cr
|
345
|
+
out.cr
|
346
|
+
when '<%', '<%=', '<%#'
|
347
|
+
scanner.stag = stag
|
348
|
+
add_put_cmd(out, content) if content.size > 0
|
349
|
+
self.content = +''
|
350
|
+
when "\n"
|
351
|
+
content << "\n"
|
352
|
+
add_put_cmd(out, content)
|
353
|
+
self.content = +''
|
354
|
+
when '<%%'
|
355
|
+
content << '<%'
|
356
|
+
else
|
357
|
+
content << stag
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
def compile_etag(etag, out, scanner)
|
362
|
+
case etag
|
363
|
+
when '%>'
|
364
|
+
compile_content(scanner.stag, out)
|
365
|
+
scanner.stag = nil
|
366
|
+
self.content = +''
|
367
|
+
when '%%>'
|
368
|
+
content << '%>'
|
369
|
+
else
|
370
|
+
content << etag
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def compile_content(stag, out)
|
375
|
+
case stag
|
376
|
+
when '<%'
|
377
|
+
if content[-1] == ?\n
|
378
|
+
content.chop!
|
379
|
+
out.push(content)
|
380
|
+
out.cr
|
381
|
+
else
|
382
|
+
out.push(content)
|
383
|
+
end
|
384
|
+
when '<%='
|
385
|
+
add_insert_cmd(out, content)
|
386
|
+
when '<%#'
|
387
|
+
# commented out
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def prepare_trim_mode(mode) # :nodoc:
|
392
|
+
case mode
|
393
|
+
when 1
|
394
|
+
return [false, '>']
|
395
|
+
when 2
|
396
|
+
return [false, '<>']
|
397
|
+
when 0, nil
|
398
|
+
return [false, nil]
|
399
|
+
when String
|
400
|
+
unless mode.match?(/\A(%|-|>|<>){1,2}\z/)
|
401
|
+
warn_invalid_trim_mode(mode, uplevel: 5)
|
402
|
+
end
|
403
|
+
|
404
|
+
perc = mode.include?('%')
|
405
|
+
if mode.include?('-')
|
406
|
+
return [perc, '-']
|
407
|
+
elsif mode.include?('<>')
|
408
|
+
return [perc, '<>']
|
409
|
+
elsif mode.include?('>')
|
410
|
+
return [perc, '>']
|
411
|
+
else
|
412
|
+
[perc, nil]
|
413
|
+
end
|
414
|
+
else
|
415
|
+
warn_invalid_trim_mode(mode, uplevel: 5)
|
416
|
+
return [false, nil]
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
def make_scanner(src) # :nodoc:
|
421
|
+
Scanner.make_scanner(src, @trim_mode, @percent)
|
422
|
+
end
|
423
|
+
|
424
|
+
# Construct a new compiler using the trim_mode. See ERB::new for available
|
425
|
+
# trim modes.
|
426
|
+
def initialize(trim_mode)
|
427
|
+
@percent, @trim_mode = prepare_trim_mode(trim_mode)
|
428
|
+
@put_cmd = 'print'
|
429
|
+
@insert_cmd = @put_cmd
|
430
|
+
@pre_cmd = []
|
431
|
+
@post_cmd = []
|
432
|
+
end
|
433
|
+
attr_reader :percent, :trim_mode
|
434
|
+
|
435
|
+
# The command to handle text that ends with a newline
|
436
|
+
attr_accessor :put_cmd
|
437
|
+
|
438
|
+
# The command to handle text that is inserted prior to a newline
|
439
|
+
attr_accessor :insert_cmd
|
440
|
+
|
441
|
+
# An array of commands prepended to compiled code
|
442
|
+
attr_accessor :pre_cmd
|
443
|
+
|
444
|
+
# An array of commands appended to compiled code
|
445
|
+
attr_accessor :post_cmd
|
446
|
+
|
447
|
+
private
|
448
|
+
|
449
|
+
# A buffered text in #compile
|
450
|
+
attr_accessor :content
|
451
|
+
|
452
|
+
def detect_magic_comment(s, enc = nil)
|
453
|
+
re = @percent ? /\G(?:<%#(.*)%>|%#(.*)\n)/ : /\G<%#(.*)%>/
|
454
|
+
frozen = nil
|
455
|
+
s.scan(re) do
|
456
|
+
comment = $+
|
457
|
+
comment = $1 if comment[/-\*-\s*([^\s].*?)\s*-\*-$/]
|
458
|
+
case comment
|
459
|
+
when %r"coding\s*[=:]\s*([[:alnum:]\-_]+)"
|
460
|
+
enc = Encoding.find($1.sub(/-(?:mac|dos|unix)/i, ''))
|
461
|
+
when %r"frozen[-_]string[-_]literal\s*:\s*([[:alnum:]]+)"
|
462
|
+
frozen = $1
|
463
|
+
end
|
464
|
+
end
|
465
|
+
return enc, frozen
|
466
|
+
end
|
467
|
+
|
468
|
+
def warn_invalid_trim_mode(mode, uplevel:)
|
469
|
+
warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + 1
|
470
|
+
end
|
471
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#--
|
2
|
+
# ERB::DefMethod
|
3
|
+
#
|
4
|
+
# Utility module to define eRuby script as instance method.
|
5
|
+
#
|
6
|
+
# === Example
|
7
|
+
#
|
8
|
+
# example.rhtml:
|
9
|
+
# <% for item in @items %>
|
10
|
+
# <b><%= item %></b>
|
11
|
+
# <% end %>
|
12
|
+
#
|
13
|
+
# example.rb:
|
14
|
+
# require 'erb'
|
15
|
+
# class MyClass
|
16
|
+
# extend ERB::DefMethod
|
17
|
+
# def_erb_method('render()', 'example.rhtml')
|
18
|
+
# def initialize(items)
|
19
|
+
# @items = items
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# print MyClass.new([10,20,30]).render()
|
23
|
+
#
|
24
|
+
# result:
|
25
|
+
#
|
26
|
+
# <b>10</b>
|
27
|
+
#
|
28
|
+
# <b>20</b>
|
29
|
+
#
|
30
|
+
# <b>30</b>
|
31
|
+
#
|
32
|
+
module ERB::DefMethod
|
33
|
+
# define _methodname_ as instance method of current module, using ERB
|
34
|
+
# object or eRuby file
|
35
|
+
def def_erb_method(methodname, erb_or_fname)
|
36
|
+
if erb_or_fname.kind_of? String
|
37
|
+
fname = erb_or_fname
|
38
|
+
erb = ERB.new(File.read(fname))
|
39
|
+
erb.def_method(self, methodname, fname)
|
40
|
+
else
|
41
|
+
erb = erb_or_fname
|
42
|
+
erb.def_method(self, methodname, erb.filename || '(ERB)')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
module_function :def_erb_method
|
46
|
+
end
|
data/lib/erb/util.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
#--
|
2
|
+
# ERB::Escape
|
3
|
+
#
|
4
|
+
# A subset of ERB::Util. Unlike ERB::Util#html_escape, we expect/hope
|
5
|
+
# Rails will not monkey-patch ERB::Escape#html_escape.
|
6
|
+
begin
|
7
|
+
# We don't build the C extension for JRuby, TruffleRuby, and WASM
|
8
|
+
if $LOAD_PATH.resolve_feature_path('erb/escape')
|
9
|
+
require 'erb/escape'
|
10
|
+
end
|
11
|
+
rescue LoadError # resolve_feature_path raises LoadError on TruffleRuby 22.3.0
|
12
|
+
end
|
13
|
+
unless defined?(ERB::Escape)
|
14
|
+
module ERB::Escape
|
15
|
+
def html_escape(s)
|
16
|
+
CGI.escapeHTML(s.to_s)
|
17
|
+
end
|
18
|
+
module_function :html_escape
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
#--
|
23
|
+
# ERB::Util
|
24
|
+
#
|
25
|
+
# A utility module for conversion routines, often handy in HTML generation.
|
26
|
+
module ERB::Util
|
27
|
+
#
|
28
|
+
# A utility method for escaping HTML tag characters in _s_.
|
29
|
+
#
|
30
|
+
# require "erb"
|
31
|
+
# include ERB::Util
|
32
|
+
#
|
33
|
+
# puts html_escape("is a > 0 & a < 10?")
|
34
|
+
#
|
35
|
+
# _Generates_
|
36
|
+
#
|
37
|
+
# is a > 0 & a < 10?
|
38
|
+
#
|
39
|
+
include ERB::Escape # html_escape
|
40
|
+
module_function :html_escape
|
41
|
+
alias h html_escape
|
42
|
+
module_function :h
|
43
|
+
|
44
|
+
#
|
45
|
+
# A utility method for encoding the String _s_ as a URL.
|
46
|
+
#
|
47
|
+
# require "erb"
|
48
|
+
# include ERB::Util
|
49
|
+
#
|
50
|
+
# puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
|
51
|
+
#
|
52
|
+
# _Generates_
|
53
|
+
#
|
54
|
+
# Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
|
55
|
+
#
|
56
|
+
def url_encode(s)
|
57
|
+
CGI.escapeURIComponent(s.to_s)
|
58
|
+
end
|
59
|
+
alias u url_encode
|
60
|
+
module_function :u
|
61
|
+
module_function :url_encode
|
62
|
+
end
|