Skip Menu |

This queue is for tickets about the JavaScript-Beautifier CPAN distribution.

Report information
The Basics
Id: 69496
Status: new
Priority: 0/
Queue: JavaScript-Beautifier

People
Owner: Nobody in particular
Requestors: TONVOON [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: (no value)



Subject: Removal of trailing commas
Good old Internet Explorer complains violently if there are trailing commas in hash lists or array lists in javascript. This patch includes a new flag, -r | --remove_extra_commas, which will remove these pesky commas. Included are tests and documentation. Warning: as this deletes bits of your input code, there is the possibility that it will break your javascript. I've tested all the situations I'm aware of, but there maybe others. I'd be interested in other people's experiences and would be happy to investigate failing cases.
Subject: 01remove_extra_commas.patch
diff -ur JavaScript-Beautifier-0.17.original/bin/js_beautify.pl JavaScript-Beautifier-0.17/bin/js_beautify.pl --- JavaScript-Beautifier-0.17.original/bin/js_beautify.pl 2009-12-30 02:47:20.000000000 +0000 +++ JavaScript-Beautifier-0.17/bin/js_beautify.pl 2011-07-05 07:46:56.787500900 +0000 @@ -20,6 +20,7 @@ "s|indent_size=i", "c|indent_character=s", "p|preserve_newlines", + "r|remove_extra_commas", ) or pod2usage(2); pod2usage(1) if $params{help}; @@ -39,7 +40,8 @@ my $pretty_js = js_beautify( $js_source_code, { indent_size => $params{s} || 4, indent_character => $params{c} || ' ', - preserve_newlines => $params{p} || 1 + preserve_newlines => $params{p} || 1, + remove_extra_commas => $params{r} || 0, } ); if ( $params{output} or $params{o} ) { @@ -89,6 +91,20 @@ 1 by default +=item B<-r>, B<--remove_extra_commas> + +0 by default + +=back + +=head1 COPYRIGHT & LICENSE + +Copyright 2009 Fayland Lam, all rights reserved. + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=cut =back =head1 COPYRIGHT & LICENSE @@ -98,4 +114,4 @@ This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. -=cut \ No newline at end of file +=cut Only in JavaScript-Beautifier-0.17: blib diff -ur JavaScript-Beautifier-0.17.original/lib/JavaScript/Beautifier.pm JavaScript-Beautifier-0.17/lib/JavaScript/Beautifier.pm --- JavaScript-Beautifier-0.17.original/lib/JavaScript/Beautifier.pm 2009-12-30 02:47:20.000000000 +0000 +++ JavaScript-Beautifier-0.17/lib/JavaScript/Beautifier.pm 2011-07-05 07:43:56.390559837 +0000 @@ -11,7 +11,7 @@ @EXPORT_OK = qw/js_beautify/; my ( @input, @output, @modes ); -my ( $token_text, $last_type, $last_text, $last_last_text, $last_word, $current_mode, $indent_string, $parser_pos, $in_case, $prefix, $token_type, $do_block_just_closed, $var_line, $var_line_tainted, $if_line_flag, $wanted_newline, $just_added_newline ); +my ( $token_text, $last_type, $last_text, $last_last_text, $last_word, $current_mode, $indent_string, $parser_pos, $in_case, $prefix, $token_type, $do_block_just_closed, $var_line, $var_line_tainted, $if_line_flag, $wanted_newline, $just_added_newline, $last_comma_pos, $last_comma_pos_from_comment ); my @whitespace = split('', "\n\r\t "); my @wordchar = split('', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'); @@ -21,7 +21,7 @@ # words which should always start on new line. my @line_starter = split(',', 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'); -my ( $opt_indent_level, $opt_indent_size, $opt_indent_character, $opt_preserve_newlines, $opt_space_after_anon_function ); +my ( $opt_indent_level, $opt_indent_size, $opt_indent_character, $opt_preserve_newlines, $opt_space_after_anon_function, $opt_remove_extra_commas ); sub js_beautify { my ( $js_source_code, $opts ) = @_; @@ -31,6 +31,7 @@ $opt_preserve_newlines = exists $opts->{preserve_newlines} ? $opts->{preserve_newlines} : 1; $opt_indent_level = $opts->{indent_level} ||= 0; $opt_space_after_anon_function = exists $opts->{space_after_anon_function} ? $opts->{space_after_anon_function} : 0; + $opt_remove_extra_commas = exists $opts->{remove_extra_commas} ? $opts->{remove_extra_commas} : 0; # ------------------------------------- $just_added_newline = 0; @@ -113,8 +114,12 @@ print_token(); $last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next; } elsif ( $token_type eq 'TK_END_EXPR' ) { - if ( $token_text eq ']' && $current_mode eq '[INDENTED-EXPRESSION]' ) { - unindent(); + if ( $token_text eq ']' ) { + if ( $current_mode eq '[INDENTED-EXPRESSION]' ) { + unindent(); + } elsif ( $current_mode eq '[EXPRESSION]' ) { + remove_last_comma(); + } } restore_mode(); print_token(); @@ -149,6 +154,7 @@ } unindent(); } else { + remove_last_comma(); unindent(); print_newline(); } @@ -156,6 +162,7 @@ restore_mode(); $last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next; } elsif ( $token_type eq 'TK_WORD' ) { + $last_comma_pos_from_comment = undef; # no, it's not you. even I have problems understanding how this works # and what does what. if ( $do_block_just_closed ) { @@ -247,6 +254,7 @@ $var_line = 0; $last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next; } elsif ( $token_type eq 'TK_STRING' ) { + $last_comma_pos_from_comment = undef; if ( $last_type eq 'TK_START_BLOCK' || $last_type eq 'TK_END_BLOCK' || $last_type eq 'TK_SEMICOLON' ) { print_newline(); } elsif ( $last_type eq 'TK_WORD' ) { @@ -255,6 +263,7 @@ print_token(); $last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next; } elsif ( $token_type eq 'TK_OPERATOR' ) { + $last_comma_pos_from_comment = undef; my $start_delim = 1; my $end_delim = 1; if ( $var_line && $token_text ne ',' ) { @@ -280,6 +289,8 @@ } if ( $token_text eq ',' ) { + # Deliberately do not -1 as print_token is next + $last_comma_pos = scalar @output; if ($var_line) { if ( $var_line_tainted ) { print_token(); @@ -302,6 +313,7 @@ print_space(); } } + #$last_comma_pos = scalar @output -1; $last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next; } elsif ( $token_text eq '--' || $token_text eq '++' ) { # unary operators special case if ( $last_text eq ';' ) { @@ -357,12 +369,18 @@ $last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next; } elsif ($token_type eq 'TK_BLOCK_COMMENT') { print_newline(); + if($last_text eq ',') { + $last_comma_pos_from_comment = $last_comma_pos; + } print_token(); print_newline(); $last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next; } elsif ($token_type eq 'TK_COMMENT') { # print_newline(); print_space(); + if($last_text eq ',') { + $last_comma_pos_from_comment = $last_comma_pos; + } print_token(); print_newline(); $last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next; @@ -428,6 +446,23 @@ pop @output; } } +sub remove_last_comma { + return unless $opt_remove_extra_commas; + my $last = ( defined $last_comma_pos_from_comment ? $last_comma_pos_from_comment : scalar @output - 1 ); + my $i = $last; + while ($i) { + if ($output[$i] =~ /,$/) { + # delete from here to last + #splice @output, $i, $last - $i + 1, ( $last_comma_pos_from_comment ? " " : () ); + splice @output, $i, $last - $i + 1; + last; + } elsif ($output[$i] !~ /\s$/) { + last; + } + $i--; + } + $last_comma_pos_from_comment = undef; +} sub set_mode { my $mode = shift; push @modes, $current_mode; @@ -753,6 +788,12 @@ =back +=item remove_extra_commas + +Will remove the last comma in a hash or an array list. Also known as "the Internet Explorer bug". Default is 0 + +=back + =head1 AUTHOR Fayland Lam, C<< <fayland at gmail.com> >> Only in JavaScript-Beautifier-0.17: Makefile Only in JavaScript-Beautifier-0.17: pm_to_blib diff -ur JavaScript-Beautifier-0.17.original/t/01-javascript-beauty.t JavaScript-Beautifier-0.17/t/01-javascript-beauty.t --- JavaScript-Beautifier-0.17.original/t/01-javascript-beauty.t 2009-12-30 02:47:20.000000000 +0000 +++ JavaScript-Beautifier-0.17/t/01-javascript-beauty.t 2011-07-05 07:38:34.923229920 +0000 @@ -1,4 +1,4 @@ -#!perl -T +#!perl use strict; use warnings; @@ -20,10 +20,12 @@ my ($input, $expected) = @_; $expected ||= $input; + my $desc = $input; + $desc =~ s/\n/\\n/g; my $result = js_beautify( $input, $opts ); $tests_num++; - is($result, $expected, $input); + is($result, $expected, $desc); } sub bt { @@ -154,6 +156,24 @@ bt('/abc/i.test()'); bt( "{/abc/i.test()}", "{\n /abc/i.test()\n}" ); +$opts->{remove_extra_commas} = 1; + +bt( "{ 'stuff':'here', }", "{\n 'stuff': 'here'\n}" ); +bt( "[{'bob':'fred'},{'hilda':'wilma'},]", "[{\n 'bob': 'fred'\n},\n{\n 'hilda': 'wilma'\n}]" ); +bt( "{ 'stuff':'here', //Some comments\n }", "{\n 'stuff': 'here'\n //Some comments\n}" ); +bt( "{ 'stuff':'here', /* Some comment block */\n }", "{\n 'stuff': 'here'\n /* Some comment block */\n}" ); +bt( "{ 'no comma':'removal', /* Some comment block */\n'stuff':'here', /* Another comment block */ }", "{\n 'no comma': 'removal',\n /* Some comment block */\n 'stuff': 'here'\n /* Another comment block */\n}" ); +bt( "{ 'stuff':'here', /* Some comment block */ /* Second comment block */\n }", "{\n 'stuff': 'here'\n /* Some comment block */\n /* Second comment block */\n}" ); + +$opts->{remove_extra_commas} = 0; + +bt( "{ 'stuff':'here', }", "{\n 'stuff': 'here',\n}" ); +bt( "[{'bob':'fred'},{'hilda':'wilma'},]", "[{\n 'bob': 'fred'\n},\n{\n 'hilda': 'wilma'\n},\n]" ); +bt( "{ 'stuff':'here', //Some comments\n }", "{\n 'stuff': 'here',\n //Some comments\n}" ); +bt( "{ 'stuff':'here', /* Some comment block */\n }", "{\n 'stuff': 'here',\n /* Some comment block */\n}" ); +bt( "{ 'no comma':'removal', /* Some comment block */\n'stuff':'here', /* Another comment block */ }", "{\n 'no comma': 'removal',\n /* Some comment block */\n 'stuff': 'here',\n /* Another comment block */\n}" ); +bt( "{ 'stuff':'here', /* Some comment block */ /* Second comment block */\n }", "{\n 'stuff': 'here',\n /* Some comment block */\n /* Second comment block */\n}" ); + bt( "{x=#1=[]}", "{\n x = #1=[]\n}"); bt( "{a:#1={}}", "{\n a: #1={}\n}"); bt( "{a:#1#}", "{\n a: #1#\n}" );