1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
var lop = require("lop");
var RegexTokeniser = lop.RegexTokeniser;
var htmlPaths = require("./html-paths");
exports.read = read;
function read(string) {
var capture = lop.rules.sequence.capture;
var identifierRule = lop.rules.tokenOfType("identifier");
var whitespaceRule = lop.rules.tokenOfType("whitespace");
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 styleElementRule = lop.rules.sequence(
capture(identifierRule),
capture(lop.rules.zeroOrMore(classRule)),
capture(freshRule)
).map(function(tagName, classNames, fresh) {
var attributes = {};
var options = {};
if (classNames.length > 0) {
attributes["class"] = classNames.join(" ");
}
if (fresh) {
options["fresh"] = true;
}
return htmlPaths.element(tagName, attributes, options);
});
var styleRule = lop.rules.then(
lop.rules.zeroOrMoreWithSeparator(
styleElementRule,
lop.rules.sequence(
whitespaceRule,
lop.rules.tokenOfType("gt"),
whitespaceRule
)
),
htmlPaths.elements
);
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));
}
return parseResult.value();
}
function describeFailure(parseResult) {
return parseResult.errors().map(describeError).join("\n");
function describeError(error) {
return error.describe();
}
}
function tokenise(string) {
var tokeniser = new RegexTokeniser([
{name: "identifier", regex: /([a-z][a-z0-9\-]*)/},
{name: "dot", regex: /\./},
{name: "colon", regex: /:/},
{name: "gt", regex: />/},
{name: "whitespace", regex: /\s+/}
]);
return tokeniser.tokenise(string);
}
|