mab 0.0.1
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/lib/mab.rb +5 -0
- data/lib/mab/builder.rb +45 -0
- data/lib/mab/indentation.rb +33 -0
- data/lib/mab/kernel_method.rb +6 -0
- data/lib/mab/mixin.rb +246 -0
- data/lib/mab/version.rb +4 -0
- metadata +73 -0
data/lib/mab.rb
ADDED
data/lib/mab/builder.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Mab
|
2
|
+
class SimpleBuilder
|
3
|
+
include Mixin
|
4
|
+
|
5
|
+
def initialize(assigns = {}, helper = nil, &blk)
|
6
|
+
@_helper = helper
|
7
|
+
@_result = []
|
8
|
+
|
9
|
+
assigns.each do |key, value|
|
10
|
+
instance_variable_set(:"@#{key}", value)
|
11
|
+
end
|
12
|
+
|
13
|
+
if helper
|
14
|
+
helper.instance_variables.each do |var|
|
15
|
+
instance_variable_set(var, helper.instance_variable_get(var))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
capture(&blk) if blk
|
20
|
+
end
|
21
|
+
|
22
|
+
def capture(&blk)
|
23
|
+
@_result << mab(&blk)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s; @_result.join end
|
27
|
+
|
28
|
+
def method_missing(name, *args, &blk)
|
29
|
+
if @_helper && @_helper.respond_to?(name, true)
|
30
|
+
@_helper.send(name, *args, &blk)
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Builder < SimpleBuilder
|
38
|
+
include HTML5
|
39
|
+
end
|
40
|
+
|
41
|
+
class PrettyBuilder < Builder
|
42
|
+
include Indentation
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Mab
|
2
|
+
module Indentation
|
3
|
+
def mab_insert(str)
|
4
|
+
if i = @mab_context.options[:indentation]
|
5
|
+
super([$/ + " " * i, str])
|
6
|
+
else
|
7
|
+
@mab_context.options[:indentation] = 0
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def mab_done(tag)
|
13
|
+
if blk = tag.block
|
14
|
+
tag.block = proc do
|
15
|
+
begin
|
16
|
+
@mab_context.options[:indentation] += 1
|
17
|
+
blk.call
|
18
|
+
ensure
|
19
|
+
@mab_context.options[:indentation] -= 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def reindent!(str)
|
27
|
+
str.split(/\r?\n/).each do |s|
|
28
|
+
text! s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
data/lib/mab/mixin.rb
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Mab
|
4
|
+
module Mixin
|
5
|
+
class Error < StandardError; end
|
6
|
+
class Tag
|
7
|
+
attr_accessor :name, :content, :block
|
8
|
+
attr_reader :options, :context, :instance
|
9
|
+
attr_writer :attributes, :pos
|
10
|
+
|
11
|
+
def initialize(name, options, context, instance = nil)
|
12
|
+
@name = name
|
13
|
+
@options = options
|
14
|
+
@context = context
|
15
|
+
@instance = instance
|
16
|
+
@done = false
|
17
|
+
@content = false
|
18
|
+
@pos = @context.size
|
19
|
+
end
|
20
|
+
|
21
|
+
def attributes
|
22
|
+
@attributes ||= {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def merge_attributes(attrs)
|
26
|
+
if defined?(@attributes)
|
27
|
+
@attributes.merge!(attrs)
|
28
|
+
else
|
29
|
+
@attributes = attrs
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(name, content = nil, attrs = nil, &blk)
|
34
|
+
name = name.to_s
|
35
|
+
|
36
|
+
if name[-1] == ?!
|
37
|
+
attributes[:id] = name[0..-2]
|
38
|
+
else
|
39
|
+
if attributes.has_key?(:class)
|
40
|
+
attributes[:class] += " #{name}"
|
41
|
+
else
|
42
|
+
attributes[:class] = name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
insert(content, attrs, &blk)
|
47
|
+
end
|
48
|
+
|
49
|
+
def insert(content = nil, attrs = nil, &blk)
|
50
|
+
raise Error, "This tag is already closed" if @done
|
51
|
+
|
52
|
+
if content.is_a?(Hash)
|
53
|
+
attrs = content
|
54
|
+
content = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
merge_attributes(attrs) if attrs
|
58
|
+
|
59
|
+
if block_given?
|
60
|
+
@block = blk
|
61
|
+
@done = true
|
62
|
+
elsif content
|
63
|
+
content = content.to_s
|
64
|
+
@content = CGI.escapeHTML(content)
|
65
|
+
@done = !content.empty?
|
66
|
+
elsif attrs
|
67
|
+
@done = true
|
68
|
+
end
|
69
|
+
|
70
|
+
@instance.mab_done(self) if @done
|
71
|
+
|
72
|
+
if @block
|
73
|
+
before = @context.children
|
74
|
+
res = @block.call
|
75
|
+
|
76
|
+
if before >= @context.children
|
77
|
+
@content = res.to_s
|
78
|
+
else
|
79
|
+
@content = nil
|
80
|
+
@instance.mab_insert("</#{@name}>")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_ary() nil end
|
88
|
+
def to_str() to_s end
|
89
|
+
|
90
|
+
def attrs_to_s
|
91
|
+
attributes.inject("") do |res, (name, value)|
|
92
|
+
if value
|
93
|
+
value = (value == true) ? name : CGI.escapeHTML(value.to_s)
|
94
|
+
res << " #{name}=\"#{value}\""
|
95
|
+
end
|
96
|
+
res
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_s
|
101
|
+
if !@context.joining? && @context[@pos]
|
102
|
+
@context[@pos] = nil
|
103
|
+
@context.children -= 1
|
104
|
+
end
|
105
|
+
res = "<#{@name}#{attrs_to_s}"
|
106
|
+
res << (@options[:xml] && @content == false ? ' />' : '>')
|
107
|
+
res << "#{@content}</#{@name}>" if @content
|
108
|
+
res
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class Context < Array
|
113
|
+
attr_accessor :children, :options
|
114
|
+
|
115
|
+
def initialize
|
116
|
+
@children = 0
|
117
|
+
@joining = false
|
118
|
+
@options = {}
|
119
|
+
end
|
120
|
+
|
121
|
+
def <<(str)
|
122
|
+
@children += 1
|
123
|
+
super(str)
|
124
|
+
end
|
125
|
+
|
126
|
+
def join(*)
|
127
|
+
@joining = true
|
128
|
+
super
|
129
|
+
end
|
130
|
+
|
131
|
+
def joining?
|
132
|
+
@joining
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def tag!(name, content = nil, attrs = nil, &blk)
|
137
|
+
ctx = @mab_context || raise(Error, "Tags can only be written within a `mab { }`-block")
|
138
|
+
tag = Tag.new(name, mab_options, ctx, self)
|
139
|
+
mab_insert(tag)
|
140
|
+
tag.insert(content, attrs, &blk)
|
141
|
+
end
|
142
|
+
|
143
|
+
def text!(str)
|
144
|
+
mab_insert(str)
|
145
|
+
end
|
146
|
+
|
147
|
+
def text(str)
|
148
|
+
text! CGI.escapeHTML(str.to_s)
|
149
|
+
end
|
150
|
+
|
151
|
+
def mab(&blk)
|
152
|
+
prev = defined?(@mab_context) && @mab_context
|
153
|
+
ctx = @mab_context = Context.new
|
154
|
+
res = instance_eval(&blk)
|
155
|
+
ctx.empty? ? res : ctx.join
|
156
|
+
ensure
|
157
|
+
@mab_context = prev
|
158
|
+
end
|
159
|
+
|
160
|
+
def mab_insert(tag)
|
161
|
+
ctx = @mab_context || raise(Error, 'mab { }-block required')
|
162
|
+
ctx << tag
|
163
|
+
end
|
164
|
+
|
165
|
+
def mab_done(tag)
|
166
|
+
end
|
167
|
+
|
168
|
+
def mab_options
|
169
|
+
@mab_options ||= {}
|
170
|
+
end
|
171
|
+
|
172
|
+
module XML
|
173
|
+
include Mixin
|
174
|
+
|
175
|
+
def mab_options
|
176
|
+
@mab_options ||= super.update(:xml => true)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
module HTMLDefiners
|
181
|
+
def define_tag(meth, tag)
|
182
|
+
class_eval <<-EOF
|
183
|
+
def #{meth}(content = "", attrs = nil, &blk)
|
184
|
+
if content.is_a?(Hash)
|
185
|
+
attrs = content
|
186
|
+
content = ""
|
187
|
+
end
|
188
|
+
tag!(:#{tag}, content, attrs, &blk)
|
189
|
+
end
|
190
|
+
EOF
|
191
|
+
end
|
192
|
+
|
193
|
+
def define_tags(*tags)
|
194
|
+
tags.flatten.each do |tag|
|
195
|
+
define_tag(tag, tag)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def define_empty_tag(meth, tag)
|
200
|
+
class_eval <<-EOF
|
201
|
+
def #{meth}(attrs = nil)
|
202
|
+
if (!attrs.nil? && !attrs.is_a?(Hash)) || block_given?
|
203
|
+
raise Error, "#{meth} doesn't allow content"
|
204
|
+
end
|
205
|
+
tag!(:#{tag}, attrs)
|
206
|
+
end
|
207
|
+
EOF
|
208
|
+
end
|
209
|
+
|
210
|
+
def define_empty_tags(*tags)
|
211
|
+
tags.flatten.each do |tag|
|
212
|
+
define_empty_tag(tag, tag)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
module HTML5
|
218
|
+
extend HTMLDefiners
|
219
|
+
include Mixin
|
220
|
+
|
221
|
+
define_tags %w[a abbr acronym address applet article aside audio b
|
222
|
+
basefont bdi bdo big blockquote body button canvas caption
|
223
|
+
center cite code colgroup datalist dd del details dfn dir div dl
|
224
|
+
dt em fieldset figcaption figure font footer form frame frameset
|
225
|
+
h1 h2 h3 h4 h5 h6 head header hgroup html i iframe ins kbd label
|
226
|
+
legend li link map mark math menu meter nav noframes noscript
|
227
|
+
object ol optgroup option output p pre progress q rp rt ruby s
|
228
|
+
samp script section select small span strike strong style sub
|
229
|
+
summary sup svg table tbody td textarea tfoot th thead time
|
230
|
+
title tr tt u ul var video xmp]
|
231
|
+
|
232
|
+
define_empty_tags %w[base link meta hr br wbr img embed param source
|
233
|
+
track area col input keygen command]
|
234
|
+
|
235
|
+
def doctype!
|
236
|
+
text! '<!DOCTYPE html>'
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
module XHTML5
|
241
|
+
include HTML5
|
242
|
+
include XML
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
data/lib/mab/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mab
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Magnus Holm
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &70107192708940 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70107192708940
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: minitest
|
27
|
+
requirement: &70107192708280 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70107192708280
|
36
|
+
description:
|
37
|
+
email:
|
38
|
+
- judofyr@gmail.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- lib/mab/builder.rb
|
44
|
+
- lib/mab/indentation.rb
|
45
|
+
- lib/mab/kernel_method.rb
|
46
|
+
- lib/mab/mixin.rb
|
47
|
+
- lib/mab/version.rb
|
48
|
+
- lib/mab.rb
|
49
|
+
homepage:
|
50
|
+
licenses: []
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.8.10
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Markup as Ruby
|
73
|
+
test_files: []
|