tagz 4.6.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/a.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  require 'tagz'
2
2
 
3
- include Tagz.globally
3
+ include Tagz.privately
4
4
 
5
- p a_{ false }
5
+ def bar
6
+ missing
7
+ end
8
+
9
+ puts div_{ 'foobar' }
10
+ bar
data/gemspec.rb CHANGED
@@ -24,10 +24,10 @@ Gem::Specification::new do |spec|
24
24
 
25
25
  spec.require_path = "lib"
26
26
 
27
- spec.has_rdoc = File::exist? "doc"
28
- spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
27
+ spec.has_rdoc = true #File::exist? "doc"
28
+ spec.test_suite_file = "test/#{ lib }.rb" if File::file?("test/#{ lib }.rb")
29
29
  #spec.add_dependency 'lib', '>= version'
30
- spec.add_dependency 'fattr'
30
+ #spec.add_dependency 'fattr'
31
31
 
32
32
  spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
33
33
 
@@ -1,3 +1,5 @@
1
+ #! /usr/bin/env ruby
2
+
1
3
  require 'pathname'
2
4
 
3
5
  $VERBOSE=nil
@@ -3,28 +3,174 @@ unless defined? Tagz
3
3
  module Tagz
4
4
  unless defined?(Tagz::VERSION)
5
5
  Tagz::VERSION = [
6
- Tagz::VERSION_MAJOR = 4,
7
- Tagz::VERSION_MINOR = 6,
6
+ Tagz::VERSION_MAJOR = 5,
7
+ Tagz::VERSION_MINOR = 0,
8
8
  Tagz::VERSION_TEENY = 0
9
9
  ].join('.')
10
10
  def Tagz.version() Tagz::VERSION end
11
11
  end
12
12
 
