Files
liquid/node_modules/csswring/lib/csswring.js
Tetsuro 82249c99b3 Set up Grunt
Fixing up Grunt file to watch for directories

Exclude node modules folder from Jekyll built site
2015-07-25 13:48:45 -04:00

527 lines
11 KiB
JavaScript

'use strict';
var csswring;
var list = require('postcss/lib/list');
var onecolor = require('onecolor');
var postcss = require('postcss');
var re = require('./regexp');
var shortColors = require('./color_keywords').short;
// Set quotation mark
var setQuote = function (quote) {
if (!quote) {
quote = '"';
}
return quote;
};
// Check string can unquote or not
var canUnquote = function (str) {
var firstChar = str.slice(0, 1);
var secondChar;
if (re.number.test(firstChar)) {
return false;
}
secondChar = str.slice(1, 2);
if (
firstChar === '-' &&
(secondChar === '-' || re.number.test(secondChar))
) {
return false;
}
if (/^[\w-]+$/.test(str)) {
return true;
}
return false;
};
// Unquote font family name if possible
var unquoteFontFamily = function (family) {
var quote;
family = family.replace(re.quotedString, '$2');
quote = setQuote(RegExp.$1);
if (!list.space(family).every(canUnquote)) {
family = quote + family + quote;
}
return family;
};
// Convert colors to HEX or `rgba()` notation
var toRGBColor = function (m, leading, color) {
color = onecolor(color);
/* istanbul ignore if */
// Return unmodified value when `one.color` failed to parse `color`
if (!color) {
return m;
}
if (color.alpha() < 1) {
return leading + color.cssa();
}
return leading + color.hex() + ' ';
};
// Convert to shortest color
var toShortestColor = function (m, leading, r1, r2, g1, g2, b1, b2) {
var color = '#' + r1 + r2 + g1 + g2 + b1 + b2;
if (r1 === r2 && g1 === g2 && b1 === b2) {
color = '#' + r1 + g1 + b1;
}
if (shortColors.hasOwnProperty(color)) {
color = shortColors[color];
}
return leading + color.toLowerCase();
};
// Unquote inside `url()` notation if possible
var unquoteURL = function (m, leading, url) {
var quote;
url = url.replace(re.quotedString, '$2');
quote = setQuote(RegExp.$1);
if (re.urlNeedQuote.test(url)) {
url = quote + url + quote;
}
return leading + 'url(' + url + ')';
};
// Remove white spaces inside `calc()` notation
var removeCalcWhiteSpaces = function (m, leading, calc) {
calc = calc.replace(/\s([*/])\s/g, '$1');
return leading + 'calc(' + calc + ')';
};
// Wring value of declaration
var wringValue = function (value) {
value = value.replace(re.colorFunction, toRGBColor);
value = value.replace(re.colorHex, toShortestColor);
value = value.replace(re.colorTransparent, '$1transparent ');
value = value.trim();
value = value.replace(re.whiteSpaces, ' ');
value = value.replace(/([(,])\s/g, '$1');
value = value.replace(/\s([),])/g, '$1');
value = value.replace(re.numberLeadingZeros, '$1$2');
value = value.replace(re.zeroValueUnit, '$1$2');
value = value.replace(re.decimalWithZeros, '$1$2$3.$4');
value = value.replace(re.urlFunction, unquoteURL);
value = value.replace(re.calcFunction, removeCalcWhiteSpaces);
return value;
};
// Unquote attribute selector if possible
var unquoteAttributeSelector = function (m, att, con, val) {
var quote;
if (!con || !val) {
return '[' + att + ']';
}
val = val.trim();
val = val.replace(re.quotedString, '$2');
quote = setQuote(RegExp.$1);
if (!canUnquote(val)) {
val = quote + val + quote;
}
return '[' + att + con + val + ']';
};
// Remove white spaces from string
var removeWhiteSpaces = function (string) {
return string.replace(re.whiteSpaces, '');
};
// Remove white spaces from both ends of `:not()`
var trimNegationFunction = function (m, not) {
return ':not(' + not.trim() + ')';
};
// Wring selector of ruleset
var wringSelector = function (selector) {
selector = selector.replace(re.whiteSpaces, ' ');
selector = selector.replace(re.selectorAtt, unquoteAttributeSelector);
selector = selector.replace(re.selectorFunctions, removeWhiteSpaces);
selector = selector.replace(re.selectorNegationFunction, trimNegationFunction);
selector = selector.replace(re.selectorCombinators, '$1');
return selector;
};
// Check keyframe is valid or not
var isValidKeyframe = function (keyframe) {
if (keyframe === 'from' || keyframe === 'to') {
return true;
}
keyframe = parseFloat(keyframe);
if (!isNaN(keyframe) && keyframe >= 0 && keyframe <= 100) {
return true;
}
return false;
};
// Unique array element
var uniqueArray = function (array) {
var i;
var l;
var result = [];
var value;
for (i = 0, l = array.length; i < l; i++) {
value = array[i];
if (result.indexOf(value) < 0) {
result.push(value);
}
}
return result;
};
// Remove duplicate declaration
var removeDuplicateDeclaration = function (decl, index) {
var d = decl.before + decl.prop + decl.between + decl.value;
if (this.hasOwnProperty(d)) {
decl.parent.remove(this[d]);
}
this[d] = index;
};
// Check required `@font-face` descriptor or not
var isRequiredFontFaceDescriptor = function (decl) {
var prop = decl.prop;
return (prop === 'src') || (prop === 'font-family');
};
// Remove `@font-face` descriptor with default value
var removeDefaultFontFaceDescriptor = function (decl, index) {
var prop = decl.prop;
var value = decl.value;
if (
(re.descriptorFontFace.test(prop) && value === 'normal') ||
(prop === 'unicode-range' && re.unicodeRangeDefault.test(value)) ||
prop + value === 'font-weight400'
) {
decl.parent.remove(index);
}
};
// Quote `@import` URL
var quoteImportURL = function (m, quote, url) {
quote = setQuote(quote);
return quote + url + quote;
};
// Quote `@namespace` URL
var quoteNamespaceURL = function (param, index, p) {
var quote;
if (param === p[p.length - 1]) {
param = param.replace(re.quotedString, '$2');
quote = setQuote(RegExp.$1);
param = quote + param + quote;
}
return param;
};
// Wring comment
var wringComment = function (removeAllComments, comment) {
if (
(removeAllComments || comment.text.indexOf('!') !== 0) &&
comment.text.indexOf('#') !== 0
) {
comment.removeSelf();
return;
}
comment.before = '';
};
// Wring declaration
var wringDecl = function (preserveHacks, decl) {
var prop = decl.prop;
var value = decl.value;
var values;
delete decl._value;
if (preserveHacks && decl.before) {
decl.before = decl.before.replace(/[;\s]/g, '');
} else {
decl.before = '';
}
if (preserveHacks && decl.between) {
decl.between = decl.between.replace(re.whiteSpaces, '');
} else {
decl.between = ':';
}
if (decl.important) {
decl._important = '!important';
}
if (prop === 'content') {
return;
}
if (prop === 'font-family') {
decl.value = list.comma(value).map(unquoteFontFamily).join(',');
return;
}
values = list.comma(value);
value = values.map(wringValue).join(',');
if (re.propertyMultipleValues.test(prop)) {
values = list.space(value);
if (values.length === 4 && values[1] === values[3]) {
values.splice(3, 1);
}
if (values.length === 3 && values[0] === values[2]) {
values.splice(2, 1);
}
if (values.length === 2 && values[0] === values[1]) {
values.splice(1, 1);
}
value = values.join(' ');
}
if (prop === 'font-weight') {
if (value === 'normal') {
value = '400';
} else if (value === 'bold') {
value = '700';
}
}
decl.value = value;
};
// Wring declaration like string
var wringDeclLike = function (m, prop, value) {
var decl = postcss.decl({
prop: prop,
value: value
});
wringDecl.call(null, false, decl);
return '(' + decl.toString() + ')';
};
// Wring ruleset
var wringRule = function (rule) {
var decls;
var parent;
var selectors;
delete rule._selector;
rule.before = '';
rule.between = '';
rule.semicolon = false;
rule.after = '';
if (rule.nodes.length === 0 || rule.selector === '') {
rule.removeSelf();
return;
}
parent = rule.parent;
selectors = rule.selectors.map(wringSelector);
if (parent.type === 'atrule' && parent.name === 'keyframes') {
selectors = selectors.filter(isValidKeyframe);
if (selectors.length === 0) {
rule.removeSelf();
return;
}
}
rule.selector = uniqueArray(selectors).join(',');
decls = {};
rule.each(removeDuplicateDeclaration.bind(decls));
};
// Filter at-rule
var filterAtRule = function (rule) {
var name = rule.name;
var type = rule.type;
if (type === 'comment') {
return;
}
if (
type !== 'atrule' ||
(name !== 'charset' && name !== 'import')
) {
this.filter = true;
return;
}
if (name === 'charset' && !this.charset) {
this.charset = true;
return;
}
if (this.filter || (name === 'charset' && this.charset)) {
rule.removeSelf();
return;
}
};
// Wring at-rule
var wringAtRule = function (atRule) {
var params;
delete atRule._params;
atRule.before = '';
atRule.afterName = ' ';
atRule.between = '';
atRule.semicolon = false;
atRule.after = '';
if (!atRule.params) {
atRule.params = '';
}
if (atRule.name === 'charset') {
return;
}
if (atRule.name === 'font-face') {
if (atRule.nodes.filter(isRequiredFontFaceDescriptor).length < 2) {
atRule.removeSelf();
return;
}
atRule.each(removeDefaultFontFaceDescriptor);
}
if (atRule.nodes && atRule.nodes.length === 0) {
atRule.removeSelf();
return;
}
params = atRule.params;
params = params.replace(re.whiteSpaces, ' ');
params = params.replace(/([(),:])\s/g, '$1');
params = params.replace(/\s([),:])/g, '$1');
if (atRule.name === 'import') {
params = params.replace(re.urlFunction, '$1$2');
params = params.replace(re.quotedString, quoteImportURL);
}
if (atRule.name === 'namespace') {
params = params.replace(re.urlFunction, '$1$2');
params = list.space(params).map(quoteNamespaceURL).join('');
}
if (atRule.name === 'keyframes') {
params = params.replace(re.quotedString, '$2');
}
if (atRule.name === 'supports') {
params = params.replace(re.declInParentheses, wringDeclLike);
params = params.replace(re.supportsConjunctions, ') $1');
}
atRule.params = params;
if (
atRule.params === '' ||
params.indexOf('(') === 0 ||
params.indexOf('"') === 0 ||
params.indexOf('\'') === 0
) {
atRule.afterName = '';
}
};
// CSSWring object
var CSSWring = function (opts) {
var preserveHacks = false;
var removeAllComments = false;
if (opts && opts.preserveHacks) {
preserveHacks = opts.preserveHacks;
}
if (opts && opts.removeAllComments) {
removeAllComments = opts.removeAllComments;
}
this.postcss = this.postcss.bind(null, preserveHacks, removeAllComments);
};
CSSWring.prototype.postcss = function (preserveHacks, removeAllComments, css) {
css.semicolon = false;
css.after = '';
css.eachComment(wringComment.bind(null, removeAllComments));
css.eachDecl(wringDecl.bind(null, preserveHacks));
css.eachRule(wringRule);
css.each(filterAtRule.bind({}));
css.eachAtRule(wringAtRule);
return css;
};
CSSWring.prototype.wring = function (css, opts) {
return postcss().use(this.postcss).process(css, opts);
};
// CSSWring instance
csswring = function (opts) {
return new CSSWring(opts);
};
csswring.postcss = function (css) {
return csswring().postcss(css);
};
csswring.wring = function (css, opts) {
return csswring(opts).wring(css, opts);
};
module.exports = csswring;
/*eslint no-underscore-dangle:0*/