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.
Files changed (13) hide show
  1. data/README +40 -249
  2. data/Rakefile +228 -0
  3. data/lib/tagz.rb +234 -154
  4. data/readme.erb +154 -0
  5. data/samples/d.rb +4 -4
  6. data/tagz.gemspec +26 -0
  7. data/test/tagz.rb +154 -0
  8. metadata +6 -8
  9. data/a.rb +0 -12
  10. data/gemspec.rb +0 -44
  11. data/gen_readme.rb +0 -34
  12. data/install.rb +0 -214
  13. data/prof.rb +0 -25
@@ -1,14 +1,7 @@
1
1
  unless defined? Tagz
2
2
 
3
3
  module Tagz
4
- unless defined?(Tagz::VERSION)
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 = XChar.escape key.to_s
25
- value = XChar.escape value.to_s
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.concat "<#{ name }#{ attributes }>"
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.concat "</#{ name }>"
43
+ tagz.push "</#{ name }>"
51
44
  end
52
45
  else
53
46
  tagz << value.to_s unless(tagz.size > size)
54
- tagz.concat "</#{ name }>"
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.concat "</#{ name }>"
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.concat "</#{ tag }>"
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.concat("\n")
128
+ tagz.push("\n")
136
129
  unless a.empty?
137
- tagz.concat(a.join)
138
- tagz.concat("\n")
130
+ tagz.push(a.join)
131
+ tagz.push("\n")
139
132
  end
140
133
  end
141
134
  end
142
135
  end
143
136
 
144
- class Document < ::String
145
- def Document.for other
146
- Document === other ? other : Document.new(other.to_s)
147
- end
137
+ # escape support
138
+ #
139
+ def Tagz.escapeHTML(*strings)
140
+ XChar.escape(strings.join)
141
+ end
148
142
 
149
- def element
150
- Element.new(*a, &b)
151
- end
152
- alias_method 'e', 'element'
143
+ def Tagz.escape(*strings)
144
+ XChar.escape(strings.join)
145
+ end
153
146
 
154
- def << string
155
- case string
156
- when Document
157
- super string.to_s
158
- else
159
- super XChar.escape(string.to_s)
160
- end
161
- self
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
- def escape(*strings)
165
- XChar.escape(strings.join)
166
- end
167
- alias_method 'h', 'escape'
159
+ def Tagz.escape_attributes!(*args, &block)
160
+ Tagz.escape_attribute!(*args, &block)
161
+ end
168
162
 
169
- def puts string
170
- concat "#{ string }\n"
171
- end
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
- def document
176
- self
177
- end
178
- alias_method 'doc', 'document'
167
+ # default escape
168
+ #
169
+ escape_attribute!{|value| XChar.escape(value)}
179
170
 
180
- def + other
181
- self.dup << other
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
- def to_s
185
- self
186
- end
183
+ def Tagz.escape_contents!(*args, &block)
184
+ Tagz.escape_content!(*args, &block)
185
+ end
187
186
 
188
- def to_str
189
- self
190
- end
187
+ def Tagz.escape_content(value)
188
+ @escape_content.call(value.to_s)
191
189
  end
192
190
 
193
- class Element < ::String
194
- def Element.attributes options
195
- unless options.empty?
196
- ' ' <<
197
- options.map do |key, value|
198
- key = XChar.escape key.to_s
199
- value = XChar.escape value.to_s
200
- if value =~ %r/"/
201
- raise ArgumentError, value if value =~ %r/'/
202
- value = "'#{ value }'"
203
- else
204
- raise ArgumentError, value if value =~ %r/"/
205
- value = "\"#{ value }\""
206
- end
207
- [key, value].join('=')
208
- end.join(' ')
209
- else
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
- attr 'name'
225
+ def element
226
+ Element.new(*a, &b)
227
+ end
228
+ alias_method 'e', 'element'
215
229
 