13
- def Tagz.escapeHTML string
14
- string = string.to_s.dup
15
- string.gsub!(%r/&/n, '&amp;')
16
- string.gsub!(%r/\"/n, '&quot;')
17
- string.gsub!(%r/>/n, '&gt;')
18
- string.gsub!(%r/</n, '&lt;')
19
- string
13
+ private
14
+
15
+ # open_tag
16
+ #
17
+ def tagz__ name, *argv, &block
18
+ options = argv.last.is_a?(Hash) ? argv.pop : {}
19
+ content = argv
20
+
21
+ unless options.empty?
22
+ attributes = ' ' <<
23
+ options.map do |key, value|
24
+ key = XChar.escape key.to_s
25
+ value = XChar.escape value.to_s
26
+ if value =~ %r/"/
27
+ raise ArgumentError, value if value =~ %r/'/
28
+ value = "'#{ value }'"
29
+ else
30
+ raise ArgumentError, value if value =~ %r/"/
31
+ value = "\"#{ value }\""
32
+ end
33
+ [key, value].join('=')
34
+ end.join(' ')
35
+ else
36
+ attributes = ''
37
+ end
38
+
39
+ tagz.concat "<#{ name }#{ attributes }>"
40
+
41
+ if content.empty?
42
+ if block
43
+ size = tagz.size
44
+ value = block.call(tagz)
45
+ if NilClass === value
46
+ tagz[-1] = "/>"
47
+ else
48
+ tagz << value.to_s unless(tagz.size > size)
49
+ tagz.concat "</#{ name }>"
50
+ end
51
+ end
52
+ else
53
+ tagz << content.join
54
+ if block
55
+ size = tagz.size
56
+ value = block.call(tagz)
57
+ tagz << value.to_s unless(tagz.size > size)
58
+ end
59
+ tagz.concat "</#{ name }>"
60
+ end
61
+
62
+ tagz
20
63
  end
21
64
 
22
- class Fragment < ::String
23
- def << other
24
- super other.to_s
65
+ # close_tag
66
+ #
67
+ def __tagz tag, *a, &b
68
+ tagz.concat "</#{ tag }>"
69
+ end
70
+
71
+ # access tagz doc and enclose tagz operations
72
+ #
73
+ def tagz document = nil, &block
74
+ @tagz ||= nil ## shut wornings up
75
+ previous = @tagz
76
+
77
+ if block
78
+ @tagz ||= (Document.for(document) || Document.new)
79
+ begin
80
+ size = @tagz.size
81
+ value = instance_eval(&block)
82
+ @tagz << value unless(@tagz.size > size)
83
+ @tagz
84
+ ensure
85
+ @tagz = previous
86
+ end
87
+ else
88
+ document ? Document.for(document) : @tagz
89
+ end
90
+ end
91
+
92
+ # catch special tagz methods
93
+ #
94
+ def method_missing m, *a, &b
95
+ strategy =
96
+ case m.to_s
97
+ when %r/^(.*[^_])_(!)?$/o
98
+ :open_tag
99
+ when %r/^_([^_].*)$/o
100
+ :close_tag
101
+ when 'e'
102
+ :element
103
+ when '__', '___'
104
+ :puts
105
+ else
106
+ nil
107
+ end
108
+
109
+ if(strategy.nil? or (tagz.nil? and not Globally===self))
110
+ begin
111
+ super
112
+ ensure
113
+ $!.set_backtrace caller(skip=1) if $!
114
+ end
115
+ end
116
+
117
+ case strategy
118
+ when :open_tag
119
+ m, bang = $1, $2
120
+ b ||= lambda{} if bang
121
+ tagz{ tagz__(m, *a, &b) }
122
+ when :close_tag
123
+ m = $1
124
+ tagz{ __tagz(m, *a, &b) }
125
+ when :element
126
+ Element.new(*a, &b)
127
+ when :puts
128
+ tagz do
129
+ tagz.concat("\n")
130
+ unless a.empty?
131
+ tagz.concat(a.join)
132
+ tagz.concat("\n")
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ class Document < ::String
139
+ def Document.for other
140
+ Document === other ? other : Document.new(other.to_s)
141
+ end
142
+
143
+ def element
144
+ Element.new(*a, &b)
145
+ end
146
+ alias_method 'e', 'element'
147
+
148
+ def << string
149
+ case string
150
+ when Document
151
+ super string.to_s
152
+ else
153
+ super XChar.escape(string.to_s)
154
+ end
25
155
  self
26
156
  end
27
157
 
158
+ def escape(*strings)
159
+ XChar.escape(strings.join)
160
+ end
161
+ alias_method 'h', 'escape'
162
+
163
+ def puts string
164
+ concat "#{ string }\n"
165
+ end
166
+ alias_method 'push', 'concat'
167
+ alias_method 'write', 'concat'
168
+
169
+ def document
170
+ self
171
+ end
172
+ alias_method 'doc', 'document'
173
+
28
174
  def + other
29
175
  self.dup << other
30
176
  end
@@ -43,8 +189,8 @@ unless defined? Tagz
43
189
  unless options.empty?
44
190
  ' ' <<
45
191
  options.map do |key, value|
46
- key = Tagz.escapeHTML key.to_s
47
- value = Tagz.escapeHTML value.to_s
192
+ key = XChar.escape key.to_s
193
+ value = XChar.escape value.to_s
48
194
  if value =~ %r/"/
49
195
  raise ArgumentError, value if value =~ %r/'/
50
196
  value = "'#{ value }'"
@@ -87,144 +233,79 @@ unless defined? Tagz
87
233
  end
88
234
  end
89
235
 
90
- def Tagz.export *methods
91
- methods.flatten.compact.uniq.each do |m|
92
- module_function m
93
- end
94
- end
95
-
96
- def Tagz.<< other
97
- Tagz.tagz << other
98
- self
99
- end
100
-
101
- module Globally
102
- private
103
- include Tagz
104
- def method_missing m, *a, &b
105
- tagz{ super }
106
- end
107
- end
108
-
109
- def Tagz.globally
110
- Globally
111
- end
112
-
113
- private
236
+ module XChar
237
+ # http://intertwingly.net/stories/2004/04/14/i18n.html#CleaningWindows
238
+ #
239
+ CP1252 = {
240
+ 128 => 8364, # euro sign
241
+ 130 => 8218, # single low-9 quotation mark
242
+ 131 => 402, # latin small letter f with hook
243
+ 132 => 8222, # double low-9 quotation mark
244
+ 133 => 8230, # horizontal ellipsis
245
+ 134 => 8224, # dagger
246
+ 135 => 8225, # double dagger
247
+ 136 => 710, # modifier letter circumflex accent
248
+ 137 => 8240, # per mille sign
249
+ 138 => 352, # latin capital letter s with caron
250
+ 139 => 8249, # single left-pointing angle quotation mark
251
+ 140 => 338, # latin capital ligature oe
252
+ 142 => 381, # latin capital letter z with caron
253
+ 145 => 8216, # left single quotation mark
254
+ 146 => 8217, # right single quotation mark
255
+ 147 => 8220, # left double quotation mark
256
+ 148 => 8221, # right double quotation mark
257
+ 149 => 8226, # bullet
258
+ 150 => 8211, # en dash
259
+ 151 => 8212, # em dash
260
+ 152 => 732, # small tilde
261
+ 153 => 8482, # trade mark sign
262
+ 154 => 353, # latin small letter s with caron
263
+ 155 => 8250, # single right-pointing angle quotation mark
264
+ 156 => 339, # latin small ligature oe
265
+ 158 => 382, # latin small letter z with caron
266
+ 159 => 376} # latin capital letter y with diaeresis
114
267
 
115
- def tagz__ name, *argv, &block
116
- options = {}
117
- content = []
268
+ # http://www.w3.org/TR/REC-xml/#dt-chardata
269
+ #
270
+ PREDEFINED = {
271
+ 38 => '&amp;', # ampersand
272
+ 60 => '&lt;', # left angle bracket
273
+ 62 => '&gt;'} # right angle bracket
118
274
 
119
- argv.each do |arg|
120
- case arg
121
- when Hash
122
- options.update arg
123
- else
124
- content.push arg
125
- end
126
- end
275
+ # http://www.w3.org/TR/REC-xml/#charsets
276
+ #
277
+ VALID = [[0x9, 0xA, 0xD], (0x20..0xD7FF), (0xE000..0xFFFD), (0x10000..0x10FFFF)]
127
278
 
128
- unless options.empty?
129
- attributes = ' ' <<
130
- options.map do |key, value|
131
- key = Tagz.escapeHTML key.to_s
132
- value = Tagz.escapeHTML value.to_s
133
- if value =~ %r/"/
134
- raise ArgumentError, value if value =~ %r/'/
135
- value = "'#{ value }'"
136
- else
137
- raise ArgumentError, value if value =~ %r/"/
138
- value = "\"#{ value }\""
139
- end
140
- [key, value].join('=')
141
- end.join(' ')
142
- else
143
- attributes = ''
279
+ def XChar.escape(string)
280
+ string.unpack('U*').map{|n| xchr(n)}.join # ASCII, UTF-8
281
+ rescue
282
+ string.unpack('C*').map{|n| xchr(n)}.join # ISO-8859-1, WIN-1252
144
283
  end
145
284
 
146
- tagz << "<#{ name }#{ attributes }>"
147
-
148
- if content.empty?
149
- if block
150
- size = tagz.size
151
- value = block.call(tagz)
152
- if NilClass === value
153
- tagz[-1] = "/>"
154
- else
155
- tagz << value.to_s unless(Fragment === value or tagz.size > size)
156
- tagz << "</#{ name }>"
157
- end
158
- end
159
- else
160
- content.each{|c| tagz << c.to_s unless Fragment === c}
161
- if block
162
- size = tagz.size
163
- value = block.call(tagz)
164
- tagz << value.to_s unless(Fragment === value or tagz.size > size)
165
- end
166
- tagz << "</#{ name }>"
285
+ def XChar.xchr(n)
286
+ (@xchr ||= {})[n] ||= ((
287
+ n = XChar::CP1252[n] || n
288
+ n = 42 unless XChar::VALID.find{|range| range.include? n}
289
+ XChar::PREDEFINED[n] or (n<128 ? n.chr : "&##{n};")
290
+ ))
167
291
  end
168
-
169
- tagz
170
292
  end
171
293
 
172
- def __tagz tag, *a, &b
173
- tagz << "</#{ tag }>"
294
+ def Tagz.escapeHTML string
295
+ XChar.escape(string)
174
296
  end
175
297
 
176
- def tagz &block
177
- if block
178
- if not defined?(@tagz) or @tagz.nil?
179
- @tagz = Fragment.new
180
- top = true
181
- end
182
- begin
183
- size = @tagz.size
184
- value = instance_eval(&block)
185
- @tagz << value unless(Fragment === value or @tagz.size > size)
186
- @tagz
187
- ensure
188
- @tagz = nil if top
189
- end
190
- else
191
- @tagz if defined? @tagz
192
- end
298
+ module Globally; include Tagz; end
299
+ def Tagz.globally
300
+ Globally
193
301
  end
194
302
 
195
- def method_missing m, *a, &b
196
- if not Globally === self
197
- unless defined?(@tagz) and @tagz
198
- begin
199
- super
200
- ensure
201
- $!.set_backtrace caller(skip=1) if $!
202
- end
203
- end
204
- end
205
-
206
- case m.to_s
207
- when %r/^(.*[^_])_(!)?$/o
208
- m, bang = $1, $2
209
- b ||= lambda{} if bang
210
- tagz{ tagz__(m, *a, &b) }
211
- when %r/^_([^_].*)$/o
212
- m = $1
213
- tagz{ __tagz(m, *a, &b) }
214
- when 'e'
215
- Element.new(*a, &b)
216
- when '__'
217
- tagz{ tagz << "\n"; a.each{|s| tagz << s}; }
218
- else
219
- begin
220
- super
221
- ensure
222
- $!.set_backtrace caller(skip=1) if $!
223
- end
224
- end
303
+ module Privately; include Tagz; end
304
+ def Tagz.privately
305
+ Privately
225
306
  end
226
307
 
227
- export %w( tagz tagz__ __tagz method_missing )
308
+ %w( tagz tagz__ __tagz method_missing ).each{|m| module_function(m)}
228
309
  end
229
310
 
230
311
  def Tagz *argv, &block
data/prof.rb ADDED
@@ -0,0 +1,25 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'ruby-prof'
5
+
6
+ $:.unshift File.dirname(__FILE__)
7
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
8
+
9
+ require 'tagz'
10
+
11
+ RubyProf.start
12
+
13
+ include Tagz.globally
14
+
15
+ 1000.times do
16
+ div_(:class => 'speedtest'){
17
+ a_(:href => 'foo&bar'){ 'foo&bar' }
18
+ }
19
+ end
20
+
21
+
22
+ result = RubyProf.stop
23
+
24
+ printer = RubyProf::FlatPrinter.new(result)
25
+ printer.print(STDOUT, 0)
@@ -3,7 +3,8 @@
3
3
  # the need for '<% rows.each do |row| %> ... <% row.each do |cell| %> '
4
4
  # madness and other types of logic to be coded in the templating language,
5
5
  # leaving templating to template engines and logic and looping to ruby -
6
- # unencumbered by extra funky syntax
6
+ # unencumbered by extra funky syntax. in rails tagz will automatically be
7
+ # available in your erb templates.
7
8
  #
8
9
 
9
10
  require 'tagz'
@@ -17,21 +18,15 @@ template = ERB.new <<-ERB
17
18
  <html>
18
19
  <body>
19
20
  <%=
20
-
21
- if rows
22
-
23
- table_{
24
- rows.each do |row|
25
- tr_{
26
- row.each do |cell|
27
- td_{ cell }
28
- end
29
- }
30
- end
31
- }
32
-
33
- end
34
-
21
+ table_{
22
+ rows.each do |row|
23
+ tr_{
24
+ row.each do |cell|
25
+ td_{ cell }
26
+ end
27
+ }
28
+ end
29
+ }
35
30
  %>
36
31
  </body>
37
32
  </html>
@@ -12,13 +12,13 @@ def header
12
12
  html_
13
13
  body_(:class => 'ninja-like', :id => 'giraffe-slayer')
14
14
 
15
- tagz << "\n<!-- this is the header -->\n"
15
+ ___ "<!-- this is the header -->"
16
16
  }
