UNPKG

css-whitespace

Version:

Whitespace significant CSS to regular CSS

203 lines (166 loc) 3.13 kB
/** * Pesudo selectors. */ var pseudos = [ ':selection', 'fullscreen', 'nth-child', 'first-child', 'last-child', 'link', 'visited', 'hover', 'active', 'focus', 'first-letter', 'first-line', 'before', 'after', 'lang', 'enabled', 'disabled', 'only-child', 'only-of-type', 'first-of-type', 'last-of-type', 'nth-last-of-type', 'nth-of-type', 'root', 'empty', 'target', 'not', '-o', '-ms', '-moz', '-webkit' ] /** * Property regexp. */ pseudos = pseudos.join('|'); var propre = new RegExp('^ *([-\\w]+):(?!' + pseudos + ') *([^\n]*)'); /** * Scan the given `str` returning tokens. * * @param {String} str * @return {Array} * @api private */ module.exports = function(str) { var indents = [0]; var stash = []; // strip blanks str = str.replace(/\r/g, ''); str = str.replace(/\n\s*\n/gm, '\n'); return scan(); /** * tok+ */ function scan() { var toks = [] , curr; while (str.length) { curr = next(); curr && toks.push(curr); if (str.length && !curr) { throw new Error('syntax error near "' + str.slice(0, 10) + '"'); } } toks = toks.concat(stash); while (indents.pop()) toks.push(['outdent']); toks.push(['eos']); return toks; } /** * eos * | indentation * | rule */ function next() { return stashed() || comment() || csscomment() || indentation() || prop() || rule(); } /** * Deferred tokens. */ function stashed() { return stash.shift(); } /** * Comment. */ function comment() { var m = str.match(/^\/\/([^\n]*)/); if (!m) return; str = str.slice(m[0].length); return next(); } /** * Multiline comment. */ function csscomment() { if ('/' != str[0] || '*' != str[1]) return; str = str.slice(2); var i = 0; while ('*' != str[i] && '/' != str[i + 1]) ++i; var buf = str.slice(0, i); str = str.slice(buf.length + 2); return ['comment', buf]; } /** * INDENT * | OUTDENT */ function indentation() { var spaces = str.match(/^\n( *)/); if (!spaces) return; str = str.slice(spaces[0].length); spaces = spaces[1].length; var prev = indents[indents.length - 1]; // INDENT if (spaces > prev) return indent(spaces); // OUTDENT if (spaces < prev) return outdent(spaces); return next(); } /** * Indent. */ function indent(spaces) { indents.push(spaces); return ['indent']; } /** * Outdent. */ function outdent(spaces) { while (indents[indents.length - 1] > spaces) { indents.pop(); stash.push(['outdent']); } return stashed(); } /** * Property. */ function prop() { var m = str.match(propre); if (!m) return; str = str.slice(m[0].length); return ['prop', m[1], m[2]]; } /** * Rule. */ function rule() { var m = str.match(/^([^\n,]+, *\n|[^\n]+)+/); if (!m) return; str = str.slice(m[0].length); m = m[0].split(/\s*,\s*/); return ['rule', m]; } }