tagz 4.6.0 → 5.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/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: []