17
17
  end
18
18
 
19
19
  def footer
20
20
  tagz{
21
- tagz << "\n<!-- this is the footer -->\n"
21
+ ___ "<!-- this is the footer -->"
22
22
 
23
23
  body_
24
24
  html_
@@ -3,15 +3,20 @@
3
3
  # but can sometimes make reading the generated html a bit rough. of course
4
4
  # using tidy or the dom inspector in firebug obviates the issue; nevertheless
5
5
  # it's sometime nice to break things up a little. you can use 'tagz << "\n"'
6
- # or the special shorthand '__' to accomplish this
6
+ # or the special shorthand '__' or '___' to accomplish this
7
7
  #
8
8
 
9
9
  require 'tagz'
10
10
  include Tagz.globally
11
11
 
12
- p div_{
13
- span_{ true }
14
- __
15
- span_{ false } # hey ryan, i fixed this ;-)
16
- __
17
- }
12
+ html =
13
+ div_{
14
+ span_{ true }
15
+ __
16
+ span_{ false } # hey ryan, i fixed this ;-)
17
+ ___
18
+
19
+ ___ 'foo & escaped bar'
20
+ }
21
+
22
+ puts html
@@ -0,0 +1,19 @@
1
+ # tagz gives you low-level control of the output and makes even dashersized
2
+ # xml tagz easy enough to work with
3
+ #
4
+
5
+ require 'tagz'
6
+ include Tagz.globally
7
+
8
+ xml =
9
+ root_{
10
+ tagz__('foo-bar', :key => 'foo&bar'){ 'content' }
11
+
12
+ tagz__('bar-foo')
13
+ tagz.concat 'content'
14
+ tagz.concat tagz.escape('foo&bar')
15
+ __tagz('bar-foo')
16
+ }
17
+
18
+ puts xml
19
+
@@ -1,8 +1,13 @@
1
+ #! /usr/bin/env ruby
2
+
1
3
  require 'test/unit'
4
+
5
+ $VERBOSE = 2
2
6
  STDOUT.sync = true
3
7
  $:.unshift 'lib'
4
8
  $:.unshift '../lib'
5
9
  $:.unshift '.'
10
+
6
11
  require 'tagz'
7
12
 
8
13
  class TagzTest < Test::Unit::TestCase
@@ -395,7 +400,7 @@ class TagzTest < Test::Unit::TestCase
395
400
  actual = tagz{
396
401
  html_{
397
402
  body_{
398
- links.map{|link| e(:a, :href => link){ link }}.join e(:span){ '|' }
403
+ tagz.write links.map{|link| e(:a, :href => link){ link }}.join(e(:span){ '|' })
399
404
  }
400
405
  }
401
406
  }
@@ -467,4 +472,68 @@ class TagzTest < Test::Unit::TestCase
467
472
  }
