forked from cdnjs/cdnjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request cdnjs#1563 from philipwalton/html-inspector
Add version 0.4.1.
- Loading branch information
Showing
6 changed files
with
3,583 additions
and
1 deletion.
There are no files selected for viewing
117 changes: 117 additions & 0 deletions
117
ajax/libs/html-inspector/0.4.1/html-inspector.best-practices.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
HTMLInspector.rules.add("inline-event-handlers", function(listener, reporter) { | ||
|
||
listener.on('attribute', function(name, value) { | ||
if (name.indexOf("on") === 0) { | ||
reporter.warn( | ||
"inline-event-handlers", | ||
"An '" + name + "' attribute was found in the HTML. Use external scripts for event binding instead.", | ||
this | ||
) | ||
} | ||
}) | ||
|
||
}) | ||
|
||
HTMLInspector.rules.add( | ||
"script-placement", | ||
{ | ||
whitelist: [] | ||
}, | ||
function(listener, reporter, config) { | ||
|
||
var elements = [] | ||
, whitelist = config.whitelist | ||
, matches = this.utils.matches | ||
|
||
function isWhitelisted(el) { | ||
if (!whitelist) return false | ||
if (typeof whitelist == "string") return matches(el, whitelist) | ||
if (Array.isArray(whitelist)) { | ||
return whitelist.length && whitelist.some(function(item) { | ||
return matches(el, item) | ||
}) | ||
} | ||
return false | ||
} | ||
|
||
listener.on("element", function(name) { | ||
elements.push(this) | ||
}) | ||
|
||
listener.on("afterInspect", function() { | ||
var el | ||
// scripts at the end of the elements are safe | ||
while (el = elements.pop()) { | ||
if (el.nodeName.toLowerCase() != "script") break | ||
} | ||
elements.forEach(function(el) { | ||
if (el.nodeName.toLowerCase() == "script") { | ||
// scripts with the async or defer attributes are safe | ||
if (el.async === true || el.defer === true) return | ||
// at this point, if the script isn't whitelisted, throw an error | ||
if (!isWhitelisted(el)) { | ||
reporter.warn( | ||
"script-placement", | ||
"<script> elements should appear right before " | ||
+ "the closing </body> tag for optimal performance.", | ||
el | ||
) | ||
} | ||
} | ||
}) | ||
}) | ||
} | ||
) | ||
|
||
HTMLInspector.rules.add( | ||
"unnecessary-elements", | ||
{ | ||
isUnnecessary: function(element) { | ||
var name = element.nodeName.toLowerCase() | ||
, isUnsemantic = name == "div" || name == "span" | ||
, isAttributed = element.attributes.length === 0 | ||
return isUnsemantic && isAttributed | ||
} | ||
}, | ||
function(listener, reporter, config) { | ||
listener.on('element', function(name) { | ||
if (config.isUnnecessary(this)) { | ||
reporter.warn( | ||
"unnecessary-elements", | ||
"Do not use <div> or <span> elements without any attributes.", | ||
this | ||
) | ||
} | ||
} | ||
) | ||
}) | ||
|
||
HTMLInspector.rules.add( | ||
"unused-classes", | ||
{ | ||
whitelist: [ | ||
/^js\-/, | ||
/^supports\-/, | ||
/^language\-/, | ||
/^lang\-/ | ||
] | ||
}, | ||
function(listener, reporter, config) { | ||
|
||
var css = HTMLInspector.modules.css | ||
, classes = css.getClassSelectors() | ||
, foundIn = this.utils.foundIn | ||
|
||
listener.on("class", function(name) { | ||
if (!foundIn(name, config.whitelist) && classes.indexOf(name) < 0) { | ||
reporter.warn( | ||
"unused-classes", | ||
"The class '" | ||
+ name | ||
+ "' is used in the HTML but not found in any stylesheet.", | ||
this | ||
) | ||
} | ||
} | ||
) | ||
}) |
114 changes: 114 additions & 0 deletions
114
ajax/libs/html-inspector/0.4.1/html-inspector.convention.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
;(function() { | ||
|
||
// ============================================================ | ||
// There are several different BEM naming conventions that | ||
// I'm aware of. To make things easier, I refer to the | ||
// methodologies by the name of projects that utilize them. | ||
// | ||
// suit: https://github.com/necolas/suit | ||
// ------------------------------------- | ||
// BlockName | ||
// BlockName--modifierName | ||
// BlockName-elementName | ||
// BlockName-elementName--modifierName | ||
// | ||
// inuit: http://inuitcss.com/ | ||
// --------------------------- | ||
// block-name | ||
// block-name--modifier-name | ||
// block-name__element-name | ||
// block-name__element-name--modifier-name | ||
// | ||
// yandex: http://bem.info/ | ||
// ------------------------ | ||
// block-name | ||
// block-name__elemement-name | ||
// block-name_modifier_name | ||
// block-name__element-name_modifier_name | ||
// | ||
// ============================================================ | ||
|
||
var methodologies = { | ||
"suit": { | ||
modifier: /^([A-Z][a-zA-Z]*(?:\-[a-zA-Z]+)?)\-\-[a-zA-Z]+$/, | ||
element: /^([A-Z][a-zA-Z]*)\-[a-zA-Z]+$/ | ||
}, | ||
"inuit": { | ||
modifier: /^((?:[a-z]+\-)*[a-z]+(?:__(?:[a-z]+\-)*[a-z]+)?)\-\-(?:[a-z]+\-)*[a-z]+$/, | ||
element: /^((?:[a-z]+\-)*[a-z]+)__(?:[a-z]+\-)*[a-z]+$/ | ||
}, | ||
"yandex": { | ||
modifier: /^((?:[a-z]+\-)*[a-z]+(?:__(?:[a-z]+\-)*[a-z]+)?)_(?:[a-z]+_)*[a-z]+$/, | ||
element: /^((?:[a-z]+\-)*[a-z]+)__(?:[a-z]+\-)*[a-z]+$/ | ||
} | ||
} | ||
|
||
function getMethodology() { | ||
if (typeof config.methodology == "string") { | ||
return methodologies[config.methodology] | ||
} | ||
return config.methodology | ||
} | ||
|
||
var config = { | ||
|
||
methodology: "suit", | ||
|
||
getBlockName: function(elementOrModifier) { | ||
var block | ||
, methodology = getMethodology() | ||
if (methodology.modifier.test(elementOrModifier)) | ||
return block = RegExp.$1 | ||
if (methodology.element.test(elementOrModifier)) | ||
return block = RegExp.$1 | ||
return block || false | ||
}, | ||
|
||
isElement: function(cls) { | ||
return getMethodology().element.test(cls) | ||
}, | ||
|
||
isModifier: function(cls) { | ||
return getMethodology().modifier.test(cls) | ||
} | ||
} | ||
|
||
HTMLInspector.rules.add( | ||
"bem-conventions", | ||
config, | ||
function(listener, reporter, config) { | ||
|
||
var parents = this.utils.parents | ||
, matches = this.utils.matches | ||
|
||
listener.on('class', function(name) { | ||
if (config.isElement(name)) { | ||
// check the ancestors for the block class | ||
var ancestorIsBlock = parents(this).some(function(el) { | ||
return matches(el, "." + config.getBlockName(name)) | ||
}) | ||
if (!ancestorIsBlock) { | ||
reporter.warn( | ||
"bem-conventions", | ||
"The BEM element '" + name | ||
+ "' must be a descendent of '" + config.getBlockName(name) | ||
+ "'.", | ||
this | ||
) | ||
} | ||
} | ||
if (config.isModifier(name)) { | ||
if (!matches(this, "." + config.getBlockName(name))) { | ||
reporter.warn( | ||
"bem-conventions", | ||
"The BEM modifier class '" + name | ||
+ "' was found without the unmodified class '" + config.getBlockName(name) | ||
+ "'.", | ||
this | ||
) | ||
} | ||
} | ||
} | ||
) | ||
}) | ||
}()) |
Oops, something went wrong.