Skip to content

Instantly share code, notes, and snippets.

@jzaefferer
Created February 25, 2015 17:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jzaefferer/23bef744ffea751b2668 to your computer and use it in GitHub Desktop.
Save jzaefferer/23bef744ffea751b2668 to your computer and use it in GitHub Desktop.
Copyright Jörn Zaefferer; licensed MIT
var rocambole = require('rocambole');
var _tk = require('rocambole-token');
var MAX_LINE_LENGTH = 75;
exports.transformAfter = function(ast) {
rocambole.recursive(ast, transform);
};
function transform(node) {
if (node.type !== 'ObjectExpression') return;
// Don't collapse nested objects
if (node.parent.type === 'Property') return;
// It collapses objects that are short enough
// 0 indicates measurement failed, ignore
var length = expectedLength(node);
if (length === 0 || length > MAX_LINE_LENGTH) return;
// This one seems short
_tk.eachInBetween(node.startToken, node.endToken, function(token) {
if (_tk.isBr(token)) {
// Insert one blank to replace the line break
_tk.before(token, {
type: 'WhiteSpace',
value: ' '
});
// Remove all whitespace/indent after the line break
var next = token.next;
while (_tk.isEmpty(next)) {
_tk.remove(next);
next = next.next;
}
// Remove the line break itself
_tk.remove(token);
}
});
}
function expectedLength(node) {
var length = 0;
var startOfTheLine = _tk.findPrev(node.startToken, 'LineBreak');
// No linebreak indicates first line of the file, find first token instead
if (!startOfTheLine) {
startOfTheLine = _tk.findPrev(node.startToken, function(token) {
return !token.prev;
});
}
var firstChar = _tk.findNextNonEmpty(startOfTheLine);
// Need to take into consideration the indent
_tk.eachInBetween(startOfTheLine, firstChar, function(token) {
length += String(token.raw || token.value).length;
});
var prev;
_tk.eachInBetween(firstChar, node.endToken, function(token) {
if (_tk.isEmpty(token)) {
// Empty tokens are "collapsed" (multiple linebreaks/whitespace becomes
// a single whitespace)
length += _tk.isEmpty(prev) ? 0 : 1;
prev = token;
return;
}
// Don't collapse objects with line comments; block comments should be okay
if (token.type === 'LineComment') {
length += 1000;
}
length += String(token.raw || token.value).length;
prev = token;
});
if (length === 0) {
throw new Error('Failed to measure length of object expression: ' + node.toString());
}
return length;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment