diff options
Diffstat (limited to 'node_modules/css-parse')
| -rw-r--r-- | node_modules/css-parse/Readme.md | 142 | ||||
| -rw-r--r-- | node_modules/css-parse/index.js | 494 | ||||
| -rw-r--r-- | node_modules/css-parse/package.json | 29 |
3 files changed, 665 insertions, 0 deletions
diff --git a/node_modules/css-parse/Readme.md b/node_modules/css-parse/Readme.md new file mode 100644 index 00000000..0f6169ef --- /dev/null +++ b/node_modules/css-parse/Readme.md @@ -0,0 +1,142 @@ +# css-parse [](https://travis-ci.org/visionmedia/css-parse) + + JavaScript CSS parser for nodejs and the browser. + +## Installation + + $ npm install css-parse + +## Usage + +````javascript +var parse = require('css-parse'); + +// CSS input string +var css = "body { \n background-color: #fff;\n }"; + +var output_obj = parse(css); + +// Position and Source parameters +var output_obj_pos = parse(css, { position: true, source: 'file.css' }); + +// Print parsed object as CSS string +console.log(JSON.stringify(output_obj, null, 2)); + +```` + +## Example + +css: + +```css +body { + background: #eee; + color: #888; +} +``` + +parse tree: + +```json +{ + "type": "stylesheet", + "stylesheet": { + "rules": [ + { + "type": "rule", + "selectors": [ + "body" + ], + "declarations": [ + { + "type": "declaration", + "property": "background", + "value": "#eee" + }, + { + "type": "declaration", + "property": "color", + "value": "#888" + } + ] + } + ] + } +} +``` + +parse tree with `.position` enabled: + +```json +{ + "type": "stylesheet", + "stylesheet": { + "rules": [ + { + "type": "rule", + "selectors": [ + "body" + ], + "declarations": [ + { + "type": "declaration", + "property": "background", + "value": "#eee", + "position": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 19 + } + } + }, + { + "type": "declaration", + "property": "color", + "value": "#888", + "position": { + "start": { + "line": 4, + "column": 3 + }, + "end": { + "line": 4, + "column": 14 + } + } + } + ], + "position": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 5, + "column": 2 + } + } + } + ] + } +} +``` + +If you also pass in `source: 'path/to/original.css'`, that will be set +on `node.position.source`. + +## Performance + + Parsed 15,000 lines of CSS (2mb) in 40ms on my macbook air. + +## Related + + [css-stringify](https://github.com/visionmedia/css-stringify "CSS-Stringify") + [css-value](https://github.com/visionmedia/css-value "CSS-Value") + +## License + + MIT diff --git a/node_modules/css-parse/index.js b/node_modules/css-parse/index.js new file mode 100644 index 00000000..3e200938 --- /dev/null +++ b/node_modules/css-parse/index.js @@ -0,0 +1,494 @@ + +module.exports = function(css, options){ + options = options || {}; + + /** + * Positional. + */ + + var lineno = 1; + var column = 1; + + /** + * Update lineno and column based on `str`. + */ + + function updatePosition(str) { + var lines = str.match(/\n/g); + if (lines) lineno += lines.length; + var i = str.lastIndexOf('\n'); + column = ~i ? str.length - i : column + str.length; + } + + /** + * Mark position and patch `node.position`. + */ + + function position() { + var start = { line: lineno, column: column }; + if (!options.position) return positionNoop; + + return function(node){ + node.position = { + start: start, + end: { line: lineno, column: column }, + source: options.source + }; + + whitespace(); + return node; + } + } + + /** + * Return `node`. + */ + + function positionNoop(node) { + whitespace(); + return node; + } + + /** + * Error `msg`. + */ + + function error(msg) { + var err = new Error(msg + ' near line ' + lineno + ':' + column); + err.filename = options.source; + err.line = lineno; + err.column = column; + err.source = css; + throw err; + } + + /** + * Parse stylesheet. + */ + + function stylesheet() { + return { + type: 'stylesheet', + stylesheet: { + rules: rules() + } + }; + } + + /** + * Opening brace. + */ + + function open() { + return match(/^{\s*/); + } + + /** + * Closing brace. + */ + + function close() { + return match(/^}/); + } + + /** + * Parse ruleset. + */ + + function rules() { + var node; + var rules = []; + whitespace(); + comments(rules); + while (css.charAt(0) != '}' && (node = atrule() || rule())) { + rules.push(node); + comments(rules); + } + return rules; + } + + /** + * Match `re` and return captures. + */ + + function match(re) { + var m = re.exec(css); + if (!m) return; + var str = m[0]; + updatePosition(str); + css = css.slice(str.length); + return m; + } + + /** + * Parse whitespace. + */ + + function whitespace() { + match(/^\s*/); + } + + /** + * Parse comments; + */ + + function comments(rules) { + var c; + rules = rules || []; + while (c = comment()) rules.push(c); + return rules; + } + + /** + * Parse comment. + */ + + function comment() { + var pos = position(); + if ('/' != css.charAt(0) || '*' != css.charAt(1)) return; + + var i = 2; + while (null != css.charAt(i) && ('*' != css.charAt(i) || '/' != css.charAt(i + 1))) ++i; + i += 2; + + var str = css.slice(2, i - 2); + column += 2; + updatePosition(str); + css = css.slice(i); + column += 2; + + return pos({ + type: 'comment', + comment: str + }); + } + + /** + * Parse selector. + */ + + function selector() { + var m = match(/^([^{]+)/); + if (!m) return; + return trim(m[0]).split(/\s*,\s*/); + } + + /** + * Parse declaration. + */ + + function declaration() { + var pos = position(); + + // prop + var prop = match(/^(\*?[-#\/\*\w]+(\[[0-9a-z_-]+\])?)\s*/); + if (!prop) return; + prop = trim(prop[0]); + + // : + if (!match(/^:\s*/)) return error("property missing ':'"); + + // val + var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); + if (!val) return error('property missing value'); + + var ret = pos({ + type: 'declaration', + property: prop, + value: trim(val[0]) + }); + + // ; + match(/^[;\s]*/); + + return ret; + } + + /** + * Parse declarations. + */ + + function declarations() { + var decls = []; + + if (!open()) return error("missing '{'"); + comments(decls); + + // declarations + var decl; + while (decl = declaration()) { + decls.push(decl); + comments(decls); + } + + if (!close()) return error("missing '}'"); + return decls; + } + + /** + * Parse keyframe. + */ + + function keyframe() { + var m; + var vals = []; + var pos = position(); + + while (m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)) { + vals.push(m[1]); + match(/^,\s*/); + } + + if (!vals.length) return; + + return pos({ + type: 'keyframe', + values: vals, + declarations: declarations() + }); + } + + /** + * Parse keyframes. + */ + + function atkeyframes() { + var pos = position(); + var m = match(/^@([-\w]+)?keyframes */); + + if (!m) return; + var vendor = m[1]; + + // identifier + var m = match(/^([-\w]+)\s*/); + if (!m) return error("@keyframes missing name"); + var name = m[1]; + + if (!open()) return error("@keyframes missing '{'"); + + var frame; + var frames = comments(); + while (frame = keyframe()) { + frames.push(frame); + frames = frames.concat(comments()); + } + + if (!close()) return error("@keyframes missing '}'"); + + return pos({ + type: 'keyframes', + name: name, + vendor: vendor, + keyframes: frames + }); + } + + /** + * Parse supports. + */ + + function atsupports() { + var pos = position(); + var m = match(/^@supports *([^{]+)/); + + if (!m) return; + var supports = trim(m[1]); + + if (!open()) return error("@supports missing '{'"); + + var style = comments().concat(rules()); + + if (!close()) return error("@supports missing '}'"); + + return pos({ + type: 'supports', + supports: supports, + rules: style + }); + } + + /** + * Parse host. + */ + + function athost() { + var pos = position(); + var m = match(/^@host */); + + if (!m) return; + + if (!open()) return error("@host missing '{'"); + + var style = comments().concat(rules()); + + if (!close()) return error("@host missing '}'"); + + return pos({ + type: 'host', + rules: style + }); + } + + /** + * Parse media. + */ + + function atmedia() { + var pos = position(); + var m = match(/^@media *([^{]+)/); + + if (!m) return; + var media = trim(m[1]); + + if (!open()) return error("@media missing '{'"); + + var style = comments().concat(rules()); + + if (!close()) return error("@media missing '}'"); + + return pos({ + type: 'media', + media: media, + rules: style + }); + } + + /** + * Parse paged media. + */ + + function atpage() { + var pos = position(); + var m = match(/^@page */); + if (!m) return; + + var sel = selector() || []; + + if (!open()) return error("@page missing '{'"); + var decls = comments(); + + // declarations + var decl; + while (decl = declaration()) { + decls.push(decl); + decls = decls.concat(comments()); + } + + if (!close()) return error("@page missing '}'"); + + return pos({ + type: 'page', + selectors: sel, + declarations: decls + }); + } + + /** + * Parse document. + */ + + function atdocument() { + var pos = position(); + var m = match(/^@([-\w]+)?document *([^{]+)/); + if (!m) return; + + var vendor = trim(m[1]); + var doc = trim(m[2]); + + if (!open()) return error("@document missing '{'"); + + var style = comments().concat(rules()); + + if (!close()) return error("@document missing '}'"); + + return pos({ + type: 'document', + document: doc, + vendor: vendor, + rules: style + }); + } + + /** + * Parse import + */ + + function atimport() { + return _atrule('import'); + } + + /** + * Parse charset + */ + + function atcharset() { + return _atrule('charset'); + } + + /** + * Parse namespace + */ + + function atnamespace() { + return _atrule('namespace') + } + + /** + * Parse non-block at-rules + */ + + function _atrule(name) { + var pos = position(); + var m = match(new RegExp('^@' + name + ' *([^;\\n]+);')); + if (!m) return; + var ret = { type: name }; + ret[name] = trim(m[1]); + return pos(ret); + } + + /** + * Parse at rule. + */ + + function atrule() { + if (css[0] != '@') return; + + return atkeyframes() + || atmedia() + || atsupports() + || atimport() + || atcharset() + || atnamespace() + || atdocument() + || atpage() + || athost(); + } + + /** + * Parse rule. + */ + + function rule() { + var pos = position(); + var sel = selector(); + + if (!sel) return; + comments(); + + return pos({ + type: 'rule', + selectors: sel, + declarations: declarations() + }); + } + + return stylesheet(); +}; + +/** + * Trim `str`. + */ + +function trim(str) { + return str ? str.replace(/^\s+|\s+$/g, '') : ''; +} diff --git a/node_modules/css-parse/package.json b/node_modules/css-parse/package.json new file mode 100644 index 00000000..3acca2f8 --- /dev/null +++ b/node_modules/css-parse/package.json @@ -0,0 +1,29 @@ +{ + "name": "css-parse", + "version": "1.7.0", + "description": "CSS parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "author": "TJ Holowaychuk <tj@vision-media.ca>", + "license": "MIT", + "devDependencies": { + "mocha": "*", + "should": "*", + "matcha": "~0.4.0", + "bytes": "~0.2.1" + }, + "main": "index", + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/css-parse.git" + }, + "scripts": { + "test": "make test" + }, + "files": [ + "index.js" + ] +} |
