Rails and HTML and XHTML

Posted by Charlie Wed, 12 Apr 2006 08:47:00 GMT

Rails support for HTML and XHTML is less than exemplary. For some reason, the 1.1.1 release considers the application/xhtml+xml mime type to be a synonym for text/html. Umm....why?

And it gets stranger still. If you've ever looked at the HTML that Rails generates you'll see markup that looks like this:

<head>
  <link ... />
</head>
<input type="text" value="foo" name="bar" /><br />

Notice the extra "/>" characters? This usage comes from none other than the W3C which recommends it if you want older browsers (at this point only Internet Explorer) to be able to render your XHTML as if it was HTML. Whether this is a good idea or not is long-standing religious debate that's not worth rehashing.

What is worth asking though is why is Rails doing this? Right now it provides the worst of all worlds. First, it serves quasi XHTML to browsers as HTML. This is wrong for Firefox, Safari and Opera which all understand XHTML. And it serves XHTML to Internet Explorer which doesn't understand it. In addition, this quasi XHTML masquerading as HTML doesn't validate against the HTML 4.01 strict standard or the XHTML standard.

Wouldn't it be a whole lot easier to generate HTML 4.01 and be done with it? The alternative solution is to implement content negotiation so that XHTML is served to modern browsers and HTLM to Internet Explorer. However, before you can even take the first step in this direction you have to teach Rails that XHTML is in fact not HTML. Here is the code:

module ActionController
  module MimeResponds
    class Responder
      DEFAULT_BLOCKS = {
        :xhtml    => 'Proc.new { render }'
      }

      for mime_type in %w( xhtml )
        eval <<-EOT
          def #{mime_type}(&block)
            custom(Mime::#{mime_type.upcase}, &block)
          end
        EOT
      end
    end
  end
end

module Mime
  # Fix HTML
  #HTML  = Type.new "text/html", :html, %w( application/xhtml+xml )
  HTML  = Type.new "text/html", :html
  
  # Add XHTML
  XHTML  = Type.new "application/xhtml+xml", :xhtml
  
  # Fix xhtml lookup
  LOOKUP["application/xhtml+xml"] = XHTML
end

Once you've done that, you need to change the ActionView::TagHelper::so that it doesn't add in the "/>" characters. However, at this point you run into a problem. To figure out whether to close the tag or not requires knowing the response content type, which is on the response object. Unfortunately, the tag method is mixed into ActionView::Base as well as ActionView::Helpers::InstanceTag (and maybe others classes also). The problem is that getting the the response object is different in each case. It would be nice if there was a global place to get it from. More about this in a future post.

Posted in , ,  | no comments | no trackbacks

Comments

Trackbacks

Use the following link to trackback from your own site:
http://cfis.savagexi.com/trackbacks?article_id=rails-and-html-and-xhtml&day=12&month=04&year=2006

Comments are disabled