Quick — what’s wrong with the following code?
<div class="main-content">
<div class="introduction">
<h3>Introduction</h3>
<p class="body">In the <em>very</em>beginning, the Web was nothing but <span class="highlighted">completely static</span>
content. While static content was in many ways <div class="extra_emphasis">amazing</div> for the time,
just because of the ease of use, it was not enough.</p>
<p class="body">And so this begat the CGI. Someone realized that <strong>any program at all</strong> could generate
HTML, and that was also <span class="highlighted">amazing</span>.</p>
</div>
</div>
Write it as Fortitude, and it knows right away:
Fortitude::Errors::InvalidElementNesting at /app/views/example/test1.html.rb:17 The widget #<Views::Example::Test1:0x007fcf7a337da8> tried to render an element that is not allowed by element nesting rules: you can't put a <div> inside a <p>. (See 'http://www.w3.org/TR/html5/grouping-content.html#the-p-element' for more details.)
And, quick — what’s wrong with this code?
<div class="main-content">
<div class="introduction">
<h1>Rock 'N Roll</h1>
<p class="body">What we call today "rock 'n roll" really started with the blues. Listen to this:</p>
<audio src="http://example.com/mp3/blues1.mp3" preload="true" width="600" autoplay="false">
</div>
</div>
Once again, Fortitude knows:
Fortitude::Errors::InvalidElementAttributes at /app/views/example/test2.html.rb:11
The widget #<Views::Example::Test2:0x007fcf830a8548> tried to
render an element, <audio>, with attributes that are
not allowed: {:width=>400}.
Only these attributes are allowed: [:accesskey, :autoplay,
:class, :contenteditable, :controls, :crossorigin, :dir,
:draggable, :dropzone, :hidden, :id, :lang, :loop,
:mediagroup, :muted, :onabort, :onblur, :oncancel,
:oncanplay, :oncanplaythrough, :onchange, :onclick,
:onclose, :oncuechange, :ondblclick, :ondrag, :ondragend,
:ondragenter, :ondragexit, :ondragleave, :ondragover,
:ondragstart, :ondrop, :ondurationchange, :onemptied,
:onended, :onerror, :onfocus, :oninput, :oninvalid,
:onkeydown, :onkeypress, :onkeyup, :onload,
:onloadeddata, :onloadedmetadata, :onloadstart,
:onmousedown, :onmouseenter, :onmouseleave, :onmousemove,
:onmouseout, :onmouseover, :onmouseup, :onmousewheel,
:onpause, :onplay, :onplaying, :onprogress, :onratechange,
:onreset, :onresize, :onscroll, :onseeked, :onseeking,
:onselect, :onshow, :onstalled, :onsubmit, :onsuspend,
:ontimeupdate, :ontoggle, :onvolumechange, :onwaiting,
:preload, :role, :spellcheck, :src, :style, :tabindex,
:title, :translate]
(See 'http://www.w3.org/TR/html5/embedded-content-0.html#the-audio-element'
for more details.)
And, finally, what’s wrong with this code?
<div class="main-content">
<div class="introduction">
<h3>Introduction</h3>
<p class="body" id="para">In the <em>very</em>beginning, the Web was nothing but <span class="highlighted">completely static</span>
content. While static content was in many ways <div class="extra_emphasis">amazing</div> for the time,
just because of the ease of use, it was not enough.</p>
<p class="body" id="para">And so this begat the CGI. Someone realized that <strong>any program at all</strong> could generate
HTML, and that was also <span class="highlighted">amazing</span>.</p>
</div>
</div>
You guessed it — Fortitude knows:
Fortitude::Errors::DuplicateId at /app/views/example/test3.html.rb:17 The widget #<Views::Example::Test3:0x007fcf7ae3ed00> tried to use a DOM ID, 'para', that has already been used. It was originally used on a <p> tag within widget #<Views::Example::Test3:0x007fcf7ae3ed00>, and is now trying to be used on a <p> tag.
Fortitude’s ID checking operates across the entire page, and is fully dynamic — if you re-use an ID that’s been used in any view or partial, anywhere on that page, you’ll get a precise error, telling you exactly what’s wrong.
Every single one of these features is configurable. In particular, they’re off by default, and we recommend you only turn them on in development mode. (In production, it’s almost always better to emit invalid HTML than to show your user a 500 page.)
Use these features from the beginning of your Fortitude development, and a huge amount of checking with an HTML validator (or just emitting invalid markup) simply vanishes.
And, as an added bonus: what’s wrong with this code?
<p>We’ll use CSS to add some space
at this empty span: <span class="spacer" />. See?<br />
Wasn’t that nice?</p>
This code almost certainly does not mean what the author thought it meant: you cannot close a <span> or other such elements using /> in HTML, and void tags like <br> should never be written using />. (And, lest you think this is a theoretical problem only, take a look at the linked article — older browsers can and will render your page differently if you do this.)
On the other hand, this Fortitude code:
p {
text "We’ll use CSS to add some space at this empty span: "
span :class => 'spacer'
text ". See?"
br
text "Wasn’t that nice?"
}
…will render as this correct HTML — with Fortitude, it is impossible to make these kinds of mistakes:
<p>We’ll use CSS to add some space
at this empty span: <span class="spacer"></span>. See?<br>
Wasn’t that nice?</p>
In our next example, we’ll see how Fortitude’s formatting and commenting features make it a whole lot easier to read the resulting HTML and discover which view is responsible for emitting a particular piece of HTML.