first commit
This commit is contained in:
186
build/node_modules/csso/lib/compressor/index.js
generated
vendored
Normal file
186
build/node_modules/csso/lib/compressor/index.js
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
var List = require('../utils/list');
|
||||
var clone = require('../utils/clone');
|
||||
var usageUtils = require('./usage');
|
||||
var clean = require('./clean');
|
||||
var compress = require('./compress');
|
||||
var restructureBlock = require('./restructure');
|
||||
var walkRules = require('../utils/walk').rules;
|
||||
|
||||
function readRulesChunk(rules, specialComments) {
|
||||
var buffer = new List();
|
||||
var nonSpaceTokenInBuffer = false;
|
||||
var protectedComment;
|
||||
|
||||
rules.nextUntil(rules.head, function(node, item, list) {
|
||||
if (node.type === 'Comment') {
|
||||
if (!specialComments || node.value.charAt(0) !== '!') {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nonSpaceTokenInBuffer || protectedComment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
list.remove(item);
|
||||
protectedComment = node;
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.type !== 'Space') {
|
||||
nonSpaceTokenInBuffer = true;
|
||||
}
|
||||
|
||||
buffer.insert(list.remove(item));
|
||||
});
|
||||
|
||||
return {
|
||||
comment: protectedComment,
|
||||
stylesheet: {
|
||||
type: 'StyleSheet',
|
||||
info: null,
|
||||
rules: buffer
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function compressChunk(ast, firstAtrulesAllowed, usageData, num, logger) {
|
||||
logger('Compress block #' + num, null, true);
|
||||
|
||||
var seed = 1;
|
||||
walkRules(ast, function markStylesheets() {
|
||||
if ('id' in this.stylesheet === false) {
|
||||
this.stylesheet.firstAtrulesAllowed = firstAtrulesAllowed;
|
||||
this.stylesheet.id = seed++;
|
||||
}
|
||||
});
|
||||
logger('init', ast);
|
||||
|
||||
// remove redundant
|
||||
clean(ast, usageData);
|
||||
logger('clean', ast);
|
||||
|
||||
// compress nodes
|
||||
compress(ast, usageData);
|
||||
logger('compress', ast);
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
function getCommentsOption(options) {
|
||||
var comments = 'comments' in options ? options.comments : 'exclamation';
|
||||
|
||||
if (typeof comments === 'boolean') {
|
||||
comments = comments ? 'exclamation' : false;
|
||||
} else if (comments !== 'exclamation' && comments !== 'first-exclamation') {
|
||||
comments = false;
|
||||
}
|
||||
|
||||
return comments;
|
||||
}
|
||||
|
||||
function getRestructureOption(options) {
|
||||
return 'restructure' in options ? options.restructure :
|
||||
'restructuring' in options ? options.restructuring :
|
||||
true;
|
||||
}
|
||||
|
||||
function wrapBlock(block) {
|
||||
return new List([{
|
||||
type: 'Ruleset',
|
||||
selector: {
|
||||
type: 'Selector',
|
||||
selectors: new List([{
|
||||
type: 'SimpleSelector',
|
||||
sequence: new List([{
|
||||
type: 'Identifier',
|
||||
name: 'x'
|
||||
}])
|
||||
}])
|
||||
},
|
||||
block: block
|
||||
}]);
|
||||
}
|
||||
|
||||
module.exports = function compress(ast, options) {
|
||||
ast = ast || { type: 'StyleSheet', info: null, rules: new List() };
|
||||
options = options || {};
|
||||
|
||||
var logger = typeof options.logger === 'function' ? options.logger : Function();
|
||||
var specialComments = getCommentsOption(options);
|
||||
var restructuring = getRestructureOption(options);
|
||||
var firstAtrulesAllowed = true;
|
||||
var usageData = false;
|
||||
var inputRules;
|
||||
var outputRules = new List();
|
||||
var chunk;
|
||||
var chunkNum = 1;
|
||||
var chunkRules;
|
||||
|
||||
if (options.clone) {
|
||||
ast = clone(ast);
|
||||
}
|
||||
|
||||
if (ast.type === 'StyleSheet') {
|
||||
inputRules = ast.rules;
|
||||
ast.rules = outputRules;
|
||||
} else {
|
||||
inputRules = wrapBlock(ast);
|
||||
}
|
||||
|
||||
if (options.usage) {
|
||||
usageData = usageUtils.buildIndex(options.usage);
|
||||
}
|
||||
|
||||
do {
|
||||
chunk = readRulesChunk(inputRules, Boolean(specialComments));
|
||||
|
||||
compressChunk(chunk.stylesheet, firstAtrulesAllowed, usageData, chunkNum++, logger);
|
||||
|
||||
// structure optimisations
|
||||
if (restructuring) {
|
||||
restructureBlock(chunk.stylesheet, usageData, logger);
|
||||
}
|
||||
|
||||
chunkRules = chunk.stylesheet.rules;
|
||||
|
||||
if (chunk.comment) {
|
||||
// add \n before comment if there is another content in outputRules
|
||||
if (!outputRules.isEmpty()) {
|
||||
outputRules.insert(List.createItem({
|
||||
type: 'Raw',
|
||||
value: '\n'
|
||||
}));
|
||||
}
|
||||
|
||||
outputRules.insert(List.createItem(chunk.comment));
|
||||
|
||||
// add \n after comment if chunk is not empty
|
||||
if (!chunkRules.isEmpty()) {
|
||||
outputRules.insert(List.createItem({
|
||||
type: 'Raw',
|
||||
value: '\n'
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (firstAtrulesAllowed && !chunkRules.isEmpty()) {
|
||||
var lastRule = chunkRules.last();
|
||||
|
||||
if (lastRule.type !== 'Atrule' ||
|
||||
(lastRule.name !== 'import' && lastRule.name !== 'charset')) {
|
||||
firstAtrulesAllowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (specialComments !== 'exclamation') {
|
||||
specialComments = false;
|
||||
}
|
||||
|
||||
outputRules.appendList(chunkRules);
|
||||
} while (!inputRules.isEmpty());
|
||||
|
||||
return {
|
||||
ast: ast
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user