first commit
This commit is contained in:
291
build/node_modules/csso/lib/utils/translateWithSourceMap.js
generated
vendored
Normal file
291
build/node_modules/csso/lib/utils/translateWithSourceMap.js
generated
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
var SourceMapGenerator = require('source-map').SourceMapGenerator;
|
||||
var SourceNode = require('source-map').SourceNode;
|
||||
|
||||
// Our own implementation of SourceNode#toStringWithSourceMap,
|
||||
// since SourceNode doesn't allow multiple references to original source.
|
||||
// Also, as we know structure of result we could be optimize generation
|
||||
// (currently it's ~40% faster).
|
||||
function walk(node, fn) {
|
||||
for (var chunk, i = 0; i < node.children.length; i++) {
|
||||
chunk = node.children[i];
|
||||
|
||||
if (chunk instanceof SourceNode) {
|
||||
// this is a hack, because source maps doesn't support for 1(generated):N(original)
|
||||
// if (chunk.merged) {
|
||||
// fn('', chunk);
|
||||
// }
|
||||
|
||||
walk(chunk, fn);
|
||||
} else {
|
||||
fn(chunk, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateSourceMap(root) {
|
||||
var map = new SourceMapGenerator();
|
||||
var css = '';
|
||||
var sourceMappingActive = false;
|
||||
var lastOriginalLine = null;
|
||||
var lastOriginalColumn = null;
|
||||
var lastIndexOfNewline;
|
||||
var generated = {
|
||||
line: 1,
|
||||
column: 0
|
||||
};
|
||||
var activatedMapping = {
|
||||
generated: generated
|
||||
};
|
||||
|
||||
walk(root, function(chunk, original) {
|
||||
if (original.line !== null &&
|
||||
original.column !== null) {
|
||||
if (lastOriginalLine !== original.line ||
|
||||
lastOriginalColumn !== original.column) {
|
||||
map.addMapping({
|
||||
source: original.source,
|
||||
original: original,
|
||||
generated: generated
|
||||
});
|
||||
}
|
||||
|
||||
lastOriginalLine = original.line;
|
||||
lastOriginalColumn = original.column;
|
||||
sourceMappingActive = true;
|
||||
} else if (sourceMappingActive) {
|
||||
map.addMapping(activatedMapping);
|
||||
sourceMappingActive = false;
|
||||
}
|
||||
|
||||
css += chunk;
|
||||
|
||||
lastIndexOfNewline = chunk.lastIndexOf('\n');
|
||||
if (lastIndexOfNewline !== -1) {
|
||||
generated.line += chunk.match(/\n/g).length;
|
||||
generated.column = chunk.length - lastIndexOfNewline - 1;
|
||||
} else {
|
||||
generated.column += chunk.length;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
css: css,
|
||||
map: map
|
||||
};
|
||||
}
|
||||
|
||||
function createAnonymousSourceNode(children) {
|
||||
return new SourceNode(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
children
|
||||
);
|
||||
}
|
||||
|
||||
function createSourceNode(info, children) {
|
||||
if (info.primary) {
|
||||
// special marker node to add several references to original
|
||||
// var merged = createSourceNode(info.merged, []);
|
||||
// merged.merged = true;
|
||||
// children.unshift(merged);
|
||||
|
||||
// use recursion, because primary can also has a primary/merged info
|
||||
return createSourceNode(info.primary, children);
|
||||
}
|
||||
|
||||
return new SourceNode(
|
||||
info.line,
|
||||
info.column - 1,
|
||||
info.source,
|
||||
children
|
||||
);
|
||||
}
|
||||
|
||||
function each(list) {
|
||||
if (list.head === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (list.head === list.tail) {
|
||||
return translate(list.head.data);
|
||||
}
|
||||
|
||||
return list.map(translate).join('');
|
||||
}
|
||||
|
||||
function eachDelim(list, delimeter) {
|
||||
if (list.head === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (list.head === list.tail) {
|
||||
return translate(list.head.data);
|
||||
}
|
||||
|
||||
return list.map(translate).join(delimeter);
|
||||
}
|
||||
|
||||
function translate(node) {
|
||||
switch (node.type) {
|
||||
case 'StyleSheet':
|
||||
return createAnonymousSourceNode(node.rules.map(translate));
|
||||
|
||||
case 'Atrule':
|
||||
var nodes = ['@', node.name];
|
||||
|
||||
if (node.expression && !node.expression.sequence.isEmpty()) {
|
||||
nodes.push(' ', translate(node.expression));
|
||||
}
|
||||
|
||||
if (node.block) {
|
||||
nodes.push('{', translate(node.block), '}');
|
||||
} else {
|
||||
nodes.push(';');
|
||||
}
|
||||
|
||||
return createSourceNode(node.info, nodes);
|
||||
|
||||
case 'Ruleset':
|
||||
return createAnonymousSourceNode([
|
||||
translate(node.selector), '{', translate(node.block), '}'
|
||||
]);
|
||||
|
||||
case 'Selector':
|
||||
return createAnonymousSourceNode(node.selectors.map(translate)).join(',');
|
||||
|
||||
case 'SimpleSelector':
|
||||
var nodes = node.sequence.map(function(node) {
|
||||
// add extra spaces around /deep/ combinator since comment beginning/ending may to be produced
|
||||
if (node.type === 'Combinator' && node.name === '/deep/') {
|
||||
return ' ' + translate(node) + ' ';
|
||||
}
|
||||
|
||||
return translate(node);
|
||||
});
|
||||
|
||||
return createSourceNode(node.info, nodes);
|
||||
|
||||
case 'Block':
|
||||
return createAnonymousSourceNode(node.declarations.map(translate)).join(';');
|
||||
|
||||
case 'Declaration':
|
||||
return createSourceNode(
|
||||
node.info,
|
||||
[translate(node.property), ':', translate(node.value)]
|
||||
);
|
||||
|
||||
case 'Property':
|
||||
return node.name;
|
||||
|
||||
case 'Value':
|
||||
return node.important
|
||||
? each(node.sequence) + '!important'
|
||||
: each(node.sequence);
|
||||
|
||||
case 'Attribute':
|
||||
var result = translate(node.name);
|
||||
var flagsPrefix = ' ';
|
||||
|
||||
if (node.operator !== null) {
|
||||
result += node.operator;
|
||||
|
||||
if (node.value !== null) {
|
||||
result += translate(node.value);
|
||||
|
||||
// space between string and flags is not required
|
||||
if (node.value.type === 'String') {
|
||||
flagsPrefix = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.flags !== null) {
|
||||
result += flagsPrefix + node.flags;
|
||||
}
|
||||
|
||||
return '[' + result + ']';
|
||||
|
||||
case 'FunctionalPseudo':
|
||||
return ':' + node.name + '(' + eachDelim(node.arguments, ',') + ')';
|
||||
|
||||
case 'Function':
|
||||
return node.name + '(' + eachDelim(node.arguments, ',') + ')';
|
||||
|
||||
case 'Negation':
|
||||
return ':not(' + eachDelim(node.sequence, ',') + ')';
|
||||
|
||||
case 'Braces':
|
||||
return node.open + each(node.sequence) + node.close;
|
||||
|
||||
case 'Argument':
|
||||
case 'AtruleExpression':
|
||||
return each(node.sequence);
|
||||
|
||||
case 'Url':
|
||||
return 'url(' + translate(node.value) + ')';
|
||||
|
||||
case 'Progid':
|
||||
return translate(node.value);
|
||||
|
||||
case 'Combinator':
|
||||
return node.name;
|
||||
|
||||
case 'Identifier':
|
||||
return node.name;
|
||||
|
||||
case 'PseudoClass':
|
||||
return ':' + node.name;
|
||||
|
||||
case 'PseudoElement':
|
||||
return '::' + node.name;
|
||||
|
||||
case 'Class':
|
||||
return '.' + node.name;
|
||||
|
||||
case 'Id':
|
||||
return '#' + node.name;
|
||||
|
||||
case 'Hash':
|
||||
return '#' + node.value;
|
||||
|
||||
case 'Dimension':
|
||||
return node.value + node.unit;
|
||||
|
||||
case 'Nth':
|
||||
return node.value;
|
||||
|
||||
case 'Number':
|
||||
return node.value;
|
||||
|
||||
case 'String':
|
||||
return node.value;
|
||||
|
||||
case 'Operator':
|
||||
return node.value;
|
||||
|
||||
case 'Raw':
|
||||
return node.value;
|
||||
|
||||
case 'Unknown':
|
||||
return node.value;
|
||||
|
||||
case 'Percentage':
|
||||
return node.value + '%';
|
||||
|
||||
case 'Space':
|
||||
return ' ';
|
||||
|
||||
case 'Comment':
|
||||
return '/*' + node.value + '*/';
|
||||
|
||||
default:
|
||||
throw new Error('Unknown node type: ' + node.type);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function(node) {
|
||||
return generateSourceMap(
|
||||
createAnonymousSourceNode(translate(node))
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user