<li>HTMLLint: warn about repeating attributes (e.g. multiple styles, classes, etc.)</li>
<li>HTMLLint: warn about repeating &nbsp; or <br> sequences</li>
<li>HTMLLint: warn about missing doctype</li>
- <li>HTMLLint: warn about <code>href="javascript:void 0"</code></li>
</ul>
</div>
<p class="quiet" style="font-style:italic;">
.short { display: inline-block; width: 20em; margin-top: 0.25em; }
.deprecated-element, .deprecated-attribute { color: red; }
-.presentational-element, .presentational-attribute { color: #FF8C00; }
\ No newline at end of file
+.presentational-element, .presentational-attribute, .inaccessible-attribute { color: #FF8C00; }
\ No newline at end of file
(attrName === 'width' && (/^(?:hr|td|th|applet|pre)$/).test(tag))
);
}
+ function isInaccessibleAttribute(attrName, attrValue) {
+ return (
+ attrName === 'href' &&
+ (/^\s*javascript\s*:\s*void\s*(\s+0|\(\s*0\s*\))\s*$/i).test(attrValue)
+ );
+ }
function Lint() {
this.log = [ ];
}
- Lint.prototype._testElement = function(tag, attrName) {
+ Lint.prototype.testElement = function(tag) {
if (isDeprecatedElement(tag)) {
this.log.push(
'<li>Warning: found <span class="deprecated-element">deprecated element</span> (<strong>',
}
};
- Lint.prototype._testAttribute = function(tag, attrName) {
+ Lint.prototype.testAttribute = function(tag, attrName, attrValue) {
if (isEventAttribute(attrName)) {
this.log.push(
'<li>Warning: found <span class="event-attribute">event attribute</span> (<strong>',
else if (isDeprecatedAttribute(tag, attrName)) {
this.log.push(
'<li>Warning: found <span class="deprecated-attribute">deprecated attribute</span> (<strong>',
- attrName, '</strong> on <code>', tag, '</code> element)</li>');
+ attrName, '</strong> on <code><', tag, '></code> element)</li>');
}
else if (isStyleAttribute(attrName)) {
this.log.push(
- '<li>Warning: found <span class="style-attribute">style attribute</span> (on <code>', tag, '</code> element)</li>');
+ '<li>Warning: found <span class="style-attribute">style attribute</span> (on <code><', tag, '></code> element)</li>');
+ }
+ else if (isInaccessibleAttribute(attrName, attrValue)) {
+ this.log.push(
+ '<li>Warning: found <span class="inaccessible-attribute">inaccessible attribute</span> '+
+ '(on <code><', tag, '></code> element)</li>');
}
};
- Lint.prototype.test = function(tag, attrName) {
- this._testElement(tag, attrName);
- this._testAttribute(tag, attrName);
+ Lint.prototype.test = function(tag, attrName, attrValue) {
+ this.testElement(tag);
+ this.testAttribute(tag, attrName, attrValue);
};
Lint.prototype.populate = function(writeToElement) {
buffer.push('<', tag);
+ lint && lint.testElement(tag);
+
for ( var i = 0, len = attrs.length; i < len; i++ ) {
- lint && lint.test(tag, attrs[i].name.toLowerCase());
+ lint && lint.testAttribute(tag, attrs[i].name.toLowerCase(), attrs[i].escaped);
buffer.push(normalizeAttribute(attrs[i], attrs, tag, options));
}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <title></title>
+ <link rel="stylesheet" href="qunit.css" type="text/css">
+ <script type="text/javascript" src="qunit.js"></script>
+ <script type="text/javascript" src="../src/htmlparser.js"></script>
+ <script type="text/javascript" src="../src/htmlminifier.js"></script>
+ <script type="text/javascript" src="../src/htmllint.js"></script>
+ </head>
+ <body>
+
+ <h1 id="qunit-header">HTML Lint</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+
+ <script type="text/javascript">
+
+ (function(global){
+
+ var minify = global.minify, input, output, lint;
+
+ module('', {
+ setup: function() {
+ lint = new HTMLLint();
+ }
+ });
+
+ test('lint exists', function() {
+ ok(typeof lint !== 'undefined');
+ });
+
+ test('lint is instance of HTMLLint', function() {
+ ok(lint instanceof HTMLLint);
+ });
+
+ test('lint API', function() {
+ equals(0, lint.log.length, '`log` property exists');
+ equals("function", typeof lint.populate, '`populate` method exists');
+ equals("function", typeof lint.test, '`test` method exists');
+ equals("function", typeof lint.testElement, '`testElement` method exists');
+ equals("function", typeof lint.testAttribute, '`testAttribute` method exists');
+ });
+
+ test('deprecated element (font)', function(){
+ minify('<font>foo</font>', { lint: lint });
+ var log = lint.log.join('');
+
+ ok(log.indexOf('font') > -1);
+ ok(log.indexOf('deprecated element') > -1);
+ });
+
+ })(this);
+ </script>
+ </body>
+</html>
\ No newline at end of file