markaby 0.8.1 → 0.9.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.
@@ -1,5 +1,5 @@
1
- require 'markaby/tags'
2
- require 'markaby/builder_tags'
1
+ require "markaby/tagset"
2
+ require "markaby/builder_tags"
3
3
 
4
4
  module Markaby
5
5
  RUBY_VERSION_ID = RUBY_VERSION.split(".").join.to_i
@@ -23,30 +23,13 @@ module Markaby
23
23
  #
24
24
  class Builder
25
25
  include Markaby::BuilderTags
26
-
27
- DEFAULT_OPTIONS = {
28
- :indent => 0,
29
- :output_helpers => true,
30
- :output_xml_instruction => true,
31
- :output_meta_tag => 'xhtml',
32
- :auto_validation => true,
33
- :tagset => Markaby::XHTMLTransitional,
34
- :root_attributes => {
35
- :xmlns => 'http://www.w3.org/1999/xhtml',
36
- :'xml:lang' => 'en',
37
- :lang => 'en'
38
- }
26
+ GENERIC_OPTIONS = {
27
+ indent: 0,
28
+ auto_validation: true
39
29
  }
40
30
 
41
- HTML5_OPTIONS = {
42
- :indent => 0,
43
- :output_helpers => true,
44
- :output_xml_instruction => false,
45
- :output_meta_tag => 'html5',
46
- :auto_validation => true,
47
- :tagset => Markaby::HTML5,
48
- :root_attributes => {}
49
- }
31
+ HTML5_OPTIONS = HTML5.default_options.dup
32
+ DEFAULT_OPTIONS = GENERIC_OPTIONS.merge(HTML5_OPTIONS)
50
33
 
51
34
  @@options = DEFAULT_OPTIONS.dup
52
35
 
@@ -54,10 +37,6 @@ module Markaby
54
37
  @@options = DEFAULT_OPTIONS.dup
55
38
  end
56
39
 
57
- def self.set_html5_options!
58
- @@options = HTML5_OPTIONS.dup
59
- end
60
-
61
40
  def self.set(option, value)
62
41
  @@options[option] = value
63
42
  end
@@ -66,15 +45,15 @@ module Markaby
66
45
  @@options[option]
67
46
  end
68
47
 
69
- def self.ignored_helpers
70
- @@ignored_helpers ||= []
71
- end
48
+ attr_reader :tagset
72
49
 
73
- def self.ignore_helpers(*helpers)
74
- ignored_helpers.concat helpers
75
- end
50
+ def tagset=(tagset)
51
+ @tagset = tagset
76
52
 
77
- attr_accessor :output_helpers, :tagset
53
+ tagset.default_options.each do |k, v|
54
+ instance_variable_set("@#{k}".to_sym, v)
55
+ end
56
+ end
78
57
 
79
58
  # Create a Markaby builder object. Pass in a hash of variable assignments to
80
59
  # +assigns+ which will be available as instance variables inside tag construction
@@ -105,13 +84,11 @@ module Markaby
105
84
  instance_variable_set("@#{k}", v)
106
85
  end
107
86
 
108
- if helper
109
- helper.instance_variables.each do |iv|
110
- instance_variable_set(iv, helper.instance_variable_get(iv))
111
- end
87
+ helper&.instance_variables&.each do |iv|
88
+ instance_variable_set(iv, helper.instance_variable_get(iv))
112
89
  end
113
90
 
114
- @builder = XmlMarkup.new(:indent => @indent, :target => @streams.last)
91
+ @builder = XmlMarkup.new(indent: @indent, target: @streams.last)
115
92
 
116
93
  text(capture(&block)) if block
117
94
  end
@@ -170,50 +147,24 @@ module Markaby
170
147
  # Create a tag named +tag+. Other than the first argument which is the tag name,
171
148
  # the arguments are the same as the tags implemented via method_missing.
172
149
  def tag!(tag, *args, &block)
173
- ele_id = nil
150
+ attributes = {}
174
151
  if @auto_validation && @tagset
175
- if !@tagset.tagset.has_key?(tag)
176
- raise InvalidXhtmlError, "no element `#{tag}' for #{tagset.doctype}"
177
- elsif args.last.respond_to?(:to_hash)
178
- attrs = args.last.to_hash
179
-
180
- if @tagset.forms.include?(tag) && attrs[:id]
181
- attrs[:name] ||= attrs[:id]
182
- end
183
-
184
- attrs.each do |k, v|
185
- atname = k.to_s.downcase.intern
186
- unless k =~ /:/ or @tagset.tagset[tag].include? atname
187
- raise InvalidXhtmlError, "no attribute `#{k}' on #{tag} elements"
188
- end
189
- if atname == :id
190
- ele_id = v.to_s
191
- if @used_ids.has_key? ele_id
192
- raise InvalidXhtmlError, "id `#{ele_id}' already used (id's must be unique)."
193
- end
194
- end
195
- if AttrsBoolean.include? atname
196
- if v
197
- attrs[k] = atname.to_s
198
- else
199
- attrs.delete k
200
- end
201
- end
202
- end
203
- end
152
+ attributes = @tagset.validate_and_transform_attributes!(tag, *args)
153
+ tag = @tagset.validate_and_transform_tag_name! tag
204
154
  end
205
-
155
+ element_id = attributes[:id].to_s
156
+ raise InvalidXhtmlError, "id `#{element_id}' already used (id's must be unique)." if @used_ids.has_key?(element_id)
206
157
  if block
207
158
  str = capture(&block)
208
159
  block = proc { text(str) }
209
160
  end
210
161
 
211
162
  f = fragment { @builder.tag!(tag, *args, &block) }
212
- @used_ids[ele_id] = f if ele_id
163
+ @used_ids[element_id] = f unless element_id.empty?
213
164
  f
214
165
  end
215
166
 
216
- private
167
+ private
217
168
 
218
169
  # This method is used to intercept calls to helper methods and instance
219
170
  # variables. Here is the order of interception:
@@ -224,37 +175,40 @@ module Markaby
224
175
  # * If +sym+ is also the name of an instance variable, the
225
176
  # value of the instance variable is returned.
226
177
  # * If +sym+ has come this far and no +tagset+ is found, +sym+ and its arguments are passed to tag!
227
- # * If a tagset is found, though, +NoMethodError+ is raised.
178
+ # * If a tagset is found, the tagset is tole to handle +sym+
228
179
  #
229
180
  # method_missing used to be the lynchpin in Markaby, but it's no longer used to handle
230
181
  # HTML tags. See html_tag for that.
231
182
  def method_missing(sym, *args, &block)
232
- if @_helper.respond_to?(sym, true) && !self.class.ignored_helpers.include?(sym)
233
- r = @_helper.send(sym, *args, &block)
234
- if @output_helpers && r.respond_to?(:to_str)
235
- fragment { @builder << r }
236
- else
237
- r
238
- end
239
- elsif @assigns.has_key?(sym)
240
- @assigns[sym]
241
- elsif @assigns.has_key?(stringy_key = sym.to_s)
242
- # Rails' ActionView assigns hash has string keys for
243
- # instance variables that are defined in the controller.
244
- @assigns[stringy_key]
245
- elsif instance_variables_for(self).include?(ivar = "@#{sym}".to_sym)
246
- instance_variable_get(ivar)
247
- elsif @_helper && instance_variables_for(@_helper).include?(ivar)
248
- @_helper.instance_variable_get(ivar)
249
- elsif instance_methods_for(::Builder::XmlMarkup).include?(sym)
250
- @builder.__send__(sym, *args, &block)
251
- elsif !@tagset
252
- tag!(sym, *args, &block)
253
- else
254
- super
183
+ case response_for(sym)
184
+ when :helper then @_helper.send(sym, *args, &block)
185
+ when :assigns then @assigns[sym]
186
+ when :stringy_assigns then @assigns[sym.to_s]
187
+ when :ivar then instance_variable_get(ivar)
188
+ when :helper_ivar then @_helper.instance_variable_get(ivar)
189
+ when :xml_markup then @builder.__send__(sym, *args, &block)
190
+ when :tag then tag!(sym, *args, &block)
191
+ when :tagset then @tagset.handle_tag sym, self, *args, &block
192
+ else super
255
193
  end
256
194
  end
257
195
 
196
+ def response_for sym
197
+ return :helper if @_helper.respond_to?(sym, true)
198
+ return :assigns if @assigns.has_key?(sym)
199
+ return :stringy_assigns if @assigns.has_key?(sym.to_s)
200
+ return :ivar if instance_variables_for(self).include?(ivar = "@#{sym}".to_sym)
201
+ return :helper_ivar if @_helper && instance_variables_for(@_helper).include?(ivar)
202
+ return :xml_markup if instance_methods_for(::Builder::XmlMarkup).include?(sym)
203
+ return :tag if @tagset.nil?
204
+ return :tagset if @tagset.can_handle? sym
205
+ nil
206
+ end
207
+
208
+ def respond_to_missing? sym, include_private = false
209
+ !response_for(sym).nil?
210
+ end
211
+
258
212
  if RUBY_VERSION_ID >= 191
259
213
  def instance_variables_for(obj)
260
214
  obj.instance_variables
@@ -301,11 +255,15 @@ module Markaby
301
255
  undef_method method if method_defined?(method)
302
256
  end
303
257
 
304
- private
258
+ private
305
259
 
306
- def method_missing(*args, &block)
260
+ def method_missing(...)
307
261
  transform_stream unless transformed_stream?
308
- @str.__send__(*args, &block)
262
+ @str.__send__(...)
263
+ end
264
+
265
+ def respond_to_missing? sym, *args
266
+ @str.respond_to? sym
309
267
  end
310
268
 
311
269
  def transform_stream
@@ -1,7 +1,9 @@
1
+ require "markaby/html5"
2
+
1
3
  module Markaby
2
4
  module BuilderTags
3
5
  (HTML5.tags - [:head]).each do |k|
4
- class_eval <<-CODE, __FILE__, __LINE__
6
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
5
7
  def #{k}(*args, &block)
6
8
  html_tag(#{k.inspect}, *args, &block)
7
9
  end
@@ -28,8 +30,8 @@ module Markaby
28
30
  # set to <tt>text/html; charset=utf-8</tt>.
29
31
  def head(*args, &block)
30
32
  tag!(:head, *args) do
31
- tag!(:meta, "http-equiv" => "Content-Type", "content" => "text/html; charset=utf-8") if @output_meta_tag == 'xhtml'
32
- tag!(:meta, "charset" => "utf-8") if @output_meta_tag == 'html5'
33
+ tag!(:meta, "http-equiv" => "Content-Type", "content" => "text/html; charset=utf-8") if @output_meta_tag == "xhtml"
34
+ tag!(:meta, "charset" => "utf-8") if @output_meta_tag == "html5"
33
35
  instance_eval(&block)
34
36
  end
35
37
  end
@@ -56,19 +58,15 @@ module Markaby
56
58
 
57
59
  # Builds an html tag with HTML5 doctype instead.
58
60
  def html5(attrs = {}, &block)
59
- enable_html5!
61
+ self.tagset = Markaby::HTML5
60
62
  html5_html(attrs, &block)
61
63
  end
62
64
 
63
65
  def enable_html5!
64
- self.tagset = Markaby::HTML5
65
-
66
- Markaby::Builder::HTML5_OPTIONS.each do |k, v|
67
- self.instance_variable_set("@#{k}".to_sym, v)
68
- end
66
+ raise NotImplementedError, "Deprecated! Call self.tagset = Markaby::HTML5"
69
67
  end
70
68
 
71
- private
69
+ private
72
70
 
73
71
  def xhtml_html(attrs = {}, &block)
74
72
  instruct! if @output_xml_instruction
@@ -6,9 +6,9 @@ module Markaby
6
6
  class CssProxy
7
7
  def initialize(builder, stream, sym)
8
8
  @builder = builder
9
- @stream = stream
10
- @sym = sym
11
- @attrs = {}
9
+ @stream = stream
10
+ @sym = sym
11
+ @attrs = {}
12
12
 
13
13
  @original_stream_length = @stream.length
14
14
 
@@ -16,10 +16,10 @@ module Markaby
16
16
  end
17
17
 
18
18
  def respond_to?(sym, include_private = false)
19
- include_private || !private_methods.map { |m| m.to_sym }.include?(sym.to_sym) ? true : false
19
+ (include_private || !private_methods.map { |m| m.to_sym }.include?(sym.to_sym)) ? true : false
20
20
  end
21
21
 
22
- private
22
+ private
23
23
 
24
24
  # Adds attributes to an element. Bang methods set the :id attribute.
25
25
  # Other methods add to the :class attribute.
@@ -0,0 +1,118 @@
1
+ require "markaby/xhtml_transitional"
2
+ module Markaby
3
+ class HTML5 < Tagset
4
+ class << self
5
+ def default_options
6
+ super.merge({
7
+ output_xml_instruction: false,
8
+ output_meta_tag: "html5",
9
+ root_attributes: {}
10
+ })
11
+ end
12
+
13
+ def custom_element? tag_name
14
+ tag_name.to_s.include? "_"
15
+ end
16
+
17
+ def can_handle? tag_name
18
+ custom_element? tag_name
19
+ end
20
+
21
+ def handle_tag tag_name, builder, *args, &block
22
+ builder.tag! tag_name, *args, &block
23
+ end
24
+
25
+ def validate_and_transform_tag_name! tag_name
26
+ custom_element?(tag_name) ? custom_element_tag_for(tag_name) : super
27
+ end
28
+
29
+ def custom_element_tag_for tag_name
30
+ tag_name.to_s.tr("_", "-").to_sym
31
+ end
32
+
33
+ def validate_attribute! tag_name, attribute_name
34
+ custom_element?(tag_name) || super
35
+ end
36
+ end
37
+
38
+ @doctype = ["html"]
39
+ @tagset = XHTMLTransitional.tagset.merge({
40
+ abbr: Attrs,
41
+ article: Attrs,
42
+ aside: Attrs,
43
+ audio: Attrs,
44
+ bdi: Attrs,
45
+ canvas: Attrs,
46
+ command: Attrs,
47
+ datalist: Attrs,
48
+ details: Attrs,
49
+ embed: Attrs,
50
+ figure: Attrs,
51
+ figcaption: Attrs,
52
+ footer: Attrs,
53
+ header: Attrs,
54
+ hgroup: Attrs,
55
+ keygen: Attrs,
56
+ mark: Attrs,
57
+ menu: Attrs,
58
+ meter: Attrs,
59
+ nav: Attrs,
60
+ output: Attrs,
61
+ progress: Attrs,
62
+ rp: Attrs,
63
+ rt: Attrs,
64
+ ruby: Attrs,
65
+ section: Attrs,
66
+ source: Attrs,
67
+ time: Attrs,
68
+ track: Attrs,
69
+ video: Attrs,
70
+ wbr: Attrs
71
+ })
72
+
73
+ # Additional attributes found in HTML5
74
+ additional_tags = {
75
+ a: [:media, :download, :ping],
76
+ area: [:media, :download, :ping, :hreflang, :rel, :type],
77
+ base: [:target],
78
+ button: [:autofocus, :form, :formaction, :formenctype, :formmethod,
79
+ :formnovalidate, :formtarget],
80
+ fieldset: [:form, :disabled, :name],
81
+ form: [:novalidate],
82
+ label: [:form],
83
+ html: [:manifest],
84
+ iframe: [:sandbox, :seamless, :srcdoc],
85
+ img: [:crossorigin],
86
+ input: [:autofocus, :placeholder, :form, :required, :autocomplete,
87
+ :min, :max, :multiple, :pattern, :step, :list, :width, :height,
88
+ :dirname, :formaction, :formenctype, :formmethod,
89
+ :formnovalidate, :formtarget],
90
+ link: [:sizes],
91
+ meta: [:charset],
92
+ menu: [:type, :label],
93
+ object: [:form, :typemustmatch],
94
+ ol: [:reversed],
95
+ output: [:form],
96
+ script: [:async],
97
+ select: [:autofocus, :form, :required],
98
+ style: [:scoped],
99
+ textarea: [:autofocus, :placeholder, :form, :required, :dirname,
100
+ :maxlength, :wrap]
101
+ }
102
+
103
+ AttrsHTML5 = [:contenteditable, :contextmentu, :draggable, :dropzone,
104
+ :hidden, :role, :spellcheck, :translate]
105
+
106
+ additional_tags.each do |k, v|
107
+ @tagset[k] += v
108
+ end
109
+
110
+ @tagset.each do |k, v|
111
+ @tagset[k] += AttrsHTML5
112
+ end
113
+
114
+ @tags = @tagset.keys
115
+ @forms = @tags & FORM_TAGS
116
+ @self_closing = @tags & SELF_CLOSING_TAGS
117
+ end
118
+ end
@@ -1,8 +1,9 @@
1
1
  # You'll need to <tt>require 'markaby/kernel_method'</tt> for this.
2
+ require "markaby"
3
+
2
4
  module Kernel
3
5
  # Shortcut for creating a quick block of Markaby.
4
- def mab(*args, &block)
5
- Markaby::Builder.new(*args, &block).to_s
6
+ def mab(...)
7
+ Markaby::Builder.new(...).to_s
6
8
  end
7
9
  end
8
-
@@ -0,0 +1,36 @@
1
+ require "markaby"
2
+
3
+ module Markaby
4
+ module Rails
5
+ class TemplateHandler
6
+ class << self
7
+ def register!(options = {})
8
+ self.options = options
9
+ ActionView::Template.register_template_handler(:mab, new)
10
+ end
11
+
12
+ # TODO: Do we need this?
13
+ # Default format used by Markaby
14
+ # class_attribute :default_format
15
+ # self.default_format = :html
16
+
17
+ def options
18
+ @options ||= {}
19
+ end
20
+
21
+ def options=(val)
22
+ options.merge!(val)
23
+ options
24
+ end
25
+ end
26
+
27
+ def call(template, source = template.source)
28
+ <<-CODE
29
+ Markaby::Builder.new(Markaby::Rails::TemplateHandler.options, self) do
30
+ #{source}
31
+ end.to_s
32
+ CODE
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,89 @@
1
+ module Markaby
2
+ FORM_TAGS = [:form, :input, :select, :textarea]
3
+ SELF_CLOSING_TAGS = [:area, :base, :br, :col, :command, :embed, :frame, :hr,
4
+ :img, :input, :keygen, :link, :meta, :param, :source,
5
+ :track, :wbr]
6
+
7
+ # Common sets of attributes.
8
+ AttrCore = [:id, :class, :style, :title]
9
+ AttrI18n = [:lang, :"xml:lang", :dir]
10
+ AttrEvents = [:onclick,
11
+ :ondblclick,
12
+ :onmousedown,
13
+ :onmouseup,
14
+ :onmouseover,
15
+ :onmousemove,
16
+ :onmouseout,
17
+ :onkeypress,
18
+ :onkeydown,
19
+ :onkeyup]
20
+ AttrFocus = [:accesskey, :tabindex, :onfocus, :onblur]
21
+ AttrHAlign = [:align, :char, :charoff]
22
+ AttrVAlign = [:valign]
23
+ Attrs = AttrCore + AttrI18n + AttrEvents
24
+
25
+ AttrsBoolean = [
26
+ :checked, :disabled, :multiple, :readonly, :selected, # standard forms
27
+ :autofocus, :required, :novalidate, :formnovalidate, # HTML5 forms
28
+ :defer, :ismap, # <script defer>, <img ismap>
29
+ :compact, :declare, :noresize, :noshade, :nowrap # deprecated or unused
30
+ ]
31
+ class Tagset
32
+ class << self
33
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
34
+
35
+ def default_options
36
+ {tagset: self}
37
+ end
38
+
39
+ def can_handle? tag_name
40
+ false
41
+ end
42
+
43
+ def handle_tag tag_name, builder, *args, &block
44
+ raise NoMethodError.new
45
+ end
46
+
47
+ def validate_and_transform_tag_name! tag_name
48
+ raise(InvalidXhtmlError, "no element `#{tag_name}' for #{doctype}") unless @tagset.has_key?(tag_name)
49
+ tag_name
50
+ end
51
+
52
+ def validate_and_transform_attributes! tag_name, *args
53
+ args.last.respond_to?(:to_hash) ? transform_attributes(tag_name, args.last.to_hash) : {}
54
+ end
55
+
56
+ def transform_attributes tag_name, attributes
57
+ attributes[:name] ||= attributes[:id] if forms.include?(tag_name) && attributes[:id]
58
+ attributes.transform_keys! { |name| transform_attribute_name name }
59
+ hashed_attributes = attributes.keys.select { |name| attributes[name].is_a? Hash }
60
+ hashed_attributes.each { |name| transform_attribute_hash attributes, name }
61
+ attributes.reject! { |name, value| name.nil? || (AttrsBoolean.include?(name) && value.nil?) }
62
+ attributes.keys.each { |name| validate_attribute! tag_name, name }
63
+ attributes
64
+ end
65
+
66
+ def transform_attribute_name name
67
+ name.to_s.downcase.tr("_", "-").to_sym
68
+ end
69
+
70
+ def transform_attribute_hash attributes, prefix
71
+ values = attributes[prefix]
72
+ expanded_attributes = {}
73
+ values.each do |suffix, value|
74
+ name = transform_attribute_name "#{prefix}-#{suffix}"
75
+ expanded_attributes[name] = value
76
+ end
77
+ attributes.merge!(expanded_attributes).delete(prefix)
78
+ end
79
+
80
+ def validate_attribute! tag_name, attribute_name
81
+ raise InvalidXhtmlError, "no attribute `#{attribute_name}' on #{tag_name} elements" unless valid_attribute_name? tag_name, attribute_name
82
+ end
83
+
84
+ def valid_attribute_name? tag_name, attribute_name
85
+ attribute_name.to_s.start_with?(":", "data-", "aria-") || @tagset[tag_name].include?(attribute_name)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -1,3 +1,7 @@
1
1
  module Markaby
2
- VERSION = '0.8.1'
2
+ MAJOR = 0
3
+ MINOR = 9
4
+ TINY = 1
5
+
6
+ VERSION = "#{MAJOR}.#{MINOR}.#{TINY}"
3
7
  end
@@ -0,0 +1,13 @@
1
+ module Markaby
2
+ class XHTMLFrameset < XmlTagset
3
+ @doctype = ["-//W3C//DTD XHTML 1.0 Frameset//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"]
4
+ @tagset = XHTMLTransitional.tagset.merge({
5
+ frameset: AttrCore + [:rows, :cols, :onload, :onunload],
6
+ frame: AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :noresize, :scrolling]
7
+ })
8
+
9
+ @tags = @tagset.keys
10
+ @forms = @tags & FORM_TAGS
11
+ @self_closing = @tags & SELF_CLOSING_TAGS
12
+ end
13
+ end
@@ -0,0 +1,89 @@
1
+ module Markaby
2
+ # All the tags and attributes from XHTML 1.0 Strict
3
+ class XHTMLStrict < XmlTagset
4
+ @doctype = ["-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"]
5
+ @tagset = {
6
+ html: AttrI18n + [:id, :xmlns],
7
+ head: AttrI18n + [:id, :profile],
8
+ title: AttrI18n + [:id],
9
+ base: [:href, :id],
10
+ meta: AttrI18n + [:id, :http, :name, :content, :scheme, :"http-equiv"],
11
+ link: Attrs + [:charset, :href, :hreflang, :type, :rel, :rev, :media],
12
+ style: AttrI18n + [:id, :type, :media, :title, :"xml:space"],
13
+ script: [:id, :charset, :type, :src, :defer, :"xml:space"],
14
+ noscript: Attrs,
15
+ body: Attrs + [:onload, :onunload],
16
+ div: Attrs,
17
+ p: Attrs,
18
+ ul: Attrs,
19
+ ol: Attrs,
20
+ li: Attrs,
21
+ dl: Attrs,
22
+ dt: Attrs,
23
+ dd: Attrs,
24
+ address: Attrs,
25
+ hr: Attrs,
26
+ pre: Attrs + [:"xml:space"],
27
+ blockquote: Attrs + [:cite],
28
+ ins: Attrs + [:cite, :datetime],
29
+ del: Attrs + [:cite, :datetime],
30
+ a: Attrs + AttrFocus + [:charset, :type, :name, :href, :hreflang, :rel, :rev, :shape, :coords],
31
+ span: Attrs,
32
+ bdo: AttrCore + AttrEvents + [:lang, :"xml:lang", :dir],
33
+ br: AttrCore,
34
+ em: Attrs,
35
+ strong: Attrs,
36
+ dfn: Attrs,
37
+ code: Attrs,
38
+ samp: Attrs,
39
+ kbd: Attrs,
40
+ var: Attrs,
41
+ cite: Attrs,
42
+ abbr: Attrs,
43
+ acronym: Attrs,
44
+ q: Attrs + [:cite],
45
+ sub: Attrs,
46
+ sup: Attrs,
47
+ tt: Attrs,
48
+ i: Attrs,
49
+ b: Attrs,
50
+ big: Attrs,
51
+ small: Attrs,
52
+ object: Attrs + [:declare, :classid, :codebase, :data, :type, :codetype, :archive, :standby, :height, :width, :usemap, :name, :tabindex],
53
+ param: [:id, :name, :value, :valuetype, :type],
54
+ img: Attrs + [:src, :alt, :longdesc, :height, :width, :usemap, :ismap],
55
+ map: AttrI18n + AttrEvents + [:id, :class, :style, :title, :name],
56
+ area: Attrs + AttrFocus + [:shape, :coords, :href, :nohref, :alt],
57
+ form: Attrs + [:action, :method, :enctype, :onsubmit, :onreset, :accept, :accept],
58
+ label: Attrs + [:for, :accesskey, :onfocus, :onblur],
59
+ input: Attrs + AttrFocus + [:type, :name, :value, :checked, :disabled, :readonly, :size, :maxlength, :src, :alt, :usemap, :onselect, :onchange, :accept],
60
+ select: Attrs + [:name, :size, :multiple, :disabled, :tabindex, :onfocus, :onblur, :onchange],
61
+ optgroup: Attrs + [:disabled, :label],
62
+ option: Attrs + [:selected, :disabled, :label, :value],
63
+ textarea: Attrs + AttrFocus + [:name, :rows, :cols, :disabled, :readonly, :onselect, :onchange],
64
+ fieldset: Attrs,
65
+ legend: Attrs + [:accesskey],
66
+ button: Attrs + AttrFocus + [:name, :value, :type, :disabled],
67
+ table: Attrs + [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding],
68
+ caption: Attrs,
69
+ colgroup: Attrs + AttrHAlign + AttrVAlign + [:span, :width],
70
+ col: Attrs + AttrHAlign + AttrVAlign + [:span, :width],
71
+ thead: Attrs + AttrHAlign + AttrVAlign,
72
+ tfoot: Attrs + AttrHAlign + AttrVAlign,
73
+ tbody: Attrs + AttrHAlign + AttrVAlign,
74
+ tr: Attrs + AttrHAlign + AttrVAlign,
75
+ th: Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
76
+ td: Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
77
+ h1: Attrs,
78
+ h2: Attrs,
79
+ h3: Attrs,
80
+ h4: Attrs,
81
+ h5: Attrs,
82
+ h6: Attrs
83
+ }
84
+
85
+ @tags = @tagset.keys
86
+ @forms = @tags & FORM_TAGS
87
+ @self_closing = @tags & SELF_CLOSING_TAGS
88
+ end
89
+ end