216
- def initialize name, *argv, &block
217
- options = {}
218
- content = []
230
+ alias_method 'write', 'concat'
231
+ alias_method 'push', 'concat'
219
232
 
220
- argv.each do |arg|
221
- case arg
222
- when Hash
223
- options.update arg
233
+ def << string
234
+ case string
235
+ when Document
236
+ super string.to_s
224
237
  else
225
- content.push arg
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
- content.push block.call if block
230
- content.compact!
252
+ def puts string
253
+ write "#{ string }\n"
254
+ end
231
255
 
232
- @name = name.to_s
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
- if content.empty?
235
- replace "<#{ @name }#{ Element.attributes options }>"
236
- else
237
- replace "<#{ @name }#{ Element.attributes options }>#{ content.join }</#{ name }>"
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
- module XChar
243
- # http://intertwingly.net/stories/2004/04/14/i18n.html#CleaningWindows
244
- #
245
- CP1252 = {
246
- 128 => 8364, # euro sign
247
- 130 => 8218, # single low-9 quotation mark
248
- 131 => 402, # latin small letter f with hook
249
- 132 => 8222, # double low-9 quotation mark
250
- 133 => 8230, # horizontal ellipsis
251
- 134 => 8224, # dagger
252
- 135 => 8225, # double dagger
253
- 136 => 710, # modifier letter circumflex accent
254
- 137 => 8240, # per mille sign
255
- 138 => 352, # latin capital letter s with caron
256
- 139 => 8249, # single left-pointing angle quotation mark
257
- 140 => 338, # latin capital ligature oe
258
- 142 => 381, # latin capital letter z with caron
259
- 145 => 8216, # left single quotation mark
260
- 146 => 8217, # right single quotation mark
261
- 147 => 8220, # left double quotation mark
262
- 148 => 8221, # right double quotation mark
263
- 149 => 8226, # bullet
264
- 150 => 8211, # en dash
265
- 151 => 8212, # em dash
266
- 152 => 732, # small tilde
267
- 153 => 8482, # trade mark sign
268
- 154 => 353, # latin small letter s with caron
269
- 155 => 8250, # single right-pointing angle quotation mark
270
- 156 => 339, # latin small ligature oe
271
- 158 => 382, # latin small letter z with caron
272
- 159 => 376} # latin capital letter y with diaeresis
273
-
274
- # http://www.w3.org/TR/REC-xml/#dt-chardata
275
- #
276
- PREDEFINED = {
277
- 38 => '&amp;', # ampersand
278
- 60 => '&lt;', # left angle bracket
279
- 62 => '&gt;'} # right angle bracket
280
-
281
- # http://www.w3.org/TR/REC-xml/#charsets
282
- #
283
- VALID = [[0x9, 0xA, 0xD], (0x20..0xD7FF), (0xE000..0xFFFD), (0x10000..0x10FFFF)]
284
-
285
- def XChar.escape(string)
286
- string.unpack('U*').map{|n| xchr(n)}.join # ASCII, UTF-8
287
- rescue
288
- string.unpack('C*').map{|n| xchr(n)}.join # ISO-8859-1, WIN-1252
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
- def XChar.xchr(n)
292
- (@xchr ||= {})[n] ||= ((
293
- n = XChar::CP1252[n] || n
294
- n = 42 unless XChar::VALID.find{|range| range.include? n}
295
- XChar::PREDEFINED[n] or (n<128 ? n.chr : "&##{n};")
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 => '&amp;', # ampersand
359
+ 60 => '&lt;', # left angle bracket
360
+ 62 => '&gt;'} # 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
- def Tagz.escapeHTML string
301
- XChar.escape(string)
302
- end
381
+ NoEscape = lambda{|v|v}
303
382
 
304
- module Globally; include Tagz; end
305
- def Tagz.globally
306
- Globally
383
+ module Globally; include ::Tagz; end
384
+ module Privately; include ::Tagz; end
307
385
  end
308
386
 
309
- module Privately; include Tagz; end
310
- def Tagz.privately
311
- Privately
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)}