aboutsummaryrefslogtreecommitdiff
path: root/node_modules/css-parse/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/css-parse/index.js')
-rw-r--r--node_modules/css-parse/index.js494
1 files changed, 494 insertions, 0 deletions
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, '') : '';
+}