UNPKG

five-bells-visualization

Version:
141 lines (126 loc) 3.93 kB
<!-- @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>