five-bells-visualization
Version:
Tool to visualize Five Bells payments
141 lines (126 loc) • 3.93 kB
HTML
<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<script>
/*
Extremely simple css parser. Intended to be not more than what we need
and definitely not necessarly correct =).
*/
(function() {
// given a string of css, return a simple rule tree
function parse(text) {
text = clean(text);
return parseCss(lex(text), text);
}
// remove stuff we don't care about that may hinder parsing
function clean(cssText) {
return cssText.replace(rx.comments, '').replace(rx.port, '');
}
// super simple {...} lexer that returns a node tree
function lex(text) {
var root = {start: 0, end: text.length};
var n = root;
for (var i=0, s=0, l=text.length; i < l; i++) {
switch (text[i]) {
case OPEN_BRACE:
//console.group(i);
if (!n.rules) {
n.rules = [];
}
var p = n;
var previous = p.rules[p.rules.length-1];
n = {start: i+1, parent: p, previous: previous};
p.rules.push(n);
break;
case CLOSE_BRACE:
//console.groupEnd(n.start);
n.end = i+1;
n = n.parent || root;
break;
}
}
return root;
}
// add selectors/cssText to node tree
function parseCss(node, text) {
var t = text.substring(node.start, node.end-1);
node.cssText = t.trim();
if (node.parent) {
var ss = node.previous ? node.previous.end : node.parent.start;
t = text.substring(ss, node.start-1);
// TODO(sorvell): ad hoc; make selector include only after last ;
// helps with mixin syntax
t = t.substring(t.lastIndexOf(';')+1);
node.selector = t.trim();
}
var r$ = node.rules;
if (r$) {
for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) {
parseCss(r, text);
}
}
return node;
}
// stringify parsed css.
function stringify(node, text) {
text = text || '';
// calc rule cssText
var cssText = '';
if (node.cssText || node.rules) {
var r$ = node.rules;
if (r$ && !hasMixinRules(r$)) {
for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) {
cssText = stringify(r, cssText);
}
} else {
cssText = removeCustomProps(node.cssText).trim();
if (cssText) {
cssText = ' ' + cssText + '\n';
}
}
}
// emit rule iff there is cssText
if (cssText) {
if (node.selector) {
text += node.selector + ' ' + OPEN_BRACE + '\n';
}
text += cssText;
if (node.selector) {
text += CLOSE_BRACE + '\n\n';
}
}
return text;
}
var OPEN_BRACE = '{';
var CLOSE_BRACE = '}';
function hasMixinRules(rules) {
return (rules[0].selector.indexOf(VAR_START) >= 0);
}
function removeCustomProps(cssText) {
return cssText
.replace(rx.customProp, '')
.replace(rx.mixinProp, '')
.replace(rx.mixinApply, '');
}
var VAR_START = '--';
// helper regexp's
var rx = {
comments: /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,
port: /@import[^;]*;/gim,
customProp: /--[^;{]*?:[^{};]*?;/gim,
mixinProp: /--[^;{]*?:[^{;]*?{[^}]*?}/gim,
mixinApply: /@mixin[\s]*\([^)]*?\)[\s]*;/gim
};
// exports
Polymer.CssParse = {
parse: parse,
stringify: stringify
};
})();
</script>