Changeset 74
- Timestamp:
- 08/19/2006 15:00:19 (2 years ago)
- Location:
- trunk
- Files:
-
- 6 modified
-
Rakefile (modified) (2 diffs)
-
lib/markaby.rb (modified) (1 diff)
-
lib/markaby/builder.rb (modified) (15 diffs)
-
lib/markaby/cssproxy.rb (modified) (3 diffs)
-
lib/markaby/tags.rb (modified) (2 diffs)
-
test/test_markaby.rb (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Rakefile
r60 r74 8 8 include FileUtils 9 9 10 REV = File.read(".svn/entries")[/committed-rev="(\d+)"/, 1] rescue nil 11 VERS = "0.5" + (REV ? ".#{REV}" : "") 12 13 task :default => [:package] 14 10 15 setup_tests 11 16 setup_rdoc ['README', 'CHANGELOG', 'lib/**/*.rb'] … … 13 18 summary = "Markup as Ruby, write HTML in your native Ruby tongue" 14 19 test_file = "test/test_markaby.rb" 15 setup_gem("markaby", "0.5", "Tim Fletcher and _why", summary, [['builder', '>=2.0.0']], test_file)20 setup_gem("markaby", VERS, "Tim Fletcher and _why", summary, [['builder', '>=2.0.0']], test_file) -
trunk/lib/markaby.rb
r60 r74 33 33 require 'markaby/cssproxy' 34 34 require 'markaby/metaid' 35 require 'markaby/tags'36 35 require 'markaby/template' -
trunk/lib/markaby/builder.rb
r62 r74 1 require 'markaby/tags' 2 1 3 module Markaby 2 4 # The Markaby::Builder class is the central gear in the system. When using … … 20 22 21 23 @@default = { 22 :indent => 2,24 :indent => 0, 23 25 :output_helpers => true, 26 :output_xml_instruction => true, 24 27 :output_meta_tag => true, 25 :image_tag_options => { :border => '0', :alt => '' } 28 :auto_validation => true, 29 :image_tag_options => { :border => '0', :alt => '' }, 30 :tagset => Markaby::XHTMLTransitional 26 31 } 27 32 … … 30 35 end 31 36 32 def self.ignored_helpers 33 @@ignored_helpers ||= [] 34 end 35 36 def self.ignore_helpers(*helpers) 37 ignored_helpers.concat helpers 38 end 39 40 XHTMLTransitional = ["-//W3C//DTD XHTML 1.0 Transitional//EN", "DTD/xhtml1-transitional.dtd"] 41 42 XHTMLStrict = ["-//W3C//DTD XHTML 1.0 Strict//EN", "DTD/xhtml1-strict.dtd"] 43 44 attr_accessor :output_helpers 37 def self.ignored_helpers 38 @@ignored_helpers ||= [] 39 end 40 41 def self.ignore_helpers(*helpers) 42 ignored_helpers.concat helpers 43 end 44 45 attr_accessor :output_helpers, :tagset 45 46 46 47 # Create a Markaby builder object. Pass in a hash of variable assignments to … … 62 63 @streams = [[]] 63 64 @assigns = assigns 64 @ margin = -165 66 @ indent = @@default[:indent]67 @output_helpers = @@default[:output_helpers]68 @output_meta_tag = @@default[:output_meta_tag]69 70 use_tagset Markaby::XHTMLTransitionalTags71 72 if helpers65 @elements = {} 66 67 @@default.each do |k, v| 68 instance_variable_set("@#{k}", @assigns[k] || v) 69 end 70 71 if helpers.nil? 72 @helpers = nil 73 else 73 74 @helpers = helpers.dup 74 75 for iv in helpers.instance_variables … … 86 87 end 87 88 88 @ margin += 189 @builder = ::Builder::XmlMarkup.new(:indent => @indent, :margin => @margin, :target => @streams.last)90 91 def @builder.target=(io)92 @target = io 93 end94 95 instance_eval(&block) if block89 @builder = ::Builder::XmlMarkup.new(:indent => @indent, :target => @streams.last) 90 class << @builder 91 attr_accessor :target, :level 92 end 93 94 if block 95 text(capture(&block)) 96 end 96 97 end 97 98 98 99 # Returns a string containing the HTML stream. Internally, the stream is stored as an Array. 99 100 def to_s 100 @streams.last. join101 @streams.last.to_s 101 102 end 102 103 … … 109 110 alias_method :concat, :text 110 111 112 # Emulate ERB to satisfy helpers like <tt>form_for</tt>. 113 def _erbout; self end 114 111 115 # Captures the HTML code built inside the +block+. This is done by creating a new 112 116 # stream for the builder object, running the block and passing back its stream as a string. … … 117 121 def capture(&block) 118 122 @streams.push(builder.target = []) 123 @builder.level += 1 119 124 str = instance_eval(&block) 120 str = to_s unless @streams.last.compact.empty?125 str = @streams.last.join if @streams.last.any? 121 126 @streams.pop 127 @builder.level -= 1 122 128 builder.target = @streams.last 123 129 str 130 end 131 132 # Content_for will store the given block in an instance variable for later use 133 # in another template or in the layout. 134 # 135 # The name of the instance variable is content_for_<name> to stay consistent 136 # with @content_for_layout which is used by ActionView's layouts. 137 # 138 # Example: 139 # 140 # content_for("header") do 141 # h1 "Half Shark and Half Lion" 142 # end 143 # 144 # If used several times, the variable will contain all the parts concatenated. 145 def content_for(name, &block) 146 @helpers.assigns["content_for_#{name}"] = 147 eval("@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)") 124 148 end 125 149 … … 127 151 # the arguments are the same as the tags implemented via method_missing. 128 152 def tag!(tag, *args, &block) 129 if @tagset 130 if !@tagset.has_key?(tag) 131 raise InvalidXhtmlError, "no element `#{tag}' for #{doctype}" 132 elsif args.last.respond_to?(:to_hash) 133 attrs = args.last.to_hash 134 attrs.each do |k, v| 135 unless k =~ /:/ or @tagset[tag].include? k.to_s.downcase.intern 136 raise InvalidXhtmlError, "no attribute `#{k}' on #{tag} elements" 137 end 153 ele_id = nil 154 if @auto_validation and @tagset 155 if !@tagset.tagset.has_key?(tag) 156 raise InvalidXhtmlError, "no element `#{tag}' for #{tagset.doctype}" 157 elsif args.last.respond_to?(:to_hash) 158 attrs = args.last.to_hash 159 attrs.each do |k, v| 160 atname = k.to_s.downcase.intern 161 unless k =~ /:/ or @tagset.tagset[tag].include? atname 162 raise InvalidXhtmlError, "no attribute `#{k}' on #{tag} elements" 163 end 164 if atname == :id 165 ele_id = v.to_s 166 if @elements.has_key? ele_id 167 raise InvalidXhtmlError, "id `#{ele_id}' already used (id's must be unique)." 168 end 169 end 170 end 138 171 end 139 end140 172 end 141 173 if block … … 143 175 block = proc { text(str) } 144 176 end 145 fragment { @builder.method_missing(tag, *args, &block) } 177 178 f = fragment { @builder.method_missing(tag, *args, &block) } 179 @elements[ele_id] = f if ele_id 180 f 146 181 end 147 182 … … 152 187 # variables. Here is the order of interception: 153 188 # 154 # * If +sym+ is a helper method, the helper method is called155 # and output to the stream.156 189 # * If +sym+ is a recognized HTML tag, the tag is output 157 190 # or a CssProxy is returned if no arguments are given. … … 160 193 # * If +sym+ is also the name of an instance variable, the 161 194 # value of the instance variable is returned. 195 # * If +sym+ is a helper method, the helper method is called 196 # and output to the stream. 162 197 # * Otherwise, +sym+ and its arguments are passed to tag! 163 198 def method_missing(sym, *args, &block) 164 if @helpers.respond_to?(sym ) && !self.class.ignored_helpers.include?(sym)199 if @helpers.respond_to?(sym, true) && !self.class.ignored_helpers.include?(sym) 165 200 r = @helpers.send(sym, *args, &block) 166 @output_helpers ? fragment { @builder << r } : r 167 elsif ::Builder::XmlMarkup.instance_methods.include?(sym.to_s) 201 if @output_helpers 202 fragment { @builder << r } 203 else 204 r 205 end 206 elsif ::Builder::XmlMarkup.instance_methods.include?(sym.to_s) 168 207 @builder.__send__(sym, *args, &block) 169 elsif @tagset and @tagset_tags.include?(sym)170 if @tagset_self_closing.include?(sym) and block171 raise InvalidXhtmlError, "the `#{sym}' element is self-closing, please remove the block"172 end173 if args.empty? and block.nil? and not NO_PROXY.include?(sym)174 return CssProxy.new do |args, block|175 if @tagset_forms.include?(sym) and args.last.respond_to?(:to_hash) and args.last[:id]176 args.last[:name] ||= args.last[:id]177 end178 tag!(sym, *args, &block)179 end180 end181 #if not @tagset_self_closing.include?(sym) and args.first.respond_to?(:to_hash)182 # block ||= proc{}183 #end184 tag!(sym, *args, &block)185 208 elsif instance_variable_get("@#{sym}") 186 209 instance_variable_get("@#{sym}") … … 192 215 end 193 216 194 undef_method :p, :select, :sub 195 196 # Builds a image tag. Assumes <tt>:border => '0', :alt => ''</tt>. 197 def img(opts = {}) 198 tag!(:img, @@default[:image_tag_options].merge(opts)) 217 def html_tag(sym, *args, &block) 218 if @auto_validation and @tagset.self_closing.include?(sym) and block 219 raise InvalidXhtmlError, "the `\#{sym}' element is self-closing, please remove the block" 220 end 221 if args.empty? and block.nil? and not NO_PROXY.include?(sym) 222 return CssProxy.new do |args, block| 223 if @tagset.forms.include?(sym) and args.last.respond_to?(:to_hash) and args.last[:id] 224 args.last[:name] ||= args.last[:id] 225 end 226 tag!(sym, *args, &block) 227 end 228 end 229 if not @tagset.self_closing.include?(sym) and args.first.respond_to?(:to_hash) 230 block ||= proc{} 231 end 232 tag!(sym, *args, &block) 233 end 234 235 XHTMLTransitional.tags.each do |k| 236 class_eval %{ 237 def #{k}(*args, &block) 238 html_tag(#{k.inspect}, *args, &block) 239 end 240 } 199 241 end 200 242 … … 204 246 tag!(:head, *args) do 205 247 tag!(:meta, "http-equiv" => "Content-Type", "content" => "text/html; charset=utf-8") if @output_meta_tag 206 instance_eval &block 207 end 208 end 209 210 def use_tagset(tagset) 211 return if @tagset == tagset 212 @tagset = tagset 213 @tagset_tags = tagset.keys 214 @tagset_forms = @tagset_tags & FORM_TAGS 215 @tagset_self_closing = @tagset_tags & SELF_CLOSING_TAGS 248 instance_eval(&block) 249 end 216 250 end 217 251 … … 219 253 # are prepended. Also assumes <tt>:xmlns => "http://www.w3.org/1999/xhtml", 220 254 # :lang => "en"</tt>. 221 def html(*doctype, &block) 222 if doctype.empty? 223 doctype = XHTMLTransitional 224 use_tagset Markaby::XHTMLTransitionalTags 225 end 226 declare!(:DOCTYPE, :html, :PUBLIC, *doctype) 227 tag!(:html, :xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en", &block) 228 end 229 alias_method :xhtml_transitional, :html 255 def xhtml_transitional(&block) 256 self.tagset = Markaby::XHTMLTransitional 257 xhtml_html &block 258 end 230 259 231 260 # Builds an html tag with XHTML 1.0 Strict doctype instead. 232 261 def xhtml_strict(&block) 233 use_tagset Markaby::XHTMLStrictTags 234 instruct! 235 html *XHTMLStrict, &block 262 self.tagset = Markaby::XHTMLStrict 263 xhtml_html &block 236 264 end 237 265 238 266 private 267 268 def xhtml_html(&block) 269 instruct! if @output_xml_instruction 270 declare!(:DOCTYPE, :html, :PUBLIC, *tagset.doctype) 271 tag!(:html, :xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en", &block) 272 end 239 273 240 274 def fragment … … 250 284 class Fragment < ::Builder::BlankSlate 251 285 def initialize(s, a, b) 252 @s, @f1, @f2 = s, a, b 286 @s, @f1, @f2 = s, a, b 253 287 end 254 288 def method_missing(*a) 255 289 unless @str 256 @str = @s[@f1, @f2].to_s 290 @str = @s[@f1, @f2].to_s 257 291 @s[@f1, @f2] = [nil] * @f2 258 292 @str -
trunk/lib/markaby/cssproxy.rb
r20 r74 13 13 end 14 14 15 # Adds attributes to an element, for internal use only. For example, if you 16 # want to write a wrapper which sets a bunch of default attributes for a certain 17 # tag. Like the default `img' method included with Markaby automatically sets an 18 # empty alt attribute. 19 def merge!(opts) 20 @opts.merge! opts 21 self 22 end 23 15 24 # Adds attributes to an element. Bang methods set the :id attribute. 16 25 # Other methods add to the :class attribute. If a block is supplied, … … 19 28 idc = id_or_class.to_s 20 29 case idc 30 when "pass" 21 31 when /!$/ 22 32 @opts[:id] = $` … … 34 44 end 35 45 end 46 47 def to_str 48 @blk.call([[@opts]]).to_s 49 end 50 alias_method :to_s, :to_str 51 36 52 end 37 53 end -
trunk/lib/markaby/tags.rb
r60 r74 1 1 module Markaby 2 3 # Common sets of attributes.4 AttrCustom = [:id, :class, :style]5 AttrEvents = [:onclick, :ondblclick, :onmousedown, :onmouseup, :onmouseover, :onmousemove,6 :onmouseout, :onkeypress, :onkeydown, :onkeyup]7 AttrAnno = [:title, :lang, :dir]8 Attrs = AttrCustom + AttrEvents + AttrAnno9 10 # Very basic rules from the XHTML 1.0 Strict DTD.11 XHTMLStrictTags = {12 :pre => AttrCustom + AttrAnno + [:space],13 :em => Attrs,14 :code => Attrs,15 :h2 => Attrs,16 :h3 => Attrs,17 :h1 => Attrs,18 :h6 => Attrs,19 :dl => Attrs,20 :h4 => Attrs,21 :h5 => Attrs,22 :area => Attrs + [:accesskey, :tabindex, :onfocus, :onblur, :shape, :coords, :href, :nohref, :alt],23 :meta => [:lang, :dir, :id, :name, :content, :scheme, "http-equiv".intern],24 :table => [],25 :dfn => Attrs,26 :label => Attrs + [:for, :accesskey, :onfocus, :onblur],27 :select => Attrs + [:name, :size, :multiple, :disabled, :tabindex, :onfocus, :onblur, :onchange],28 :noscript => Attrs,29 :style => [:lang, :dir, :id, :type, :media, :title, :space],30 :strong => Attrs,31 :span => Attrs,32 :sub => Attrs,33 :img => Attrs + [:src, :alt, :longdesc, :height, :width, :usemap, :ismap],34 :title => [:lang, :dir, :id],35 :bdo => AttrCustom + [:title] + AttrEvents + [:lang, :dir],36 :tr => [],37 :tbody => [],38 :param => [:id, :name, :value, :valuetype, :type],39 :li => Attrs,40 :acronym => Attrs,41 :html => [:lang, :dir, :id, :xmlns],42 :caption => [],43 :tfoot => [],44 :th => [],45 :sup => Attrs,46 :var => Attrs,47 :input => Attrs + [:accesskey, :tabindex, :onfocus, :onblur, :type, :name, :value, :checked, :disabled, :readonly, :size, :maxlength, :src, :alt, :usemap, :onselect, :onchange, :accept],48 :td => Attrs + [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding, :span, :align, :char, :charoff, :valign, :abbr, :axis, :headers, :scope, :rowspan, :colspan],49 :samp => Attrs,50 :cite => Attrs,51 :thead => [],52 :body => Attrs + [:onload, :onunload],53 :map => AttrCustom + [:lang, :dir, ] + AttrEvents + [:title, :name],54 :head => [:lang, :dir, :id, :profile],55 :blockquote => Attrs + [:cite],56 :fieldset => Attrs,57 :option => Attrs + [:selected, :disabled, :label, :value],58 :form => Attrs + [:action, :method, :enctype, :onsubmit, :onreset, :accept, 'accept-charset'],59 :hr => Attrs,60 :big => Attrs,61 :dd => Attrs,62 :object => Attrs + [:declare, :classid, :codebase, :data, :type, :codetype, :archive, :standby, :height, :width, :usemap, :name, :tabindex],63 :base => [:href, :id],64 :link => Attrs + [:charset, :href, :hreflang, :type, :rel, :rev, :media],65 :kbd => Attrs,66 :br => AttrCustom + [:title],67 :address => Attrs,68 :optgroup => Attrs + [:disabled, :label],69 :dt => Attrs,70 :ins => Attrs + [:cite, :datetime],71 :b => Attrs,72 :legend => Attrs + [:accesskey],73 :abbr => Attrs,74 :a => Attrs + [:accesskey, :tabindex, :onfocus, :onblur, :charset, :type, :name, :href, :hreflang, :rel, :rev, :shape, :coords],75 :ol => Attrs,76 :textarea => Attrs + [:accesskey, :tabindex, :onfocus, :onblur, :name, :rows, :cols, :disabled, :readonly, :onselect, :onchange],77 :colgroup => [],78 :i => Attrs,79 :button => Attrs + [:accesskey, :tabindex, :onfocus, :onblur, :name, :value, :type, :disabled],80 :script => [:id, :charset, :type, :src, :defer, :space],81 :col => [],82 :q => Attrs + [:cite],83 :p => Attrs,84 :del => Attrs + [:cite, :datetime],85 :small => Attrs,86 :div => Attrs,87 :tt => Attrs,88 :ul => Attrs89 }90 91 # Additional tags found in XHTML 1.0 Transitional92 XHTMLTransitionalTags = XHTMLStrictTags.merge \93 :strike => Attrs,94 :center => Attrs,95 :dir => Attrs + [:compact],96 :noframes => Attrs,97 :basefont => [:id, :size, :color, :face],98 :u => Attrs,99 :menu => Attrs + [:compact],100 :iframe => AttrCustom + [:title, :longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :scrolling, :align, :height, :width],101 :font => AttrCustom + AttrAnno + [:size, :color, :face],102 :s => Attrs,103 :applet => AttrCustom + [:title, :codebase, :archive, :code, :object, :alt, :name, :width, :height, :align, :hspace, :vspace],104 :isindex => AttrCustom + AttrAnno + [:prompt]105 106 # Additional attributes found in XHTML 1.0 Transitional107 { :script => [:language],108 :a => [:target],109 :td => [:bgcolor, :nowrap, :height],110 :p => [:align],111 :h5 => [:align],112 :h3 => [:align],113 :li => [:type, :value],114 :div => [:align],115 :pre => AttrEvents + [:width],116 :body => [:background, :bgcolor, :text, :link, :vlink, :alink],117 :ol => [:type, :compact, :start],118 :h4 => [:align],119 :h2 => [:align],120 :object => [:align, :border, :hspace, :vspace],121 :img => [:name, :align, :border, :hspace, :vspace],122 :link => [:target],123 :legend => [:align],124 :dl => [:compact],125 :input => [:align],126 :h6 => [:align],127 :hr => [:align, :noshade, :size, :width],128 :base => [:target],129 :ul => [:type, :compact],130 :br => [:clear],131 :form => [:name, :target],132 :area => [:target],133 :h1 => [:align]134 }.each do |k, v|135 XHTMLTransitionalTags[k] += v136 end137 2 138 3 FORM_TAGS = [ :form, :input, :select, :textarea ] … … 140 5 NO_PROXY = [ :hr, :br ] 141 6 7 # Common sets of attributes. 8 AttrCore = [:id, :class, :style, :title] 9 AttrI18n = [:lang, :'xml:lang', :dir] 10 AttrEvents = [:onclick, :ondblclick, :onmousedown, :onmouseup, :onmouseover, :onmousemove, 11 :onmouseout, :onkeypress, :onkeydown, :onkeyup] 12 AttrFocus = [:accesskey, :tabindex, :onfocus, :onblur] 13 AttrHAlign = [:align, :char, :charoff] 14 AttrVAlign = [:valign] 15 Attrs = AttrCore + AttrI18n + AttrEvents 16 17 # All the tags and attributes from XHTML 1.0 Strict 18 class XHTMLStrict 19 class << self 20 attr_accessor :tags, :tagset, :forms, :self_closing, :doctype 21 end 22 @doctype = ["-//W3C//DTD XHTML 1.0 Strict//EN", "DTD/xhtml1-strict.dtd"] 23 @tagset = { 24 :html => AttrI18n + [:id, :xmlns], 25 :head => AttrI18n + [:id, :profile], 26 :title => AttrI18n + [:id], 27 :base => [:href, :id], 28 :meta => AttrI18n + [:id, :http, :name, :content, :scheme, :'http-equiv'], 29 :link => Attrs + [:charset, :href, :hreflang, :type, :rel, :rev, :media], 30 :style => AttrI18n + [:id, :type, :media, :title, :'xml:space'], 31 :script => [:id, :charset, :type, :src, :defer, :'xml:space'], 32 :noscript => Attrs, 33 :body => Attrs + [:onload, :onunload], 34 :div => Attrs, 35 :p => Attrs, 36 :ul => Attrs, 37 :ol => Attrs, 38 :li => Attrs, 39 :dl => Attrs, 40 :dt => Attrs, 41 :dd => Attrs, 42 :address => Attrs, 43 :hr => Attrs, 44 :pre => Attrs + [:'xml:space'], 45 :blockquote => Attrs + [:cite], 46 :ins => Attrs + [:cite, :datetime], 47 :del => Attrs + [:cite, :datetime], 48 :a => Attrs + AttrFocus + [:charset, :type, :name, :href, :hreflang, :rel, :rev, :shape, :coords], 49 :span => Attrs, 50 :bdo => AttrCore + AttrEvents + [:lang, :'xml:lang', :dir], 51 :br => AttrCore, 52 :em => Attrs, 53 :strong => Attrs, 54 :dfn => Attrs, 55 :code => Attrs, 56 :samp => Attrs, 57 :kbd => Attrs, 58 :var => Attrs, 59 :cite => Attrs, 60 :abbr => Attrs, 61 :acronym => Attrs, 62 :q => Attrs + [:cite], 63 :sub => Attrs, 64 :sup => Attrs, 65 :tt => Attrs, 66 :i => Attrs, 67 :b => Attrs, 68 :big => Attrs, 69 :small => Attrs, 70 :object => Attrs + [:declare, :classid, :codebase, :data, :type, :codetype, :archive, :standby, :height, :width, :usemap, :name, :tabindex], 71 :param => [:id, :name, :value, :valuetype, :type], 72 :img => Attrs + [:src, :alt, :longdesc, :height, :width, :usemap, :ismap], 73 :map => AttrI18n + AttrEvents + [:id, :class, :style, :title, :name], 74 :area => Attrs + AttrFocus + [:shape, :coords, :href, :nohref, :alt], 75 :form => Attrs + [:action, :method, :enctype, :onsubmit, :onreset, :accept, :accept], 76 :label => Attrs + [:for, :accesskey, :onfocus, :onblur], 77 :input => Attrs + AttrFocus + [:type, :name, :value, :checked, :disabled, :readonly, :size, :maxlength, :src, :alt, :usemap, :onselect, :onchange, :accept], 78 :select => Attrs + [:name, :size, :multiple, :disabled, :tabindex, :onfocus, :onblur, :onchange], 79 :optgroup => Attrs + [:disabled, :label], 80 :option => Attrs + [:selected, :disabled, :label, :value], 81 :textarea => Attrs + AttrFocus + [:name, :rows, :cols, :disabled, :readonly, :onselect, :onchange], 82 :fieldset => Attrs, 83 :legend => Attrs + [:accesskey], 84 :button => Attrs + AttrFocus + [:name, :value, :type, :disabled], 85 :table => Attrs + [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding], 86 :caption => Attrs, 87 :colgroup => Attrs + AttrHAlign + AttrVAlign + [:span, :width], 88 :col => Attrs + AttrHAlign + AttrVAlign + [:span, :width], 89 :thead => Attrs + AttrHAlign + AttrVAlign, 90 :tfoot => Attrs + AttrHAlign + AttrVAlign, 91 :tbody => Attrs + AttrHAlign + AttrVAlign, 92 :tr => Attrs + AttrHAlign + AttrVAlign, 93 :th => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan], 94 :td => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan], 95 :h1 => Attrs, 96 :h2 => Attrs, 97 :h3 => Attrs, 98 :h4 => Attrs, 99 :h5 => Attrs, 100 :h6 => Attrs 101 } 102 103 @tags = @tagset.keys 104 @forms = @tags & FORM_TAGS 105 @self_closing = @tags & SELF_CLOSING_TAGS 106 end 107 108 # Additional tags found in XHTML 1.0 Transitional 109 class XHTMLTransitional 110 class << self 111 attr_accessor :tags, :tagset, :forms, :self_closing, :doctype 112 end 113 @doctype = ["-//W3C//DTD XHTML 1.0 Transitional//EN", "DTD/xhtml1-transitional.dtd"] 114 @tagset = XHTMLStrict.tagset.merge \ 115 :strike => Attrs, 116 :center => Attrs, 117 :dir => Attrs + [:compact], 118 :noframes => Attrs, 119 :basefont => [:id, :size, :color, :face], 120 :u => Attrs, 121 :menu => Attrs + [:compact], 122 :iframe => AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :scrolling, :align, :height, :width], 123 :font => AttrCore + AttrI18n + [:size, :color, :face], 124 :s => Attrs, 125 :applet => AttrCore + [:codebase, :archive, :code, :object, :alt, :name, :width, :height, :align, :hspace, :vspace], 126 :isindex => AttrCore + AttrI18n + [:prompt] 127 128 # Additional attributes found in XHTML 1.0 Transitional 129 { :script => [:language], 130 :a => [:target], 131 :td => [:bgcolor, :nowrap, :width, :height], 132 :p => [:align], 133 :h5 => [:align], 134 :h3 => [:align], 135 :li => [:type, :value], 136 :div => [:align], 137 :pre => [:width], 138 :body => [:background, :bgcolor, :text, :link, :vlink, :alink], 139 :ol => [:type, :compact, :start], 140 :h4 => [:align], 141 :h2 => [:align], 142 :object => [:align, :border, :hspace, :vspace], 143 :img => [:name, :align, :border, :hspace, :vspace], 144 :link => [:target], 145 :legend => [:align], 146