468
473
  assert_equal expected, actual
469
474
  end
475
+
476
+ def test_390
477
+ expected = '<div class="bar&amp;foo&gt;">foo&amp;bar&gt;</div>'
478
+ # actual = tagz{ div_(:class => 'bar&foo>'){|t| t.h('foo&bar>') } }
479
+ actual = tagz{ div_(:class => 'bar&foo>'){ 'foo&bar>' } }
480
+ assert_equal expected, actual
481
+
482
+ expected = %|<div class="bar&amp;foo&gt;">#{ expected }</div>|
483
+ actual = tagz{ div_(:class => 'bar&foo>'){ actual } }
484
+ assert_equal expected, actual
485
+ end
486
+
487
+ def test_400
488
+ expected = '<div><span>foo&amp;bar</span></div>'
489
+ actual = tagz{ div_{ span_{ 'foo&bar' } } }
490
+ assert_equal expected, actual
491
+ end
492
+
493
+ def test_410
494
+ expected = '<div>false</div>'
495
+ actual = tagz{ div_{ false } }
496
+ assert_equal expected, actual
497
+ end
498
+
499
+ def test_420
500
+ expected = "<div>\n<span>foobar</span>\nfoobar\n</div>"
501
+ actual = tagz{ div_{ __; span_{ :foobar }; ___('foobar'); } }
502
+ assert_equal expected, actual
503
+ end
504
+
505
+ def test_430
506
+ c = Class.new{
507
+ include Tagz.globally
508
+ def foobar() div_{ 'foobar' } end
509
+ }.new
510
+
511
+ actual=nil
512
+ assert_nothing_raised{ actual=c.foobar }
513
+ expected = '<div>foobar</div>'
514
+ assert_equal expected, actual
515
+
516
+ =begin
517
+ e = nil
518
+ assert_raises(NoMethodError){ begin; c.missing; ensure; e=$!; end }
519
+ assert e
520
+ messages = e.backtrace.map{|line| line.split(%r/:/, 3).last}
521
+ assert messages.all?{|message| message !~ /tagz/}
522
+ =end
523
+ end
524
+
525
+ def test_440
526
+ c = Class.new{
527
+ include Tagz
528
+ def foobar() tagz{ div_{ 'foobar' } } end
529
+ def barfoo() div_{ 'barfoo' } end
530
+ }.new
531
+
532
+ actual=nil
533
+ assert_nothing_raised{ actual=c.foobar }
534
+ expected = '<div>foobar</div>'
535
+ assert_equal expected, actual
536
+
537
+ assert_raises(NoMethodError){ c.barfoo }
538
+ end
470
539
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tagz
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.6.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ara T. Howard
@@ -9,19 +9,10 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-06 00:00:00 -07:00
12
+ date: 2009-03-23 00:00:00 -06:00
13
13
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: fattr
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
24
- version:
14
+ dependencies: []
15
+
25
16
  description:
26
17
  email: ara.t.howard@gmail.com
27
18
  executables: []
@@ -37,6 +28,7 @@ files:
37
28
  - install.rb
38
29
  - lib
39
30
  - lib/tagz.rb
31
+ - prof.rb
40
32
  - README
41
33
  - samples
42
34
  - samples/a.rb
@@ -45,9 +37,10 @@ files:
45
37
  - samples/d.rb
46
38
  - samples/e.rb
47
39
  - samples/f.rb
40
+ - samples/g.rb
48
41
  - test
49
42
  - test/tagz.rb
50
- has_rdoc: false
43
+ has_rdoc: true
51
44
  homepage: http://codeforpeople.com/lib/ruby/tagz/
52
45
  post_install_message:
53
46
  rdoc_options: []