* Fixed issue [#861](https://github.com/jakubpawlowicz/clean-css/issues/861) - new `transition` property optimizer.
* Fixed issue [#895](https://github.com/jakubpawlowicz/clean-css/issues/895) - ignoring specific styles.
* Fixed issue [#947](https://github.com/jakubpawlowicz/clean-css/issues/947) - selector based filtering.
+* Fixed issue [#964](https://github.com/jakubpawlowicz/clean-css/issues/964) - adds configurable line breaks.
* Fixed issue [#986](https://github.com/jakubpawlowicz/clean-css/issues/986) - level 2 optimizations and CSS 4 colors.
* Fixed issue [#1000](https://github.com/jakubpawlowicz/clean-css/issues/1000) - carriage return handling in tokenizer.
* Fixed issue [#1038](https://github.com/jakubpawlowicz/clean-css/issues/1038) - `font-variation-settings` quoting.
* new `transition` property optimizer;
* preserves any CSS content between `/* clean-css ignore:start */` and `/* clean-css ignore:end */` comments;
* allows filtering based on selector in `transform` callback, see [example](#how-to-apply-arbitrary-transformations-to-css-properties);
+* adds configurable line breaks via `format: { breakWith: 'lf' }` option;
## Constructor options
beforeBlockEnds: false, // controls if a line break comes before a block ends; defaults to `false`
betweenSelectors: false // controls if a line break comes between selectors; defaults to `false`
},
+ breakWith: '\n', // controls the new line character, can be `'\r\n'` or `'\n'` (aliased as `'windows'` and `'unix'` or `'crlf'` and `'lf'`); defaults to system one, so former on Windows and latter on Unix
indentBy: 0, // controls number of characters to indent with; defaults to `0`
indentWith: 'space', // controls a character to indent with, can be `'space'` or `'tab'`; defaults to `'space'`
spaces: { // controls where to insert spaces
+var systemLineBreak = require('os').EOL;
+
var override = require('../utils/override');
var Breaks = {
BetweenSelectors: 'betweenSelectors'
};
+var BreakWith = {
+ CarriageReturnLineFeed: '\r\n',
+ LineFeed: '\n',
+ System: systemLineBreak
+};
+
var IndentWith = {
Space: ' ',
Tab: '\t'
var DEFAULTS = {
breaks: breaks(false),
+ breakWith: BreakWith.System,
indentBy: 0,
indentWith: IndentWith.Space,
spaces: spaces(false),
return false;
}
+ if (typeof source == 'object' && 'breakWith' in source) {
+ source = override(source, { breakWith: mapBreakWith(source.breakWith) });
+ }
+
if (typeof source == 'object' && 'indentBy' in source) {
source = override(source, { indentBy: parseInt(source.indentBy) });
}
}
}
+function mapBreakWith(value) {
+ switch (value) {
+ case 'windows':
+ case 'crlf':
+ case BreakWith.CarriageReturnLineFeed:
+ return BreakWith.CarriageReturnLineFeed;
+ case 'unix':
+ case 'lf':
+ case BreakWith.LineFeed:
+ return BreakWith.LineFeed;
+ default:
+ return systemLineBreak;
+ }
+}
+
function mapIndentWith(value) {
switch (value) {
case 'space':
-var lineBreak = require('os').EOL;
var emptyCharacter = '';
var Breaks = require('../options/format').Breaks;
context.indentWith = context.format.indentWith.repeat(context.indentBy);
return (needsPrefixSpace && allowsSpace(context, Spaces.BeforeBlockBegins) ? Marker.SPACE : emptyCharacter) +
Marker.OPEN_CURLY_BRACKET +
- (allowsBreak(context, where) ? lineBreak : emptyCharacter) +
+ (allowsBreak(context, where) ? context.format.breakWith : emptyCharacter) +
context.indentWith;
} else {
return Marker.OPEN_CURLY_BRACKET;
if (context.format) {
context.indentBy -= context.format.indentBy;
context.indentWith = context.format.indentWith.repeat(context.indentBy);
- return (allowsBreak(context, Breaks.AfterProperty) || beforeBlockEnd && allowsBreak(context, Breaks.BeforeBlockEnds) ? lineBreak : emptyCharacter) +
+ return (allowsBreak(context, Breaks.AfterProperty) || beforeBlockEnd && allowsBreak(context, Breaks.BeforeBlockEnds) ? context.format.breakWith : emptyCharacter) +
context.indentWith +
Marker.CLOSE_CURLY_BRACKET +
- (isLast ? emptyCharacter : (allowsBreak(context, where) ? lineBreak : emptyCharacter) + context.indentWith);
+ (isLast ? emptyCharacter : (allowsBreak(context, where) ? context.format.breakWith : emptyCharacter) + context.indentWith);
} else {
return Marker.CLOSE_CURLY_BRACKET;
}
function semicolon(context, where, isLast) {
return context.format ?
- Marker.SEMICOLON + (isLast || !allowsBreak(context, where) ? emptyCharacter : lineBreak + context.indentWith) :
+ Marker.SEMICOLON + (isLast || !allowsBreak(context, where) ? emptyCharacter : context.format.breakWith + context.indentWith) :
Marker.SEMICOLON;
}
function comma(context) {
return context.format ?
- Marker.COMMA + (allowsBreak(context, Breaks.BetweenSelectors) ? lineBreak : emptyCharacter) + context.indentWith :
+ Marker.COMMA + (allowsBreak(context, Breaks.BetweenSelectors) ? context.format.breakWith : emptyCharacter) + context.indentWith :
Marker.COMMA;
}
break;
case Token.COMMENT:
store(context, token);
- store(context, allowsBreak(context, Breaks.AfterComment) ? lineBreak : emptyCharacter);
+ store(context, allowsBreak(context, Breaks.AfterComment) ? context.format.breakWith : emptyCharacter);
break;
case Token.RAW:
store(context, token);
var all = require('./helpers').all;
-var lineBreak = require('os').EOL;
-
function store(serializeContext, token) {
var value = typeof token == 'string' ?
token :
function wrap(serializeContext, value) {
if (serializeContext.column + value.length > serializeContext.format.wrapAt) {
- track(serializeContext, lineBreak);
- serializeContext.output.push(lineBreak);
+ track(serializeContext, serializeContext.format.breakWith);
+ serializeContext.output.push(serializeContext.format.breakWith);
}
}
var SourceMapGenerator = require('source-map').SourceMapGenerator;
var all = require('./helpers').all;
-var lineBreak = require('os').EOL;
var isRemoteResource = require('../utils/is-remote-resource');
var isWindows = process.platform == 'win32';
function wrap(serializeContext, value) {
if (serializeContext.column + value.length > serializeContext.format.wrapAt) {
- track(serializeContext, lineBreak, false);
- serializeContext.output.push(lineBreak);
+ track(serializeContext, serializeContext.format.breakWith, false);
+ serializeContext.output.push(serializeContext.format.breakWith);
}
}
]
}, { format: 'keep-breaks', level: { 1: { specialComments: 0 } } })
)
+ .addBatch(
+ optimizerContext('CRLF line breaks', {
+ 'uses specified one': [
+ '.block{color:red;display:block}',
+ '.block{color:red;\r\ndisplay:block\r\n}'
+ ]
+ }, { format: { breaks: { afterProperty: true }, breakWith: 'crlf' } })
+ )
+ .addBatch(
+ optimizerContext('LF line breaks', {
+ 'uses specified one': [
+ '.block{color:red;display:block}',
+ '.block{color:red;\ndisplay:block\n}'
+ ]
+ }, { format: { breaks: { afterProperty: true }, breakWith: 'lf' } })
+ )
.addBatch(
optimizerContext('selectors', {
'not expand + in selectors mixed with calc methods': [
var assert = require('assert');
+var systemLineBreak = require('os').EOL;
var vows = require('vows');
beforeBlockEnds: false,
betweenSelectors: false
},
+ breakWith: systemLineBreak,
indentBy: 0,
indentWith: ' ',
spaces: {
},
'hash': {
'topic': function () {
- return formatFrom({ breaks: { afterProperty: true }, indentBy: 1 });
+ return formatFrom({ breaks: { afterProperty: true }, breakWith: '\r\n', indentBy: 1 });
},
'is merged with default': function (formatOptions) {
assert.deepEqual(formatOptions, {
beforeBlockEnds: false,
betweenSelectors: false
},
+ breakWith: '\r\n',
indentBy: 1,
indentWith: ' ',
spaces: {
beforeBlockEnds: false,
betweenSelectors: false
},
+ breakWith: systemLineBreak,
indentBy: 2,
indentWith: ' ',
spaces: {
beforeBlockEnds: false,
betweenSelectors: false
},
+ breakWith: systemLineBreak,
indentBy: 0,
indentWith: '\t',
spaces: {
beforeBlockEnds: false,
betweenSelectors: false
},
+ breakWith: systemLineBreak,
indentBy: 0,
indentWith: '\t',
spaces: {
beforeBlockEnds: false,
betweenSelectors: false
},
+ breakWith: systemLineBreak,
indentBy: 3,
indentWith: ' ',
spaces: {
beforeBlockEnds: false,
betweenSelectors: false
},
+ breakWith: systemLineBreak,
indentBy: 0,
indentWith: '\t',
spaces: {
beforeBlockEnds: true,
betweenSelectors: true
},
+ breakWith: systemLineBreak,
indentBy: 2,
indentWith: ' ',
spaces: {
beforeBlockEnds: true,
betweenSelectors: false
},
+ breakWith: systemLineBreak,
indentBy: 0,
indentWith: ' ',
spaces: {