aboutsummaryrefslogtreecommitdiff
path: root/lib/style-reader.js
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2013-03-29 23:50:12 +0000
committerMichael Williamson <mike@zwobble.org>2013-03-29 23:50:12 +0000
commitb2d02fec9a161cfd657f240806b25bdaca315eea (patch)
tree690fd3747257537c3f952f1a8e128df64b133acf /lib/style-reader.js
parentbdf1832cbc2f9e0dc7355bb7d435a9f6ab574d7e (diff)
Use lop to parse styles
Diffstat (limited to 'lib/style-reader.js')
-rw-r--r--lib/style-reader.js100
1 files changed, 90 insertions, 10 deletions
diff --git a/lib/style-reader.js b/lib/style-reader.js
index 7ee36c2..1da03ba 100644
--- a/lib/style-reader.js
+++ b/lib/style-reader.js
@@ -1,3 +1,6 @@
+var lop = require("lop");
+var StringSource = lop.StringSource;
+
var styles = require("./styles");
exports.read = read;
@@ -10,16 +13,93 @@ function read(string) {
}
function readElement(string) {
- var colonParts = string.split(":");
- var parts = colonParts[0].split(".");
- var tagName = parts[0];
- var classNames = parts.slice(1);
- var options = {};
- if (classNames.length > 0) {
- options["class"] = classNames.join(" ");
+ var capture = lop.rules.sequence.capture;
+
+ var identifierRule = lop.rules.tokenOfType("identifier");
+ var classRule = lop.rules.sequence(
+ lop.rules.tokenOfType("dot"),
+ capture(identifierRule)
+ ).head();
+ var freshRule = lop.rules.then(
+ lop.rules.optional(lop.rules.sequence(
+ lop.rules.tokenOfType("colon"),
+ lop.rules.token("identifier", "fresh")
+ )),
+ function(option) {
+ return option.map(function() {
+ return true;
+ }).valueOrElse(false);
+ }
+ );
+
+ var styleRule = lop.rules.sequence(
+ capture(identifierRule),
+ capture(lop.rules.zeroOrMore(classRule)),
+ capture(freshRule)
+ ).map(function(tagName, classNames, fresh) {
+ var options = {};
+ if (classNames.length > 0) {
+ options["class"] = classNames.join(" ");
+ }
+ if (fresh) {
+ options["fresh"] = true;
+ }
+ return styles.element(tagName, options);
+ });
+
+ var tokens = tokenise(string);
+ var parser = lop.Parser();
+ var parseResult = parser.parseTokens(styleRule, tokens);
+ if (!parseResult.isSuccess()) {
+ throw new Error("Failed to parse: " + describeFailure(parseResult));
}
- if (colonParts[1] === "fresh") {
- options.fresh = true;
+ return parseResult.value();
+}
+
+function describeFailure(parseResult) {
+ return parseResult.errors().map(describeError).join("\n");
+
+ function describeError(error) {
+ return error.describe();
}
- return styles.element(tagName, options);
}
+
+function tokenise(string) {
+ var source = new StringSource(string, "raw string");
+ var index = 0;
+ var tokens = [];
+
+ while (index < string.length) {
+ var nextToken = readNextToken(string, index, source);
+ if (!nextToken) {
+ throw new Error("Could not read token from: " + string.substring(index));
+ }
+ index += nextToken.value.length;
+ tokens.push(nextToken);
+ }
+ tokens.push(new lop.Token("end", null, source.range(string.length, string.length)));
+ return tokens;
+}
+
+function readNextToken(string, startIndex, source) {
+ for (var i = 0; i < tokenRegexes.length; i++) {
+ var regex = tokenRegexes[i].regex;
+ regex.lastIndex = startIndex;
+ var result = regex.exec(string);
+ if (result && result.index === startIndex) {
+ var value = result[0];
+ return new lop.Token(
+ tokenRegexes[i].name,
+ value,
+ source.range(startIndex, startIndex + value.length)
+ );
+ }
+ }
+}
+
+var tokenRegexes = [
+ {name: "identifier", regex: /([a-z][a-z0-9\-]*)/g},
+ {name: "dot", regex: /\./g},
+ {name: "colon", regex: /:/g},
+ {name: "whitespace", regex: /\s+/g}
+];