Attribute Parsing
by bgrins
HTML
<h4>Attribute Parsing Demo</h4>
<p>
Notes: This is a comparison of the conversion from string->attribute set that happens inside of the inspector tab when modifying an attribute. The proposed parsing uses the DOM to handle conversion of string to attributes. Potentially could have security issues, but there is <a href="https://developer.mozilla.org/en-US/docs/Code_snippets/HTML_to_DOM">Components.interfaces.nsIScriptableUnescapeHTML</a> that should do the same thing.
</p>
<p>Here the thing I am talking about:<br /><img src='http://i.imgur.com/hipe5qE.gif' /></p>
<h4>Edit these below to try out different odd inputs</h4>
<p>
<code>Red = Proposed Parsing</code>
<code class="two">Blue = Current Parsing</code>
</p>
CSS
body {
font-family: "Lucida Grande";
}
code {
margin-left: 2;
margin-top: 4px;
color: #900;
display:block;
}
input {
box-sizing:border-box;
width: 60%;
display:block;
}
div {
margin: 15px 0;
padding-bottom: 5px;
border-bottom: solid 2px #ccc;
padding-top: 3px;
}
code.two {
color: #009;
}
JavaScript
var inputs = [
"id=\"hi\" class='show-selected'",
"<why-would-you-do-this>=\"???\"",
"id=\"h<i\" some:attribute=\"some\"",
"id=\"h'i\"",
"id='h\"i'",
"id='hi'",
"id='hi' a",
"id='hi' a=\"\"",
"id='hi' a=b",
"id='hi' a=b'",
"id='hi' a=b'",
"id='one' id='two' id='three'",
"style=\"font-family: 'Lucida Grande', sans-serif; font-size: 75%;\""
];
function escapeAttributeValues(attr) {
var div = document.createElement("div");
attr = simpleEscape(attr);
div.innerHTML = "<div " + attr + "></div>";
var attributes=[];
var el = div.childNodes[0];
for (var i=0, l=el.attributes.length; i<l; i++){
var attr = el.attributes.item(i)
attributes.push({name:attr.nodeName, value: attr.nodeValue});
}
return attributes;
}
/**
* Properly escape attribute values.
*
* @param {String} attr
* The attributes for which the values are to be escaped.
* @return {Array}
* An array of attribute names and their escaped values.
*/
function escapeAttributeValues2(attr) {
var name = null;
var value = null;
var result = "";
var attributes = [];
while(attr.length > 0) {
var match;
var dirty = false;
// Trim quotes and spaces from attr start
match = attr.match(/^["\s]+/);
if (match && match.length == 1) {
attr = attr.substr(match[0].length);
}
// Name
if (!dirty) {
match = attr.match(/^([\w-]+)="/);
if (match && match.length == 2) {
if (name) {
// We had a name without a value e.g. disabled. Let's set the value to "";
value = "";
} else {
name = match[1];
attr = attr.substr(match[0].length);
}
dirty = true;
}
}
// Value (in the case of multiple attributes)
if (!dirty) {
match = attr.match(/^(.+?)"\s+[\w-]+="/);
if (match && match.length > 1) {
value = typeof match[1] == "undefined" ? match[2] : match[1];
attr =...