Skip to content

Commit

Permalink
Add eol option to all components
Browse files Browse the repository at this point in the history
Some of this is hacky ways to normalizing the inputs.  Unfortunate, but effective.

Closes #715
  • Loading branch information
bitwiseman committed Jun 18, 2015
1 parent c77d0d8 commit 1b4be9b
Show file tree
Hide file tree
Showing 17 changed files with 182 additions and 72 deletions.
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,22 +164,27 @@ The CSS & HTML beautifiers are much simpler in scope, and possess far fewer opti
CSS Beautifier Options:
-s, --indent-size Indentation size [4]
-c, --indent-char Indentation character [" "]
-t, --indent-with-tabs Indent with tabs, overrides -s and -c
-e, --eol Character(s) to use as line terminators. (default newline - "\\n")
-n, --end-with-newline End output with newline
-L, --selector-separator-newline Add a newline between multiple selectors
-N, --newline-between-rules Add a newline between CSS rules
HTML Beautifier Options:
-I, --indent-inner-html Indent <head> and <body> sections. Default is false.
-s, --indent-size Indentation size [4]
-c, --indent-char Indentation character [" "]
-t, --indent-with-tabs Indent with tabs, overrides -s and -c
-e, --eol Character(s) to use as line terminators. (default newline - "\\n")
-n, --end-with-newline End output with newline
-p, --preserve-newlines Preserve existing line-breaks (--no-preserve-newlines disables)
-m, --max-preserve-newlines Maximum number of line-breaks to be preserved in one chunk [10]
-I, --indent-inner-html Indent <head> and <body> sections. Default is false.
-b, --brace-style [collapse|expand|end-expand|none] ["collapse"]
-S, --indent-scripts [keep|separate|normal] ["normal"]
-w, --wrap-line-length Maximum characters per line (0 disables) [250]
-A, --wrap-attributes Wrap attributes to new lines [auto|force] ["auto"]
-i, --wrap-attributes-indent-size Indent wrapped attributes to after N characters [indent-size]
-p, --preserve-newlines Preserve existing line-breaks (--no-preserve-newlines disables)
-m, --max-preserve-newlines Maximum number of line-breaks to be preserved in one chunk [10]
-U, --unformatted List of tags (defaults to inline) that should not be reformatted
-n, --end-with-newline End output with newline
-E, --extra_liners List of tags (defaults to [head,body,/html] that should have an extra newline before them.
```

Expand Down
14 changes: 13 additions & 1 deletion js/lib/beautify-css.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,16 @@
(function() {
function css_beautify(source_text, options) {
options = options || {};
source_text = source_text || '';
// HACK: newline parsing inconsistent. This brute force normalizes the input.
source_text = source_text.replace(/\r\n|[\r\u2028\u2029]/g, '\n')

var indentSize = options.indent_size || 4;
var indentCharacter = options.indent_char || ' ';
var selectorSeparatorNewline = (options.selector_separator_newline === undefined) ? true : options.selector_separator_newline;
var end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
var newline_between_rules = (options.newline_between_rules === undefined) ? true : options.newline_between_rules;
var eol = options.eol ? options.eol : '\n';

// compatibility
if (typeof indentSize === "string") {
Expand All @@ -79,6 +84,9 @@
indentSize = 1;
}

eol = eol.replace(/\\r/, '\r').replace(/\\n/, '\n')


// tokenizer
var whiteRe = /^\s+$/;
var wordRe = /[\w$\-_]/;
Expand Down Expand Up @@ -434,7 +442,11 @@

// establish end_with_newline
if (end_with_newline) {
sweetCode += "\n";
sweetCode += '\n';
}

if (eol != '\n') {
sweetCode = sweetCode.replace(/[\n]/g, eol);
}

return sweetCode;
Expand Down
22 changes: 20 additions & 2 deletions js/lib/beautify-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@
wrap_attributes,
wrap_attributes_indent_size,
end_with_newline,
extra_liners;
extra_liners,
eol;

options = options || {};

Expand Down Expand Up @@ -130,12 +131,15 @@
extra_liners = Array.isArray(options.extra_liners) ?
options.extra_liners.concat() : (typeof options.extra_liners === 'string') ?
options.extra_liners.split(',') : 'head,body,/html'.split(',');
eol = options.eol ? options.eol : '\n';

if(options.indent_with_tabs){
indent_character = '\t';
indent_size = 1;
}

eol = eol.replace(/\\r/, '\r').replace(/\\n/, '\n')

function Parser() {

this.pos = 0; //Parser position
Expand Down Expand Up @@ -684,6 +688,10 @@
this.printer = function(js_source, indent_character, indent_size, wrap_line_length, brace_style) { //handles input/output and some other printing functions

this.input = js_source || ''; //gets the input for the Parser

// HACK: newline parsing inconsistent. This brute force normalizes the input.
this.input = this.input.replace(/\r\n|[\r\u2028\u2029]/g, '\n')

this.output = [];
this.indent_character = indent_character;
this.indent_string = '';
Expand Down Expand Up @@ -859,8 +867,11 @@

var indentation = multi_parser.get_full_indent(script_indent_level);
if (_beautifier) {

// call the Beautifier if avaliable
text = _beautifier(text.replace(/^\s*/, indentation), options);
var child_options = JSON.parse(JSON.stringify(options));

This comment has been minimized.

Copy link
@Infocatcher

Infocatcher Jun 18, 2015

Contributor

Not sure how much this matters, but this doesn't work in old browsers and in WSH+JScript:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON#Browser_compatibility

May be converted into something like

var Child_options = function() {
    this.eol = '\\n';
};
Child_options.prototype = options;
var child_options = new Child_options();

Anyway, I already have some automated patches for things like string[N] vs string.charAt(N):
https://github.com/Infocatcher/AkelPad_scripts/blob/d2dc1306146f108294b7ceb821990fdc51db6b84/jsBeautifier.js#L7756-L7814

So, this doesn't matters for me, if may be easily fixed. And the main question is about officially supported JavaScript versions.
An yes, it's good for me to keep the code more old-school, of course. :)

This comment has been minimized.

Copy link
@bitwiseman

bitwiseman Jun 19, 2015

Author Member

Really hadn't thought about it too deeply. Please file an issue (commit comments are not especially great for tracking issues/idea progress). I'm not opposed to maintaining older browser support.

This comment has been minimized.

Copy link
@Infocatcher

Infocatcher Jun 19, 2015

Contributor

I decided to create pull request, since I already have required patches: #720

child_options.eol = '\n';
text = _beautifier(text.replace(/^\s*/, indentation), child_options);
} else {
// simply indent the string otherwise
var white = text.match(/^\s*/)[0];
Expand Down Expand Up @@ -889,9 +900,16 @@
multi_parser.last_text = multi_parser.token_text;
}
var sweet_code = multi_parser.output.join('').replace(/[\r\n\t ]+$/, '');

// establish end_with_newline
if (end_with_newline) {
sweet_code += '\n';
}

if (eol != '\n') {
sweet_code = sweet_code.replace(/[\n]/g, eol);
}

return sweet_code;
}

Expand Down
18 changes: 12 additions & 6 deletions js/lib/beautify.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.

var lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
var lineBreak = exports.lineBreak = /\r\n|[\n\r\u2028\u2029]/g;

// Test whether a given character code starts an identifier.

Expand Down Expand Up @@ -363,7 +363,7 @@
}

if (opt.eol != '\n') {
sweet_code = sweet_code.replace(/[\r]?[\n]/mg, opt.eol);
sweet_code = sweet_code.replace(/[\n]/g, opt.eol);
}

return sweet_code;
Expand Down Expand Up @@ -1760,6 +1760,7 @@
comment += comment_match[0];
parser_pos += comment_match[0].length;
}
comment = comment.replace(acorn.lineBreak, '\n');
return [comment, 'TK_BLOCK_COMMENT', directives];
}
// peek for comment // ...
Expand Down Expand Up @@ -1843,6 +1844,7 @@
var xmlLength = match ? match.index + match[0].length : xmlStr.length;
xmlStr = xmlStr.slice(0, xmlLength);
parser_pos += xmlLength - 1;
xmlStr = xmlStr.replace(acorn.lineBreak, '\n');
return [xmlStr, "TK_STRING"];
}
} else {
Expand All @@ -1854,11 +1856,14 @@
while (parser_pos < input_length &&
(esc || (input.charAt(parser_pos) !== sep &&
(sep === '`' || !acorn.newline.test(input.charAt(parser_pos)))))) {
resulting_string += input.charAt(parser_pos);
// Handle \r\n linebreaks after escapes or in template strings
if (input.charAt(parser_pos) === '\r' && input.charAt(parser_pos + 1) === '\n') {
parser_pos += 1;
if ((esc || sep === '`') && acorn.newline.test(input.charAt(parser_pos))) {
if (input.charAt(parser_pos) === '\r' && input.charAt(parser_pos + 1) === '\n') {
parser_pos += 1;
}
resulting_string += '\n';
} else {
resulting_string += input.charAt(parser_pos);
}
if (esc) {
if (input.charAt(parser_pos) === 'x' || input.charAt(parser_pos) === 'u') {
Expand Down Expand Up @@ -1937,14 +1942,15 @@
if(template_match) {
c = template_match[0];
parser_pos += c.length - 1;
c = c.replace(acorn.lineBreak, '\n');
return [c, 'TK_STRING'];
}
}

if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {
parser_pos += 3;
c = '<!--';
while (input.charAt(parser_pos) !== '\n' && parser_pos < input_length) {
while (!acorn.newline.test(input.charAt(parser_pos)) && parser_pos < input_length) {
c += input.charAt(parser_pos);
parser_pos++;
}
Expand Down
10 changes: 5 additions & 5 deletions js/lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,15 @@ function usage(err) {
'',
'Beautifier Options:',
' -s, --indent-size Indentation size [4]',
' -c, --indent-char Indentation character [" "]'
' -c, --indent-char Indentation character [" "]',
' -t, --indent-with-tabs Indent with tabs, overrides -s and -c',
' -e, --eol Character(s) to use as line terminators. (default newline - "\\n")',
' -n, --end-with-newline End output with newline'
];

switch (scriptName.split('-').shift()) {
case "js":
msg.push(' -l, --indent-level Initial indentation level [0]');
msg.push(' -t, --indent-with-tabs Indent with tabs, overrides -s and -c');
msg.push(' -e, --eol character(s) to use as line terminators. (default newline - "\\n")');
msg.push(' -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables)');
msg.push(' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]');
msg.push(' -P, --space-in-paren Add padding spaces within paren, ie. f( a, b )');
Expand All @@ -241,7 +242,6 @@ function usage(err) {
msg.push(' -w, --wrap-line-length Wrap lines at next opportunity after N characters [0]');
msg.push(' -X, --e4x Pass E4X xml literals through untouched');
msg.push(' --good-stuff Warm the cockles of Crockford\'s heart');
msg.push(' -n, --end-with-newline End output with newline');
msg.push(' -C, --comma-first Put commas at the beginning of new line instead of end');
break;
case "html":
Expand All @@ -254,7 +254,7 @@ function usage(err) {
msg.push(' -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables)');
msg.push(' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]');
msg.push(' -U, --unformatted List of tags (defaults to inline) that should not be reformatted');
msg.push(' -E, --extra_liners List of tags (defaults to [head,body,/html] that should have an extra newline');
msg.push(' -E, --extra_liners List of tags (defaults to [head,body,/html] that should have an extra newline');
break;
case "css":
msg.push(' -L, --selector-separator-newline Add a newline between multiple selectors.')
Expand Down
8 changes: 8 additions & 0 deletions js/test/beautify-css-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
if (expected !== input) {
sanitytest.expect(expected, expected);
}

// Everywhere we do newlines, they should be replaced with opts.eol
opts.eol = '\r\\n';
expected = expected.replace(/[\n]/g, '\r\n');
sanitytest.expect(input, expected);
input = input.replace(/[\n]/g, '\r\n');
sanitytest.expect(input, expected);
opts.eol = '\n';
}

// test css
Expand Down
11 changes: 8 additions & 3 deletions js/test/beautify-html-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
if (expected !== input) {
sanitytest.expect(expected, expected);
}

// Everywhere we do newlines, they should be replaced with opts.eol
opts.eol = '\r\n';
expected = expected.replace(/[\n]/g, '\r\n');
sanitytest.expect(input, expected);
input = input.replace(/[\n]/g, '\r\n');
sanitytest.expect(input, expected);
opts.eol = '\n';
}

// test html
Expand All @@ -48,9 +56,6 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
if (opts.indent_size === 4 && input) {
wrapped_input = '<div>\n' + input.replace(/^(.+)$/mg, ' $1') + '\n <span>inline</span>\n</div>';
wrapped_expectation = '<div>\n' + expectation.replace(/^(.+)$/mg, ' $1') + '\n <span>inline</span>\n</div>';
if (opts.end_with_newline) {
wrapped_expectation += '\n';
}
test_fragment(wrapped_input, wrapped_expectation);
}
}
Expand Down
18 changes: 8 additions & 10 deletions js/test/beautify-javascript-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ function run_javascript_tests(test_obj, Urlencoded, js_beautify, html_beautify,
if (expected !== input) {
sanitytest.expect(expected, expected);
}

// Everywhere we do newlines, they should be replaced with opts.eol
opts.eol = '\r\\n';
expected = expected.replace(/[\n]/g, '\r\n');
sanitytest.expect(input, expected);
input = input.replace(/[\n]/g, '\r\n');
sanitytest.expect(input, expected);
opts.eol = '\n';
}


Expand Down Expand Up @@ -79,13 +87,6 @@ function run_javascript_tests(test_obj, Urlencoded, js_beautify, html_beautify,
test_fragment(wrapped_input, wrapped_input);
}
opts.test_output_raw = false;

// Everywhere we do newlines, they should be replaced with opts.eol
opts.eol = '\r\\n';
wrapped_input = wrapped_input.replace(/[\n]/mg, '\r\n');
wrapped_expectation = wrapped_expectation.replace(/[\n]/mg, '\r\n');
test_fragment(wrapped_input, wrapped_expectation);
opts.eol = '\n';
}

}
Expand Down Expand Up @@ -1624,9 +1625,6 @@ function run_javascript_tests(test_obj, Urlencoded, js_beautify, html_beautify,

bt('a = //comment\n /regex/;');

test_fragment('/*\n * X\n */');
test_fragment('/*\r\n * X\r\n */', '/*\n * X\n */');

bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}', 'if (a) {\n b;\n} else {\n c;\n}');

// tests for brace positioning
Expand Down
20 changes: 19 additions & 1 deletion python/cssbeautifier/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def __init__(self):
self.selector_separator_newline = True
self.end_with_newline = False
self.newline_between_rules = True
self.eol = '\n'


def __repr__(self):
return \
Expand Down Expand Up @@ -160,6 +162,17 @@ def result(self):
class Beautifier:

def __init__(self, source_text, opts=default_options()):
# This is not pretty, but given how we did the version import
# it is the only way to do this without having setup.py fail on a missing six dependency.
self.six = __import__("six")

if not source_text:
source_text = ''

# HACK: newline parsing inconsistent. This brute force normalizes the input newlines.
lineBreak = re.compile(self.six.u("\r\n|[\r\u2028\u2029]"))
source_text = re.sub(lineBreak, '\n', source_text)

self.source_text = source_text
self.opts = opts
self.indentSize = opts.indent_size
Expand All @@ -171,6 +184,8 @@ def __init__(self, source_text, opts=default_options()):
self.indentChar = "\t"
self.indentSize = 1

self.opts.eol = self.opts.eol.replace('\\r', '\r').replace('\\n', '\n')

# https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule
# also in CONDITIONAL_GROUP_RULE below
self.NESTED_AT_RULE = [ \
Expand Down Expand Up @@ -444,6 +459,9 @@ def beautify(self):

# establish end_with_newline
if self.opts.end_with_newline:
sweet_code += "\n"
sweet_code += '\n'

if not self.opts.eol == '\n':
sweet_code = sweet_code.replace('\n', self.opts.eol)

return sweet_code
15 changes: 14 additions & 1 deletion python/cssbeautifier/tests/test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import unittest
import cssbeautifier

Expand Down Expand Up @@ -321,9 +324,19 @@ def decodesto(self, input, expectation=None):

# if the expected is different from input, run it again
# expected output should be unchanged when run twice.
if not expectation == None:
if not expectation != input:
self.assertMultiLineEqual(
cssbeautifier.beautify(expectation, self.options), expectation)

# Everywhere we do newlines, they should be replaced with opts.eol
self.options.eol = '\r\\n';
expectation = expectation.replace('\n', '\r\n')
self.assertMultiLineEqual(
cssbeautifier.beautify(input, self.options), expectation)
input = input.replace('\n', '\r\n')
self.assertMultiLineEqual(
cssbeautifier.beautify(input, self.options), expectation)
self.options.eol = '\n'

if __name__ == '__main__':
unittest.main()
Loading

1 comment on commit 1b4be9b

@Infocatcher
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simple /\n/g instead of /[\n]/g?

Please sign in to comment.