tagz 5.0.1 → 6.0.0
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.
- data/README +40 -249
- data/Rakefile +228 -0
- data/lib/tagz.rb +234 -154
- data/readme.erb +154 -0
- data/samples/d.rb +4 -4
- data/tagz.gemspec +26 -0
- data/test/tagz.rb +154 -0
- metadata +6 -8
- data/a.rb +0 -12
- data/gemspec.rb +0 -44
- data/gen_readme.rb +0 -34
- data/install.rb +0 -214
- data/prof.rb +0 -25
data/lib/tagz.rb
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
unless defined? Tagz
|
2
2
|
|
3
3
|
module Tagz
|
4
|
-
|
5
|
-
Tagz::VERSION = [
|
6
|
-
Tagz::VERSION_MAJOR = 5,
|
7
|
-
Tagz::VERSION_MINOR = 0,
|
8
|
-
Tagz::VERSION_TEENY = 1
|
9
|
-
].join('.')
|
10
|
-
def Tagz.version() Tagz::VERSION end
|
11
|
-
end
|
4
|
+
def Tagz.version() '6.0.0' end
|
12
5
|
|
13
6
|
private
|
14
7
|
|
@@ -21,8 +14,8 @@ unless defined? Tagz
|
|
21
14
|
unless options.empty?
|
22
15
|
attributes = ' ' <<
|
23
16
|
options.map do |key, value|
|
24
|
-
key =
|
25
|
-
value =
|
17
|
+
key = Tagz.escape_attribute(key)
|
18
|
+
value = Tagz.escape_attribute(value)
|
26
19
|
if value =~ %r/"/
|
27
20
|
raise ArgumentError, value if value =~ %r/'/
|
28
21
|
value = "'#{ value }'"
|
@@ -36,7 +29,7 @@ unless defined? Tagz
|
|
36
29
|
attributes = ''
|
37
30
|
end
|
38
31
|
|
39
|
-
tagz.
|
32
|
+
tagz.push "<#{ name }#{ attributes }>"
|
40
33
|
|
41
34
|
if content.empty?
|
42
35
|
if block
|
@@ -47,11 +40,11 @@ unless defined? Tagz
|
|
47
40
|
unless(tagz.size > size)
|
48
41
|
tagz[-1] = "/>"
|
49
42
|
else
|
50
|
-
tagz.
|
43
|
+
tagz.push "</#{ name }>"
|
51
44
|
end
|
52
45
|
else
|
53
46
|
tagz << value.to_s unless(tagz.size > size)
|
54
|
-
tagz.
|
47
|
+
tagz.push "</#{ name }>"
|
55
48
|
end
|
56
49
|
|
57
50
|
end
|
@@ -62,7 +55,7 @@ unless defined? Tagz
|
|
62
55
|
value = block.call(tagz)
|
63
56
|
tagz << value.to_s unless(tagz.size > size)
|
64
57
|
end
|
65
|
-
tagz.
|
58
|
+
tagz.push "</#{ name }>"
|
66
59
|
end
|
67
60
|
|
68
61
|
tagz
|
@@ -71,7 +64,7 @@ unless defined? Tagz
|
|
71
64
|
# close_tag
|
72
65
|
#
|
73
66
|
def __tagz tag, *a, &b
|
74
|
-
tagz.
|
67
|
+
tagz.push "</#{ tag }>"
|
75
68
|
end
|
76
69
|
|
77
70
|
# access tagz doc and enclose tagz operations
|
@@ -132,183 +125,270 @@ unless defined? Tagz
|
|
132
125
|
Element.new(*a, &b)
|
133
126
|
when :puts
|
134
127
|
tagz do
|
135
|
-
tagz.
|
128
|
+
tagz.push("\n")
|
136
129
|
unless a.empty?
|
137
|
-
tagz.
|
138
|
-
tagz.
|
130
|
+
tagz.push(a.join)
|
131
|
+
tagz.push("\n")
|
139
132
|
end
|
140
133
|
end
|
141
134
|
end
|
142
135
|
end
|
143
136
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
137
|
+
# escape support
|
138
|
+
#
|
139
|
+
def Tagz.escapeHTML(*strings)
|
140
|
+
XChar.escape(strings.join)
|
141
|
+
end
|
148
142
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
alias_method 'e', 'element'
|
143
|
+
def Tagz.escape(*strings)
|
144
|
+
XChar.escape(strings.join)
|
145
|
+
end
|
153
146
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
147
|
+
# support for configuring attribute escaping
|
148
|
+
#
|
149
|
+
def Tagz.escape_attribute!(*args, &block)
|
150
|
+
previous = @escape_attribute if defined?(@escape_attribute)
|
151
|
+
unless args.empty? and block.nil?
|
152
|
+
value = block ? block : args.shift
|
153
|
+
@escape_attribute = value ? value.to_proc : NoEscape
|
154
|
+
return previous
|
162
155
|
end
|
156
|
+
@escape_attribute
|
157
|
+
end
|
163
158
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
alias_method 'h', 'escape'
|
159
|
+
def Tagz.escape_attributes!(*args, &block)
|
160
|
+
Tagz.escape_attribute!(*args, &block)
|
161
|
+
end
|
168
162
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
alias_method 'push', 'concat'
|
173
|
-
alias_method 'write', 'concat'
|
163
|
+
def Tagz.escape_attribute(value)
|
164
|
+
@escape_attribute.call(value.to_s)
|
165
|
+
end
|
174
166
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
alias_method 'doc', 'document'
|
167
|
+
# default escape
|
168
|
+
#
|
169
|
+
escape_attribute!{|value| XChar.escape(value)}
|
179
170
|
|
180
|
-
|
181
|
-
|
171
|
+
# support for configuring content escaping
|
172
|
+
#
|
173
|
+
def Tagz.escape_content!(*args, &block)
|
174
|
+
previous = @escape_content if defined?(@escape_content)
|
175
|
+
unless args.empty? and block.nil?
|
176
|
+
value = block ? block : args.shift
|
177
|
+
@escape_content = value ? value.to_proc : NoEscape
|
178
|
+
return previous
|
182
179
|
end
|
180
|
+
@escape_content
|
181
|
+
end
|
183
182
|
|
184
|
-
|
185
|
-
|
186
|
-
|
183
|
+
def Tagz.escape_contents!(*args, &block)
|
184
|
+
Tagz.escape_content!(*args, &block)
|
185
|
+
end
|
187
186
|
|
188
|
-
|
189
|
-
|
190
|
-
end
|
187
|
+
def Tagz.escape_content(value)
|
188
|
+
@escape_content.call(value.to_s)
|
191
189
|
end
|
192
190
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
191
|
+
# default escape
|
192
|
+
#
|
193
|
+
escape_content!{|value| XChar.escape(value)}
|
194
|
+
|
195
|
+
# make tagz escape nothing
|
196
|
+
#
|
197
|
+
def Tagz.i_know_what_the_hell_i_am_doing!
|
198
|
+
Tagz.escape_attributes! false
|
199
|
+
Tagz.escape_content! false
|
200
|
+
end
|
201
|
+
|
202
|
+
# make tagz escape everything
|
203
|
+
#
|
204
|
+
def Tagz.i_do_not_know_what_the_hell_i_am_doing!
|
205
|
+
escape_attribute!{|value| XChar.escape(value)}
|
206
|
+
escape_content!{|value| XChar.escape(value)}
|
207
|
+
end
|
208
|
+
|
209
|
+
def Tagz.globally
|
210
|
+
Globally
|
211
|
+
end
|
212
|
+
|
213
|
+
def Tagz.privately
|
214
|
+
Privately
|
215
|
+
end
|
216
|
+
|
217
|
+
# hide away our own shit to minimize pollution
|
218
|
+
#
|
219
|
+
module TagzConstants
|
220
|
+
class Document < ::String
|
221
|
+
def Document.for other
|
222
|
+
Document === other ? other : Document.new(other.to_s)
|
211
223
|
end
|
212
|
-
end
|
213
224
|
|
214
|
-
|
225
|
+
def element
|
226
|
+
Element.new(*a, &b)
|
227
|
+
end
|
228
|
+
alias_method 'e', 'element'
|
215
229
|
|
216
|
-
|
217
|
-
|
218
|
-
content = []
|
230
|
+
alias_method 'write', 'concat'
|
231
|
+
alias_method 'push', 'concat'
|
219
232
|
|
220
|
-
|
221
|
-
case
|
222
|
-
when
|
223
|
-
|
233
|
+
def << string
|
234
|
+
case string
|
235
|
+
when Document
|
236
|
+
super string.to_s
|
224
237
|
else
|
225
|
-
|
238
|
+
super Tagz.escape_content(string)
|
226
239
|
end
|
240
|
+
self
|
241
|
+
end
|
242
|
+
def concat string
|
243
|
+
self << string
|
244
|
+
end
|
245
|
+
#alias_method 'concat', '<<'
|
246
|
+
|
247
|
+
def escape(*strings)
|
248
|
+
XChar.escape(strings.join)
|
227
249
|
end
|
250
|
+
alias_method 'h', 'escape'
|
228
251
|
|
229
|
-
|
230
|
-
|
252
|
+
def puts string
|
253
|
+
write "#{ string }\n"
|
254
|
+
end
|
231
255
|
|
232
|
-
|
256
|
+
def document
|
257
|
+
self
|
258
|
+
end
|
259
|
+
alias_method 'doc', 'document'
|
260
|
+
|
261
|
+
def + other
|
262
|
+
self.dup << other
|
263
|
+
end
|
233
264
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
265
|
+
def to_s
|
266
|
+
self
|
267
|
+
end
|
268
|
+
|
269
|
+
def to_str
|
270
|
+
self
|
238
271
|
end
|
239
272
|
end
|
240
|
-
end
|
241
273
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
274
|
+
class Element < ::String
|
275
|
+
def Element.attributes options
|
276
|
+
unless options.empty?
|
277
|
+
' ' <<
|
278
|
+
options.map do |key, value|
|
279
|
+
key = Tagz.escape_attribute(key)
|
280
|
+
value = Tagz.escape_attribute(value)
|
281
|
+
if value =~ %r/"/
|
282
|
+
raise ArgumentError, value if value =~ %r/'/
|
283
|
+
value = "'#{ value }'"
|
284
|
+
else
|
285
|
+
raise ArgumentError, value if value =~ %r/"/
|
286
|
+
value = "\"#{ value }\""
|
287
|
+
end
|
288
|
+
[key, value].join('=')
|
289
|
+
end.join(' ')
|
290
|
+
else
|
291
|
+
''
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
attr 'name'
|
296
|
+
|
297
|
+
def initialize name, *argv, &block
|
298
|
+
options = {}
|
299
|
+
content = []
|
300
|
+
|
301
|
+
argv.each do |arg|
|
302
|
+
case arg
|
303
|
+
when Hash
|
304
|
+
options.update arg
|
305
|
+
else
|
306
|
+
content.push arg
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
content.push block.call if block
|
311
|
+
content.compact!
|
312
|
+
|
313
|
+
@name = name.to_s
|
314
|
+
|
315
|
+
if content.empty?
|
316
|
+
replace "<#{ @name }#{ Element.attributes options }>"
|
317
|
+
else
|
318
|
+
replace "<#{ @name }#{ Element.attributes options }>#{ content.join }</#{ name }>"
|
319
|
+
end
|
320
|
+
end
|
289
321
|
end
|
290
322
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
323
|
+
module XChar
|
324
|
+
# http://intertwingly.net/stories/2004/04/14/i18n.html#CleaningWindows
|
325
|
+
#
|
326
|
+
CP1252 = {
|
327
|
+
128 => 8364, # euro sign
|
328
|
+
130 => 8218, # single low-9 quotation mark
|
329
|
+
131 => 402, # latin small letter f with hook
|
330
|
+
132 => 8222, # double low-9 quotation mark
|
331
|
+
133 => 8230, # horizontal ellipsis
|
332
|
+
134 => 8224, # dagger
|
333
|
+
135 => 8225, # double dagger
|
334
|
+
136 => 710, # modifier letter circumflex accent
|
335
|
+
137 => 8240, # per mille sign
|
336
|
+
138 => 352, # latin capital letter s with caron
|
337
|
+
139 => 8249, # single left-pointing angle quotation mark
|
338
|
+
140 => 338, # latin capital ligature oe
|
339
|
+
142 => 381, # latin capital letter z with caron
|
340
|
+
145 => 8216, # left single quotation mark
|
341
|
+
146 => 8217, # right single quotation mark
|
342
|
+
147 => 8220, # left double quotation mark
|
343
|
+
148 => 8221, # right double quotation mark
|
344
|
+
149 => 8226, # bullet
|
345
|
+
150 => 8211, # en dash
|
346
|
+
151 => 8212, # em dash
|
347
|
+
152 => 732, # small tilde
|
348
|
+
153 => 8482, # trade mark sign
|
349
|
+
154 => 353, # latin small letter s with caron
|
350
|
+
155 => 8250, # single right-pointing angle quotation mark
|
351
|
+
156 => 339, # latin small ligature oe
|
352
|
+
158 => 382, # latin small letter z with caron
|
353
|
+
159 => 376} # latin capital letter y with diaeresis
|
354
|
+
|
355
|
+
# http://www.w3.org/TR/REC-xml/#dt-chardata
|
356
|
+
#
|
357
|
+
PREDEFINED = {
|
358
|
+
38 => '&', # ampersand
|
359
|
+
60 => '<', # left angle bracket
|
360
|
+
62 => '>'} # right angle bracket
|
361
|
+
|
362
|
+
# http://www.w3.org/TR/REC-xml/#charsets
|
363
|
+
#
|
364
|
+
VALID = [[0x9, 0xA, 0xD], (0x20..0xD7FF), (0xE000..0xFFFD), (0x10000..0x10FFFF)]
|
365
|
+
|
366
|
+
def XChar.escape(string)
|
367
|
+
string.unpack('U*').map{|n| xchr(n)}.join # ASCII, UTF-8
|
368
|
+
rescue
|
369
|
+
string.unpack('C*').map{|n| xchr(n)}.join # ISO-8859-1, WIN-1252
|
370
|
+
end
|
371
|
+
|
372
|
+
def XChar.xchr(n)
|
373
|
+
(@xchr ||= {})[n] ||= ((
|
374
|
+
n = XChar::CP1252[n] || n
|
375
|
+
n = 42 unless XChar::VALID.find{|range| range.include? n}
|
376
|
+
XChar::PREDEFINED[n] or (n<128 ? n.chr : "&##{n};")
|
377
|
+
))
|
378
|
+
end
|
297
379
|
end
|
298
|
-
end
|
299
380
|
|
300
|
-
|
301
|
-
XChar.escape(string)
|
302
|
-
end
|
381
|
+
NoEscape = lambda{|v|v}
|
303
382
|
|
304
|
-
|
305
|
-
|
306
|
-
Globally
|
383
|
+
module Globally; include ::Tagz; end
|
384
|
+
module Privately; include ::Tagz; end
|
307
385
|
end
|
308
386
|
|
309
|
-
|
310
|
-
|
311
|
-
|
387
|
+
# const_missing support
|
388
|
+
#
|
389
|
+
def Tagz.const_missing(const)
|
390
|
+
super unless TagzConstants.const_defined?(const)
|
391
|
+
TagzConstants.const_get(const)
|
312
392
|
end
|
313
393
|
|
314
394
|
%w( tagz tagz__ __tagz method_missing ).each{|m| module_function(m)}
|