Permalink
Browse files

finished up the parsing for inline styles. code review time

  • Loading branch information...
Pomax committed Aug 29, 2012
1 parent c588c29 commit 6ad33d19a82b4a9a548a5497af7e374098be1a01
Showing with 109 additions and 14 deletions.
  1. +55 −13 slowparse.js
  2. +5 −0 spec/errors.base.html
  3. +39 −0 spec/index.html
  4. +10 −1 test/test-slowparse.js
View
@@ -259,6 +259,24 @@ var Slowparse = (function() {
}
};
},
+ MISSING_CSS_PROPVAL_SEPARATOR: function(parser, start, end, startProperty, endProperty) {
+ return {
+ interval: {
+ start: start,
+ end: end
+ },
+ start: {
+ property: startProperty,
+ start: start,
+ end: start + startProperty.length
+ },
+ end: {
+ property: endProperty,
+ start: end - endProperty.length,
+ end: end
+ }
+ };
+ },
MISSING_CSS_VALUE: function(parser, start, end, property) {
return {
cssProperty: {
@@ -1261,37 +1279,61 @@ var Slowparse = (function() {
});
}
},
+ // helper function
+ _toCamelCase: function(cssProperty) {
+ return cssProperty.trim().replace(/-([a-z])/g, function(a,b) { return b.toUpperCase(); });
+ },
// validate inline styling of HTML/SVG elements. Note that
- // inline styling is much simpler than full CSS, in that only
+ // inline styling is much simpler than full CSS, as only
// (property: value [; [property: value]]) syntax is used.
- _parseInlineStyle: function(styleString, start) {
+ _parseInlineStyle: function(styleString, stringStart) {
var rules = styleString.split(";"), i, last=rules.length, rule,
pair, property, value,
- pos = 0;
+ offset = 0, start = 0, end = 0;
for(i=0; i<last; i++) {
rule = rules[i];
- if (rule === "") continue;
+ // split may generate an empty token, so skip over that
+ if (rule.trim() === "") continue;
+
+ // interpret a style rule
+ start = offset + stringStart;
+ end = start + rule.length;
+
if (rule.indexOf(":")!==-1) {
pair = rule.split(":");
+
+ // missing ";" somewhere?
+ if(pair.length>2) {
+ end = start + pair[0].length + 1 + pair[1].length;
+ var tail = pair[1].split(/\s/);
+ tail = tail[tail.length-1];
+ throw new ParseError("MISSING_CSS_PROPVAL_SEPARATOR", this, start, end, pair[0].trim(), tail.trim());
+ }
+
property = pair[0];
- // legal property?
+ end = start + property.length;
+ // throw on illegal property
if(!this.cssParser._knownCSSProperty(property.trim())) {
- console.log("error: ["+property+"] at {"+(pos+start)+","+(pos+start+property.length)+"} is not a known CSS property");
+ throw new ParseError("INVALID_CSS_PROPERTY_NAME", this, start, end, property);
}
- pos += 1;
- // we don't do value validation at the moment
+ // increment next offset for the lost :
+ offset++;
+ end++;
value = pair[1];
if(!value.trim()) {
- console.log("error: missing value for property ["+property+"] at {"+(pos+start)+","+(pos+start+property.length)+"}");
+ throw new ParseError("MISSING_CSS_VALUE", this, start, end, property);
}
- } else {
+ }
+
+ // error handling if there is no ":" where there should be one.
+ else {
if(!this.cssParser._knownCSSProperty(rule.trim())) {
- console.log("error: ["+rule.trim()+"] at {"+(pos+start)+","+(pos+rule.length)+"} is not a known CSS property");
+ throw new ParseError("UNFINISHED_CSS_PROPERTY", this, start, end, rule.trim());
} else {
- console.log("error: missing value for property ["+rule.trim()+"] at {"+(pos+start)+","+(pos+start+rule.length)+"}");
+ throw new ParseError("MISSING_CSS_VALUE", this, start, end, rule.trim());
}
}
- pos += (i>0 ? 1 : 0 ) + rule.length;
+ offset += (i>0 ? 1 : 0 ) + rule.length;
}
}
};
View
@@ -102,6 +102,11 @@
still needs finalising with :
</p>
</div>
+<div class="error-msg MISSING_CSS_PROPVAL_SEPARATOR">
+ <p>Missing ; between <em data-highlight="{{start.start}},{{start.end}}">{{start.property}}</em>
+ and <em data-highlight="{{end.start}},{{end.end}}">{{end.property}}</em>.
+ </p>
+</div>
<div class="error-msg MISSING_CSS_VALUE">
<p>Missing value for <em data-highlight="{{cssProperty.start}},{{cssProperty.end}}">{{cssProperty.property}}</em>.
</p>
View
@@ -415,6 +415,30 @@ <h1 class="error-category">CSS Errors</h1>
}
</script>
</div>
+<div class="test">
+ <script type="text/x-bad-html">
+ <p style="font-family: serif color: red; border-radius: red;">lol</p>
+ </script>
+ <script type="application/json">
+ {
+ "type": "MISSING_CSS_PROPVAL_SEPARATOR",
+ "interval": {
+ "start": 10,
+ "end": 34
+ },
+ "start": {
+ "property": "font-family",
+ "start": 10,
+ "end": 21
+ },
+ "end": {
+ "property": "color",
+ "start": 29,
+ "end": 34
+ }
+ }
+ </script>
+</div>
<div class="test">
<script type="text/x-bad-html">
<style> a { color:
@@ -430,6 +454,21 @@ <h1 class="error-category">CSS Errors</h1>
}
</script>
</div>
+<div class="test">
+ <script type="text/x-bad-html">
+ <p style="colour:">test</p>
+ </script>
+ <script type="application/json">
+ {
+ "type": "INVALID_CSS_PROPERTY_NAME",
+ "cssProperty": {
+ "start": 10,
+ "end": 16,
+ "property": "colour"
+ }
+ }
+ </script>
+</div>
<div class="test">
<script type="text/x-bad-html">
<style> a { colour:
View
@@ -251,9 +251,18 @@ testManySnippets("parsing of valid HTML w/ whitespace", [
"Document fragment is correct.");
});
+test("testing inline CSS - ", function() {
+ var html = "<p style='font-family: serif; color: red; border-radius: 4px;'>test</p>";
+ var doc = parseWithoutErrors(html);
+
+ equal(doc.childNodes.length, 1, "doc has one child node");
+ var style = doc.childNodes[0].getAttribute("style");
+ equal(style, "font-family: serif; color: red; border-radius: 4px;", "style attribute contains the correct string");
+});
+
testStyleSheet("parsing of CSS rule w/ one decl, no semicolon",
"body { color: pink }",
- function(html, css, styleContents) {
+ function(html, css, styleContents) {
equal(styleContents.parseInfo.rules.length, 1);
equal(styleContents.parseInfo.rules[0].declarations.properties.length, 1);

0 comments on commit 6ad33d1

Please sign in to comment.