File size: 5,966 Bytes
bc20498 |
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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
import {COMMENT, RULESET, DECLARATION} from './Enum.js'
import {abs, charat, trim, from, sizeof, strlen, substr, append, replace, indexof} from './Utility.js'
import {node, char, prev, next, peek, caret, alloc, dealloc, delimit, whitespace, escaping, identifier, commenter} from './Tokenizer.js'
/**
* @param {string} value
* @return {object[]}
*/
export function compile (value) {
return dealloc(parse('', null, null, null, [''], value = alloc(value), 0, [0], value))
}
/**
* @param {string} value
* @param {object} root
* @param {object?} parent
* @param {string[]} rule
* @param {string[]} rules
* @param {string[]} rulesets
* @param {number[]} pseudo
* @param {number[]} points
* @param {string[]} declarations
* @return {object}
*/
export function parse (value, root, parent, rule, rules, rulesets, pseudo, points, declarations) {
var index = 0
var offset = 0
var length = pseudo
var atrule = 0
var property = 0
var previous = 0
var variable = 1
var scanning = 1
var ampersand = 1
var character = 0
var type = ''
var props = rules
var children = rulesets
var reference = rule
var characters = type
while (scanning)
switch (previous = character, character = next()) {
// (
case 40:
if (previous != 108 && charat(characters, length - 1) == 58) {
if (indexof(characters += replace(delimit(character), '&', '&\f'), '&\f', abs(index ? points[index - 1] : 0)) != -1)
ampersand = -1
break
}
// " ' [
case 34: case 39: case 91:
characters += delimit(character)
break
// \t \n \r \s
case 9: case 10: case 13: case 32:
characters += whitespace(previous)
break
// \
case 92:
characters += escaping(caret() - 1, 7)
continue
// /
case 47:
switch (peek()) {
case 42: case 47:
append(comment(commenter(next(), caret()), root, parent, declarations), declarations)
break
default:
characters += '/'
}
break
// {
case 123 * variable:
points[index++] = strlen(characters) * ampersand
// } ; \0
case 125 * variable: case 59: case 0:
switch (character) {
// \0 }
case 0: case 125: scanning = 0
// ;
case 59 + offset: if (ampersand == -1) characters = replace(characters, /\f/g, '')
if (property > 0 && (strlen(characters) - length))
append(property > 32 ? declaration(characters + ';', rule, parent, length - 1, declarations) : declaration(replace(characters, ' ', '') + ';', rule, parent, length - 2, declarations), declarations)
break
// @ ;
case 59: characters += ';'
// { rule/at-rule
default:
append(reference = ruleset(characters, root, parent, index, offset, rules, points, type, props = [], children = [], length, rulesets), rulesets)
if (character === 123)
if (offset === 0)
parse(characters, root, reference, reference, props, rulesets, length, points, children)
else
switch (atrule === 99 && charat(characters, 3) === 110 ? 100 : atrule) {
// d l m s
case 100: case 108: case 109: case 115:
parse(value, reference, reference, rule && append(ruleset(value, reference, reference, 0, 0, rules, points, type, rules, props = [], length, children), children), rules, children, length, points, rule ? props : children)
break
default:
parse(characters, reference, reference, reference, [''], children, 0, points, children)
}
}
index = offset = property = 0, variable = ampersand = 1, type = characters = '', length = pseudo
break
// :
case 58:
length = 1 + strlen(characters), property = previous
default:
if (variable < 1)
if (character == 123)
--variable
else if (character == 125 && variable++ == 0 && prev() == 125)
continue
switch (characters += from(character), character * variable) {
// &
case 38:
ampersand = offset > 0 ? 1 : (characters += '\f', -1)
break
// ,
case 44:
points[index++] = (strlen(characters) - 1) * ampersand, ampersand = 1
break
// @
case 64:
// -
if (peek() === 45)
characters += delimit(next())
atrule = peek(), offset = length = strlen(type = characters += identifier(caret())), character++
break
// -
case 45:
if (previous === 45 && strlen(characters) == 2)
variable = 0
}
}
return rulesets
}
/**
* @param {string} value
* @param {object} root
* @param {object?} parent
* @param {number} index
* @param {number} offset
* @param {string[]} rules
* @param {number[]} points
* @param {string} type
* @param {string[]} props
* @param {string[]} children
* @param {number} length
* @param {object[]} siblings
* @return {object}
*/
export function ruleset (value, root, parent, index, offset, rules, points, type, props, children, length, siblings) {
var post = offset - 1
var rule = offset === 0 ? rules : ['']
var size = sizeof(rule)
for (var i = 0, j = 0, k = 0; i < index; ++i)
for (var x = 0, y = substr(value, post + 1, post = abs(j = points[i])), z = value; x < size; ++x)
if (z = trim(j > 0 ? rule[x] + ' ' + y : replace(y, /&\f/g, rule[x])))
props[k++] = z
return node(value, root, parent, offset === 0 ? RULESET : type, props, children, length, siblings)
}
/**
* @param {number} value
* @param {object} root
* @param {object?} parent
* @param {object[]} siblings
* @return {object}
*/
export function comment (value, root, parent, siblings) {
return node(value, root, parent, COMMENT, from(char()), substr(value, 2, -2), 0, siblings)
}
/**
* @param {string} value
* @param {object} root
* @param {object?} parent
* @param {number} length
* @param {object[]} siblings
* @return {object}
*/
export function declaration (value, root, parent, length, siblings) {
return node(value, root, parent, DECLARATION, substr(value, 0, length), substr(value, length + 1, -1), length, siblings)
}
|