File: //proc/1526/task/1533/cwd/tana/frontend/node_modules/css-tree/lib/walker/create.js
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty;
function walkRules(node, item, list) {
switch (node.type) {
case 'StyleSheet':
var oldStylesheet = this.stylesheet;
this.stylesheet = node;
node.children.each(walkRules, this);
this.stylesheet = oldStylesheet;
break;
case 'Atrule':
if (node.block !== null) {
var oldAtrule = this.atrule;
this.atrule = node;
walkRules.call(this, node.block);
this.atrule = oldAtrule;
}
this.fn(node, item, list);
break;
case 'Rule':
this.fn(node, item, list);
var oldRule = this.rule;
this.rule = node;
walkRules.call(this, node.block);
this.rule = oldRule;
break;
case 'Block':
var oldBlock = this.block;
this.block = node;
node.children.each(walkRules, this);
this.block = oldBlock;
break;
}
}
function walkRulesRight(node, item, list) {
switch (node.type) {
case 'StyleSheet':
var oldStylesheet = this.stylesheet;
this.stylesheet = node;
node.children.eachRight(walkRulesRight, this);
this.stylesheet = oldStylesheet;
break;
case 'Atrule':
if (node.block !== null) {
var oldAtrule = this.atrule;
this.atrule = node;
walkRulesRight.call(this, node.block);
this.atrule = oldAtrule;
}
this.fn(node, item, list);
break;
case 'Rule':
var oldRule = this.rule;
this.rule = node;
walkRulesRight.call(this, node.block);
this.rule = oldRule;
this.fn(node, item, list);
break;
case 'Block':
var oldBlock = this.block;
this.block = node;
node.children.eachRight(walkRulesRight, this);
this.block = oldBlock;
break;
}
}
function walkDeclarations(node) {
switch (node.type) {
case 'StyleSheet':
var oldStylesheet = this.stylesheet;
this.stylesheet = node;
node.children.each(walkDeclarations, this);
this.stylesheet = oldStylesheet;
break;
case 'Atrule':
if (node.block !== null) {
var oldAtrule = this.atrule;
this.atrule = node;
walkDeclarations.call(this, node.block);
this.atrule = oldAtrule;
}
break;
case 'Rule':
var oldRule = this.rule;
this.rule = node;
if (node.block !== null) {
walkDeclarations.call(this, node.block);
}
this.rule = oldRule;
break;
case 'Block':
node.children.each(function(node, item, list) {
if (node.type === 'Declaration') {
this.fn(node, item, list);
} else {
walkDeclarations.call(this, node);
}
}, this);
break;
}
}
function getWalkersFromStructure(name, nodeType) {
var structure = nodeType.structure;
var walkers = [];
for (var key in structure) {
if (hasOwnProperty.call(structure, key) === false) {
continue;
}
var fieldTypes = structure[key];
var walker = {
name: key,
type: false,
nullable: false
};
if (!Array.isArray(structure[key])) {
fieldTypes = [structure[key]];
}
for (var i = 0; i < fieldTypes.length; i++) {
var fieldType = fieldTypes[i];
if (fieldType === null) {
walker.nullable = true;
} else if (typeof fieldType === 'string') {
walker.type = 'node';
} else if (Array.isArray(fieldType)) {
walker.type = 'list';
}
}
if (walker.type) {
walkers.push(walker);
}
}
if (walkers.length) {
return {
context: nodeType.walkContext,
fields: walkers
};
}
return null;
}
function getTypesFromConfig(config) {
var types = {};
if (config.node) {
for (var name in config.node) {
if (hasOwnProperty.call(config.node, name)) {
var nodeType = config.node[name];
if (nodeType.structure) {
var walkers = getWalkersFromStructure(name, nodeType);
if (walkers !== null) {
types[name] = walkers;
}
} else {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
}
}
}
return types;
}
function createContext(root, fn) {
var context = {
fn: fn,
root: root,
stylesheet: null,
atrule: null,
atrulePrelude: null,
rule: null,
selector: null,
block: null,
declaration: null,
function: null
};
return context;
}
module.exports = function createWalker(config) {
var types = getTypesFromConfig(config);
var walkers = {};
for (var name in types) {
if (hasOwnProperty.call(types, name)) {
var config = types[name];
walkers[name] = Function('node', 'context', 'walk',
(config.context ? 'var old = context.' + config.context + ';\ncontext.' + config.context + ' = node;\n' : '') +
config.fields.map(function(field) {
var line = field.type === 'list'
? 'node.' + field.name + '.each(walk);'
: 'walk(node.' + field.name + ');';
if (field.nullable) {
line = 'if (node.' + field.name + ') {\n ' + line + '}';
}
return line;
}).join('\n') +
(config.context ? '\ncontext.' + config.context + ' = old;' : '')
);
}
}
return {
walk: function(root, fn) {
function walk(node, item, list) {
fn.call(context, node, item, list);
if (walkers.hasOwnProperty(node.type)) {
walkers[node.type](node, context, walk);
}
}
var context = createContext(root, fn);
walk(root);
},
walkUp: function(root, fn) {
function walk(node, item, list) {
if (walkers.hasOwnProperty(node.type)) {
walkers[node.type](node, context, walk);
}
fn.call(context, node, item, list);
}
var context = createContext(root, fn);
walk(root);
},
walkRules: function(root, fn) {
walkRules.call(createContext(root, fn), root);
},
walkRulesRight: function(root, fn) {
walkRulesRight.call(createContext(root, fn), root);
},
walkDeclarations: function(root, fn) {
walkDeclarations.call(createContext(root, fn), root);
}
};
};