Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37864286
en ru br
Репозитории ALT

Группа :: Разработка/Perl
Пакет: perl-JavaScript-Beautifier

 Главная   Изменения   Спек   Патчи   Исходники   Загрузить   Gear   Bugs and FR  Repocop 

pax_global_header00006660000000000000000000000064113165372300014513gustar00rootroot0000000000000052 comment=d17fe1f4abc42c6677cf0b99b1e1f2aee4fcdc45
perl-JavaScript-Beautifier-0.17/000075500000000000000000000000001131653723000165235ustar00rootroot00000000000000perl-JavaScript-Beautifier-0.17/Build.PL000064400000000000000000000014221131653723000200160ustar00rootroot00000000000000use strict;
use warnings;
use Module::Build;

my $builder = Module::Build->new(
module_name => 'JavaScript::Beautifier',
license => 'perl',
dist_author => 'Fayland Lam <fayland@gmail.com>',
dist_version_from => 'lib/JavaScript/Beautifier.pm',
build_requires => {
'Test::More' => '0.88',
'Getopt::Long' => 0,
'Pod::Usage' => 0,
'IO::File' => 0,
},
add_to_cleanup => [ 'JavaScript-Beautifier-*' ],
create_makefile_pl => 'traditional',
script_files => [
'bin/js_beautify.pl',
],
meta_merge => {
resources => {
repository => 'http://github.com/fayland/perl-javascript-beautifier/tree/master',
}
},
);

$builder->create_build_script();
perl-JavaScript-Beautifier-0.17/Changes000064400000000000000000000032351131653723000200210ustar00rootroot00000000000000Revision history for JavaScript-Beautifier

0.17 2009.12.30
Allex Wang's fix for else { if handling
js_beautify.pl [options] - (from STDIN) (RT 53220)

0.16 2009.09.22
Fixed array indentation regressions.

0.15 2009.09.17
Array tweaks

0.14 2009.08.14
Added an option for the old "function ()" syntax.
Better handling of multi-dimensional arrays

0.13 2009.08.01
Pre-increment and pre-decrement fix
puts spaces in front of colons in ternary expressions, e.g. a ? b : c
does not put spaces in front of colons in class literals with
numeric keys, e.g. { 1: "a", 2: "b" }
does not put spaces between urnary +/-/! and the operand, e.g.
[-a], case -1, return !a
puts a new line between a new block and the start of an
expression, e.g. function a() { (x || y).z() }

0.12 2009.07.26
fixed broken <!-- / --> handline
Allow unescaped / in regexp character classes.
Added space between anon function parens.

0.11 2009.06.09
Fix .git MANIFEST

0.10 2009.06.08
Fix for "function" statement

0.09 2009.06.01
Strip trailing newlines, minor support for <!--

0.08 2009.05.13
bin/js_beatify.pl

0.07 2009.05.13
Spidermonkey sharp variable support

0.06 2009.05.05
Fix for { /regexp/ } mess up.

0.05 2009.05.05
do { ... } while (...) spacing fixes

0.04 2009.03.23
Preserve existing line breaks?

0.03 2008.12.18
tiny POD updates

0.02 2008.12.18
more test cases

0.01 Date/time
First version, released on an unsuspecting world.

perl-JavaScript-Beautifier-0.17/MANIFEST000064400000000000000000000002501131653723000176510ustar00rootroot00000000000000bin/js_beautify.pl
Build.PL
Changes
lib/JavaScript/Beautifier.pm
Makefile.PL
MANIFEST This list of files
META.yml
README
t/00-load.t
t/01-javascript-beauty.t
t/pod.t
perl-JavaScript-Beautifier-0.17/MANIFEST.SKIP000064400000000000000000000013261131653723000204230ustar00rootroot00000000000000# Avoid version control files.
\bRCS\b
\bCVS\b
,v$
\B\.svn\b
\B\.git\b
\B\.cvsignore$

# Avoid Makemaker generated and utility files.
\bMakefile$
\bblib
\bMakeMaker-\d
\bpm_to_blib$
\bblibdirs$
^MANIFEST\.SKIP$

# Avoid VMS specific Makmaker generated files
\bDescrip.MMS$
\bDESCRIP.MMS$
\bdescrip.mms$

# Avoid Module::Build generated and utility files.
\bBuild$
\bBuild.bat$
\b_build
\bBuild.COM$
\bBUILD.COM$
\bbuild.com$

# Avoid Devel::Cover generated files
\bcover_db

# Avoid temp and backup files.
~$
\.tmp$
\.old$
\.bak$
\#$
\.#
\.rej$

# Avoid OS-specific files/dirs
# Mac OSX metadata
\B\.DS_Store
# Mac OSX SMB mount metadata files
\B\._
# Avoid archives of this distribution
\bJavaScript-Beautifier-[\d\.\_]+
perl-JavaScript-Beautifier-0.17/META.yml000064400000000000000000000011651131653723000177770ustar00rootroot00000000000000---
name: JavaScript-Beautifier
version: 0.16
author:
- 'Fayland Lam <fayland@gmail.com>'
abstract: Beautify Javascript (beautifier for javascript)
license: perl
resources:
license: http://dev.perl.org/licenses/
repository: http://github.com/fayland/perl-javascript-beautifier/tree/master
build_requires:
Getopt::Long: 0
Pod::Usage: 0
Test::More: 0.88
configure_requires:
Module::Build: 0.35
provides:
JavaScript::Beautifier:
file: lib/JavaScript/Beautifier.pm
version: 0.16
generated_by: Module::Build version 0.35
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: 1.4
perl-JavaScript-Beautifier-0.17/Makefile.PL000064400000000000000000000011321131653723000204720ustar00rootroot00000000000000# Note: this file was auto-generated by Module::Build::Compat version 0.35
use ExtUtils::MakeMaker;
WriteMakefile
(
'NAME' => 'JavaScript::Beautifier',
'VERSION_FROM' => 'lib/JavaScript/Beautifier.pm',
'PREREQ_PM' => {
'Getopt::Long' => '0',
'Pod::Usage' => '0',
'Test::More' => '0.88'
},
'INSTALLDIRS' => 'site',
'EXE_FILES' => [
'bin/js_beautify.pl'
],
'PL_FILES' => {}
)
;
perl-JavaScript-Beautifier-0.17/README000064400000000000000000000026621131653723000174110ustar00rootroot00000000000000JavaScript-Beautifier

The README is used to introduce the module and provide instructions on
how to install the module, any machine dependencies it may have (for
example C compilers and installed libraries) and any other information
that should be provided before the module is installed.

A README file is required for CPAN modules since CPAN extracts the README
file from a module distribution so that people browsing the archive
can use it to get an idea of the module's uses. It is usually a good idea
to provide version information here so that people can decide whether
fixes for the module are worth downloading.


INSTALLATION

To install this module, run the following commands:

perl Build.PL
./Build
./Build test
./Build install

SUPPORT AND DOCUMENTATION

After installing, you can find documentation for this module with the
perldoc command.

perldoc JavaScript::Beautifier

You can also look for information at:

RT, CPAN's request tracker
http://rt.cpan.org/NoAuth/Bugs.html?Dist=JavaScript-Beautifier

AnnoCPAN, Annotated CPAN documentation
http://annocpan.org/dist/JavaScript-Beautifier

CPAN Ratings
http://cpanratings.perl.org/d/JavaScript-Beautifier

Search CPAN
http://search.cpan.org/dist/JavaScript-Beautifier/


COPYRIGHT AND LICENCE

Copyright (C) 2008 Fayland Lam

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

perl-JavaScript-Beautifier-0.17/bin/000075500000000000000000000000001131653723000172735ustar00rootroot00000000000000perl-JavaScript-Beautifier-0.17/bin/js_beautify.pl000064400000000000000000000034521131653723000221400ustar00rootroot00000000000000#!/usr/bin/perl

use strict;
use warnings;
use JavaScript::Beautifier qw/js_beautify/;
use Getopt::Long;
use Pod::Usage;
use IO::File;
use Carp qw/croak/;

my $file = pop @ARGV;
pod2usage(1) unless ($file);

my %params;
GetOptions(
\%params,
"help|?",
"o",
"output=s",
"s|indent_size=i",
"c|indent_character=s",
"p|preserve_newlines",
) or pod2usage(2);

pod2usage(1) if $params{help};

my $file_io;
if ($file eq '-') {
my $io = new IO::Handle;
$file_io = $io->fdopen(fileno(STDIN),"r");
} else {
$file_io = new IO::File($file, "<");
defined $file_io or croak "can't open $file: $!";
}
local $/;
my $js_source_code = <$file_io>;
$file_io->close;

my $pretty_js = js_beautify( $js_source_code, {
indent_size => $params{s} || 4,
indent_character => $params{c} || ' ',
preserve_newlines => $params{p} || 1
} );

if ( $params{output} or $params{o} ) {
my $to_file = $params{output} || $file;
open(my $fh, '>', $file);
print $fh $pretty_js;
close($fh);
} else {
print $pretty_js;
}

1;
__END__

=head1 NAME

js_beautify.pl - command tool to beautify your javascript files

=head1 SYNOPSIS

js_beautify.pl [options] FILE
js_beautify.pl [options] -

=head1 OPTIONS

=over 4

=item B<-?>, B<--help>

=item B<-o>, B<--output>

By default, we will print beautified javascript to STDOUT

if B<-o>, it will override the C<FILE>

if B<-output=newfile.js>, it will write into C<newfile.js>

=item B<-s>, B<--indent_size>

=item B<-c>, B<--indent_character>

By default, we use 4 spaces.

but if you prefer 8 spaces, we can do B<-s=8>

=item B<-p>, B<--preserve_newlines>

1 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.

=cutperl-JavaScript-Beautifier-0.17/lib/000075500000000000000000000000001131653723000172715ustar00rootroot00000000000000perl-JavaScript-Beautifier-0.17/lib/JavaScript/000075500000000000000000000000001131653723000213375ustar00rootroot00000000000000perl-JavaScript-Beautifier-0.17/lib/JavaScript/Beautifier.pm000064400000000000000000000667061131653723000237730ustar00rootroot00000000000000package JavaScript::Beautifier;

use warnings;
use strict;

our $VERSION = '0.17';
our $AUTHORITY = 'cpan:FAYLAND';

use base 'Exporter';
use vars qw/@EXPORT_OK/;
@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 @whitespace = split('', "\n\r\t ");
my @wordchar = split('', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$');
my @digits = split('', '0123456789');
# <!-- is a special case (ok, it's a minor hack actually)
my @punct = split(' ', '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::');
# 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 );

sub js_beautify {
my ( $js_source_code, $opts ) = @_;

$opt_indent_size = $opts->{indent_size} || 4;
$opt_indent_character = $opts->{indent_character} || ' ';
$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;

# -------------------------------------
$just_added_newline = 0;
$indent_string = '';
while ( $opt_indent_size-- ) {
$indent_string .= $opt_indent_character;
}
@input = split('', $js_source_code);

$last_word = ''; # last 'TK_WORD' passed
$last_type = 'TK_START_EXPR'; # last token type
$last_text = ''; # last token text
$last_last_text = ''; # pre-last token text
@output = ();

$do_block_just_closed = 0;
$var_line = 0;
$var_line_tainted = 0;

# states showing if we are currently in expression (i.e. "if" case) - 'EXPRESSION', or in usual block (like, procedure), 'BLOCK'.
# some formatting depends on that.
$current_mode = 'BLOCK';
@modes = ( $current_mode );

$parser_pos = 0; # parser position
$in_case = 0; # flag for parser that case/default has been processed, and next colon needs special attention
while ( 1 ) {
my $t = get_next_token($parser_pos);
$token_text = $t->[0];
$token_type = $t->[1];
if ( $token_type eq 'TK_EOF' ) {
last;
}

if ( $token_type eq 'TK_START_EXPR' ) {
$var_line = 0;

if ( $token_text eq '[' ) {
if ( $last_type eq 'TK_WORD' || $last_text eq ')' ) {
# this is array index specifier, break immediately
# a[x], fn()[x]
set_mode('(EXPRESSION)');
print_token();
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
}
if ( $current_mode eq '[EXPRESSION]' || $current_mode eq '[INDENTED-EXPRESSION]' ) {
if ( $last_last_text eq ']' && $last_text eq ',' ) {
# ], [ goes to new line
indent();
print_newline();
set_mode('[INDENTED-EXPRESSION]');
} elsif ($last_text eq '[') {
indent();
print_newline();
set_mode('[INDENTED-EXPRESSION]');
} else {
set_mode('[EXPRESSION]');
}
} else {
set_mode('[EXPRESSION]');
}
} else {
set_mode('(EXPRESSION)');
}

if ( $last_text eq ';' || $last_type eq 'TK_START_BLOCK' ) {
print_newline();
} elsif ( $last_type eq 'TK_END_EXPR' || $last_type eq 'TK_START_EXPR' ) {
# do nothing on (( and )( and ][ and ]( ..
} elsif ( $last_type ne 'TK_WORD' && $last_type ne 'TK_OPERATOR' ) {
print_space();
} elsif ( $last_word eq 'function' ) {
# function() vs function ()
if ( $opt_space_after_anon_function ) {
print_space();
}
} elsif ( grep { $last_word eq $_ } @line_starter ) {
print_space();
}
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();
}
restore_mode();
print_token();
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
} elsif ( $token_type eq 'TK_START_BLOCK' ) {
if ( $last_word eq 'do' ) {
set_mode('DO_BLOCK');
} else {
set_mode('BLOCK');
}
if ( $last_type ne 'TK_OPERATOR' && $last_type ne 'TK_START_EXPR' ) {
if ( $last_type eq 'TK_START_BLOCK' ) {
print_newline();
} else {
print_space();
}
}
print_token();
indent();
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
} elsif ( $token_type eq 'TK_END_BLOCK' ) {
if ( $last_type eq 'TK_START_BLOCK' ) {
# nothing
if ($just_added_newline) {
remove_indent();
# {
#
# }
} else {
# {}
trim_output();
}
unindent();
} else {
unindent();
print_newline();
}
print_token();
restore_mode();
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
} elsif ( $token_type eq 'TK_WORD' ) {
# no, it's not you. even I have problems understanding how this works
# and what does what.
if ( $do_block_just_closed ) {
print_space();
print_token();
print_space();
$do_block_just_closed = 0;
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
}
if ( $token_text eq 'case' || $token_text eq 'default' ) {
if ( $last_text eq ':' ) {
# switch cases following one another
remove_indent();
} else {
# case statement starts in the same line where switch
unindent();
print_newline();
indent();
}
print_token();
$in_case = 1;
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
}
$prefix = 'NONE';
if ( $last_type eq 'TK_END_BLOCK' ) {
if ( not (grep { lc($token_text) eq $_ } ('else', 'catch', 'finally')) ) {
$prefix = 'NEWLINE';
} else {
$prefix = 'SPACE';
print_space();
}
} elsif ( $last_type eq 'TK_SEMICOLON' && ( $current_mode eq 'BLOCK' || $current_mode eq 'DO_BLOCK' ) ) {
$prefix = 'NEWLINE';
} elsif ( $last_type eq 'TK_SEMICOLON' && is_expression($current_mode) ) {
$prefix = 'SPACE';
} elsif ( $last_type eq 'TK_STRING') {
$prefix = 'NEWLINE';
} elsif ( $last_type eq 'TK_WORD' ) {
$prefix = 'SPACE';
} elsif ( $last_type eq 'TK_START_BLOCK') {
$prefix = 'NEWLINE';
} elsif ( $last_type eq 'TK_END_EXPR' ) {
print_space();
$prefix = 'NEWLINE';
}

if ( $last_type ne 'TK_END_BLOCK' && (grep { lc($token_text) eq $_ } ('else', 'catch', 'finally')) ) {
print_newline();
} elsif ( (grep { $token_text eq $_ } @line_starter) || $prefix eq 'NEWLINE' ) {
if ( $last_text eq 'else' ) {
# no need to force newline on else break
print_space();
} elsif ( ( $last_type eq 'TK_START_EXPR' || $last_text eq '=' || $last_text eq ',' ) && $token_text eq 'function' ) {
# no need to force newline on 'function': (function
# DONOTHING
} elsif ( $last_text eq 'return' || $last_text eq 'throw' ) {
# no newline between 'return nnn'
print_space();
} elsif ( $last_type ne 'TK_END_EXPR' ) {
if ( ($last_type ne 'TK_START_EXPR' || $token_text ne 'var') && $last_text ne ':' ) {
# no need to force newline on 'var': for (var x = 0...)
if ( $token_text eq 'if' && $last_word eq 'else' && $last_text ne '{' ) {
# no newline for } else if {
print_space();
} else {
print_newline();
}
}
} else {
if ( (grep { $token_text eq $_ } @line_starter) && $last_text ne ')' ) {
print_newline();
}
}
} elsif ( $prefix eq 'SPACE' ) {
print_space();
}
print_token();
$last_word = $token_text;
if ( $token_text eq 'var' ) {
$var_line = 1;
$var_line_tainted = 0;
}
if ( $token_text eq 'if' || $token_text eq 'else' ) {
$if_line_flag = 1;
}
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
} elsif ( $token_type eq 'TK_SEMICOLON' ) {
print_token();
$var_line = 0;
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
} elsif ( $token_type eq 'TK_STRING' ) {
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' ) {
print_space();
}
print_token();
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
} elsif ( $token_type eq 'TK_OPERATOR' ) {
my $start_delim = 1;
my $end_delim = 1;
if ( $var_line && $token_text ne ',' ) {
$var_line_tainted = 1;
if ( $token_text eq ':' ) {
$var_line = 0;
}
}
if ($var_line && $token_text eq ',' && is_expression($current_mode) ) {
# do not break on comma, for(var a = 1, b = 2)
$var_line_tainted = 0;
}
if ( $token_text eq ':' && $in_case ) {
print_token(); # colon really asks for separate treatment
print_newline();
$in_case = 0;
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
}
if ( $token_text eq '::' ) {
# no spaces around exotic namespacing syntax operator
print_token();
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
}

if ( $token_text eq ',' ) {
if ($var_line) {
if ( $var_line_tainted ) {
print_token();
print_newline();
$var_line_tainted = 0;
} else {
print_token();
print_space();
}
} elsif ( $last_type eq 'TK_END_BLOCK' ) {
print_token();
print_newline();
} else {
if ( $current_mode eq 'BLOCK' ) {
print_token();
print_newline();
} else {
# EXPR or DO_BLOCK
print_token();
print_space();
}
}
$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 ';' ) {
if ( $current_mode eq 'BLOCK') {
# { foo; --i }
print_newline();
$start_delim = 1;
$end_delim = 0;
} else {
# space for (;; ++i)
$start_delim = 1;
$end_delim = 0;
}
} else {
if ($last_text eq '{') {
# {--i
print_newline();
}
$start_delim = 0;
$end_delim = 0;
}
} elsif ( ( $token_text eq '!' || $token_text eq '+' || $token_text eq '-' ) && ($last_text eq 'return' || $last_text eq 'case') ) {
$start_delim = 1;
$end_delim = 0;
} elsif ( ( $token_text eq '!' || $token_text eq '+' || $token_text eq '-' ) && $last_type eq 'TK_START_EXPR' ) {
# special case handling: if (!a)
$start_delim = 0;
$end_delim = 0;
} elsif ( $last_type eq 'TK_OPERATOR' ) {
$start_delim = 0;
$end_delim = 0;
} elsif ( $last_type eq 'TK_END_EXPR' ) {
$start_delim = 1;
$end_delim = 1;
} elsif ( $token_text eq '.' ) {
# decimal digits or object.property
$start_delim = 0;
$end_delim = 0;
} elsif ( $token_text eq ':' ) {
if (is_ternary_op()) {
$start_delim = 1;
} else {
$start_delim = 0;
}
}
if ( $start_delim ) {
print_space();
}
print_token();
if ( $end_delim ) {
print_space();
}
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
} elsif ($token_type eq 'TK_BLOCK_COMMENT') {
print_newline();
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();
print_token();
print_newline();
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
} elsif ($token_type eq 'TK_UNKNOWN') {
print_token();
$last_last_text = $last_text;$last_type = $token_type;$last_text = $token_text;next;
}
$last_type = $token_type;
$last_text = $token_text;
}

my $output = join('', @output);
$output =~ s/\n+$//;
return $output;
}

sub trim_output {
while ( scalar @output && ( $output[ scalar @output - 1 ] eq ' ' || $output[ scalar @output - 1 ] eq $indent_string ) ) {
pop @output;
}
}
sub print_newline {
my ( $ignore_repeated ) = @_;
$ignore_repeated = 1 unless defined $ignore_repeated;
$if_line_flag = 0;
trim_output();

if ( not scalar @output ) {
return; # no newline on start of file
}

if ( $output[ scalar @output - 1 ] ne "\n" || ! $ignore_repeated ) {
$just_added_newline = 1;
push @output, "\n";
}
foreach my $i ( 0 .. $opt_indent_level - 1 ) {
push @output, $indent_string;
}
}

sub print_space {
my $last_output = ' ';
$last_output = $output[ scalar @output - 1 ] if scalar @output;
if ( $last_output ne ' ' && $last_output ne "\n" && $last_output ne $indent_string ) { # prevent occassional duplicate space
push @output, ' ';
}
}

sub print_token {
$just_added_newline = 0;
push @output, $token_text;
}
sub indent {
$opt_indent_level++;
}
sub unindent {
if ( $opt_indent_level ) {
$opt_indent_level--;
}
}
sub remove_indent {
if ( scalar @output && $output[ scalar @output - 1 ] eq $indent_string ) {
pop @output;
}
}
sub set_mode {
my $mode = shift;
push @modes, $current_mode;
$current_mode = $mode;
}
sub is_expression {
my $mode = shift;
return ($mode eq '[EXPRESSION]' || $mode eq '[INDENTED-EXPRESSION]' || $mode eq '(EXPRESSION)') ? 1 : 0;
}
sub restore_mode {
$do_block_just_closed = ( $current_mode eq 'DO_BLOCK' ) ? 1 : 0;
$current_mode = pop @modes;
}

# Walk backwards from the colon to find a '?' (colon is part of a ternary op)
# or a '{' (colon is part of a class literal). Along the way, keep track of
# the blocks and expressions we pass so we only trigger on those chars in our
# own level, and keep track of the colons so we only trigger on the matching '?'.
sub is_ternary_op {
my $level = 0;
my $colon_count = 0;
foreach my $o (reverse @output) {
if ( $o eq ':' ) {
if ( $level == 0 ) {
$colon_count++;
}
next;
} elsif ( $o eq '?' ) {
if ( $level == 0 ) {
if ( $colon_count == 0 ) {
return 1;
} else {
$colon_count--;
}
}
next;
} elsif ( $o eq '{' ) {
if ( $level == 0 ) {
return 0;
}
$level--;
next;
}
if ( $o eq '(' or $o eq '[' ) {
$level--;
next;
} elsif ( $o eq ')' or $o eq ']' or $o eq '}' ) {
$level++;
next;
}
}
}

sub get_next_token {
my $n_newlines = 0;

if ( $parser_pos >= scalar @input ) {
return ['', 'TK_EOF'];
}

my $c = $input[$parser_pos];
$parser_pos++;

while ( grep { $_ eq $c } @whitespace ) {
if ( $parser_pos >= scalar @input ) {
return ['', 'TK_EOF'];
}
if ( $c eq "\n" ) {
$n_newlines += 1;
}
$c = $input[$parser_pos];
$parser_pos++;
};
$wanted_newline = 0;
if ( $opt_preserve_newlines ) {
if ( $n_newlines > 1 ) {
foreach my $i ( 0 .. 1 ) {
my $flag = ( $i == 0 ) ? 1 : 0;
print_newline( $flag );
}
}
$wanted_newline = ($n_newlines == 1) ? 1 : 0;
}
if ( grep { $c eq $_ } @wordchar ) {
if ( $parser_pos < scalar @input ) {
while ( grep { $input[$parser_pos] eq $_ } @wordchar ) {
$c .= $input[$parser_pos];
$parser_pos++;
if ( $parser_pos == scalar @input ) {
last;
}
}
}

# small and surprisingly unugly hack for 1E-10 representation
if ( $parser_pos != scalar @input && $c =~ /^[0-9]+[Ee]$/ && ($input[$parser_pos] eq '-' || $input[$parser_pos] eq '+') ) {
my $sign = $input[$parser_pos];
$parser_pos++;
my $t = get_next_token($parser_pos);
$c .= $sign . $t->[0];
return [$c, 'TK_WORD'];
}
if ( $c eq 'in' ) { # hack for 'in' operator
return [$c, 'TK_OPERATOR'];
}
if ( $wanted_newline && $last_type ne 'TK_OPERATOR' && not $if_line_flag ) {
print_newline();
}
return [$c, 'TK_WORD'];
}
if ( $c eq '(' || $c eq '[' ) {
return [$c, 'TK_START_EXPR'];
}
if ( $c eq ')' || $c eq ']' ) {
return [$c, 'TK_END_EXPR'];
}
if ( $c eq '{' ) {
return [$c, 'TK_START_BLOCK'];
}
if ( $c eq '}' ) {
return [$c, 'TK_END_BLOCK'];
}
if ( $c eq ';' ) {
return [$c, 'TK_SEMICOLON'];
}
if ( $c eq '/' ) {
my $comment;
# peek for comment /* ... */
if ( $input[$parser_pos] eq '*' ) {
$parser_pos++;
if ( $parser_pos < scalar @input ) {
while (not ( $input[$parser_pos] eq '*' && $input[$parser_pos+1] && $input[$parser_pos+1] eq '/') && $parser_pos < scalar @input ) {
$comment .= $input[$parser_pos];
$parser_pos++;
if ( $parser_pos >= scalar @input ) {
last;
}
}
}
$parser_pos += 2;
return ['/*' . $comment . '*/', 'TK_BLOCK_COMMENT'];
}
# peek for comment // ...
if ( $input[$parser_pos] eq '/' ) {
$comment = $c;
while ( $input[$parser_pos] ne "\x0d" && $input[$parser_pos] ne "\x0a" ) {
$comment .= $input[$parser_pos];
$parser_pos++;
if ( $parser_pos >= scalar @input ) {
last;
}
}
$parser_pos++;
if ($wanted_newline) {
print_newline();
}
return [$comment, 'TK_COMMENT'];
}
}
if ( $c eq "'" || # string
$c eq '"' || # string
($c eq '/' &&
(( $last_type eq 'TK_WORD' && $last_text eq 'return') ||
( $last_type eq 'TK_START_EXPR' || $last_type eq 'TK_START_BLOCK' || $last_type eq 'TK_END_BLOCK' || $last_type eq 'TK_OPERATOR' || $last_type eq 'TK_EOF' || $last_type eq 'TK_SEMICOLON')))) { # regexp
my $sep = $c;
my $esc = 0;
my $resulting_string = $c;
if ( $parser_pos < scalar @input ) {
if ( $sep eq '/') {
# handle regexp separately...
my $in_char_class = 0;
while ( $esc || $in_char_class || $input[$parser_pos] ne $sep ) {
$resulting_string .= $input[$parser_pos];
if ( not $esc ) {
$esc = ( $input[$parser_pos] eq '\\' ) ? 1 : 0;
if ( $input[$parser_pos] eq '[' ) {
$in_char_class = 1;
} elsif ( $input[$parser_pos] eq ']' ) {
$in_char_class = 0;
}
} else {
$esc = 0;
}
$parser_pos++;
if ( $parser_pos >= scalar @input ) {
# incomplete string/rexp when end-of-file reached.
# bail out with what had been received so far.
return [$resulting_string, 'TK_STRING'];
}
}

} else {
# and handle string also separately
while ( $esc || $input[$parser_pos] ne $sep ) {
$resulting_string .= $input[$parser_pos];
if ( not $esc ) {
$esc = ( $input[$parser_pos] eq '\\' ) ? 1 : 0;
} else {
$esc = 0;
}
$parser_pos++;
if ( $parser_pos >= scalar @input ) {
# incomplete string/rexp when end-of-file reached.
# bail out with what had been received so far.
return [$resulting_string, 'TK_STRING'];
}
}
}
}
$parser_pos++;
$resulting_string .= $sep;
if ( $sep eq '/' ) {
# regexps may have modifiers /regexp/MOD , so fetch those, too
while ( $parser_pos < scalar @input && (grep { $input[$parser_pos] eq $_ } @wordchar) ) {
$resulting_string .= $input[$parser_pos];
$parser_pos++;
}
}
return [$resulting_string, 'TK_STRING'];
}

if ($c eq '#') {
# Spidermonkey-specific sharp variables for circular references
# https://developer.mozilla.org/En/Sharp_variables_in_JavaScript
# http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935
my $sharp = '#';
if ($parser_pos < scalar @input && (grep { $input[$parser_pos] eq $_ } @digits) ) {
do {
$c = $input[$parser_pos];
$sharp .= $c;
$parser_pos += 1;
} while ($parser_pos < scalar @input && $c ne '#' && $c ne '=');
if ($c eq '#') {
return [$sharp, 'TK_WORD'];
} else {
return [$sharp, 'TK_OPERATOR'];
}
}
}

if ($c eq '<' && $parser_pos + 2 < scalar @input && join('', @input[$parser_pos-1 .. $parser_pos+2]) eq '<!--') {
$parser_pos += 3;
return ['<!--', 'TK_COMMENT'];
}
if ($c eq '-' && $parser_pos + 1 < scalar @input && join('', @input[$parser_pos-1 .. $parser_pos+1]) eq '-->') {
$parser_pos += 2;
if ($wanted_newline) {
print_newline();
}
return ['-->', 'TK_COMMENT'];
}

if ( grep { $c eq $_ } @punct ) {
while ( $parser_pos < scalar @input && (grep { $c . $input[$parser_pos] eq $_ } @punct) ) {
$c .= $input[$parser_pos];
$parser_pos++;
last if ( $parser_pos >= scalar @input );
}
return [$c, 'TK_OPERATOR'];
}
return [$c, 'TK_UNKNOWN'];
}

1;
__END__

=head1 NAME

JavaScript::Beautifier - Beautify Javascript (beautifier for javascript)

=head1 SYNOPSIS

use JavaScript::Beautifier qw/js_beautify/;

my $pretty_js = js_beautify( $js_source_code, {
indent_size => 4,
indent_character => ' ',
} );

=head1 DESCRIPTION

This module is mostly a Perl-rewrite of L<http://github.com/einars/js-beautify/tree/master/beautify.js>

You can check it through L<http://jsbeautifier.org/>

=head1 FUNCTIONS

=head2 js_beautify( $js_source_code, $opts );

beautify javascript.

=head3 options

=over 4

=item indent_size

=item indent_character

if you prefer Tab than Space, try:

{
indent_size => 1,
indent_character => "\t",
}

=item preserve_newlines

default is 1

my $in = "var\na=dont_preserve_newlines";
my $out = "var a = dont_preserve_newlines";
my $js = js_beautify( $in, { preserve_newlines => 0 } );
# $out eq $js
$in = "var\na=do_preserve_newlines";
$out = "var\na = do_preserve_newlines";
$js = js_beautify( $in, { preserve_newlines => 1 } );
# $out eq $js

=item space_after_anon_function

default is 0

=back

=head1 AUTHOR

Fayland Lam, C<< <fayland at gmail.com> >>

=head1 COPYRIGHT & LICENSE

Copyright 2008 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
perl-JavaScript-Beautifier-0.17/t/000075500000000000000000000000001131653723000167665ustar00rootroot00000000000000perl-JavaScript-Beautifier-0.17/t/00-load.t000064400000000000000000000002601131653723000203050ustar00rootroot00000000000000#!perl -T

use Test::More tests => 1;

BEGIN {
use_ok( 'JavaScript::Beautifier' );
}

diag( "Testing JavaScript::Beautifier $JavaScript::Beautifier::VERSION, Perl $], $^X" );
perl-JavaScript-Beautifier-0.17/t/01-javascript-beauty.t000064400000000000000000000226271131653723000230370ustar00rootroot00000000000000#!perl -T

use strict;
use warnings;
use Test::More;
use JavaScript::Beautifier qw/js_beautify/;

# from http://github.com/einars/js-beautify/tree/master/beautify-tests.js

my $tests_num = 0;

my $opts = {
indent_size => 4,
indent_character => ' ',
space_after_anon_function => 1,
preserve_newlines => 1,
};

sub test_beautifier {
my ($input, $expected) = @_;

$expected ||= $input;
my $result = js_beautify( $input, $opts );

$tests_num++;
is($result, $expected, $input);
}

sub bt {
my ($input, $expected) = @_;

test_beautifier(@_);
$expected ||= $input;

# test also the returned indentation
# e.g if input = "asdf();"
# then test that this remains properly formatted as well:
# {
# asdf();
# indent;
# }

if ( $opts->{indent_size} == 4 && $input ) {
my $wrapped_input = "{\n" . $input . "\nindent;}";
my $wrapped_expectation = $expected;
$wrapped_expectation =~ s/^(.+)$/ $1/mg;
$wrapped_expectation = "{\n$wrapped_expectation\n indent;\n}";
test_beautifier($wrapped_input, $wrapped_expectation);
}
}

bt( 'a = 1', 'a = 1');
bt( 'a=1', 'a = 1');
bt( "a();\n\nb();", "a();\n\nb();");
bt( 'var a = 1 var b = 2', "var a = 1\nvar b = 2");
bt( 'var a=1, b=c[d], e=6;', "var a = 1,\nb = c[d],\ne = 6;");
bt( 'a = " 12345 "');
bt( "a = ' 12345 '");
bt( 'if (a == 1) b = 2;', "if (a == 1) b = 2;");
bt( 'if(1){2}else{3}', "if (1) {\n 2\n} else {\n 3\n}" );
bt( 'if(1||2);', 'if (1 || 2);' );
bt( '(a==1)||(b==2)', '(a == 1) || (b == 2)' );
bt( 'var a = 1 if (2) 3;', "var a = 1\nif (2) 3;" );
bt('a /= 5');
bt('a = 0.5 * 3');
bt('a *= 10.55');
bt('a < .5');
bt('a <= .5');
bt('a<.5', 'a < .5');
bt('a<=.5', 'a <= .5');
bt('a = 0xff;');
bt( 'a=0xff+4', 'a = 0xff + 4' );
bt( 'a = [1, 2, 3, 4]');
bt( 'F*(g/=f)*g+b', 'F * (g /= f) * g + b' );
bt( 'a.b({c:d})', "a.b({\n c: d\n})" );
bt( "a.b\n(\n{\nc:\nd\n}\n)", "a.b({\n c: d\n})" );
bt( 'a=!b', 'a = !b' );
bt( 'a?b:c', 'a ? b : c' );
bt( 'a?1:2', 'a ? 1 : 2' );
bt( 'a?(b):c', 'a ? (b) : c' );
bt( 'x={a:1,b:w=="foo"?x:y,c:z}', "x = {\n a: 1,\n b: w == \"foo\" ? x : y,\n c: z\n}");
bt( 'x=a?b?c?d:e:f:g;', 'x = a ? b ? c ? d : e : f : g;' );
bt( 'x=a?b?c?d:{e1:1,e2:2}:f:g;', "x = a ? b ? c ? d : {\n e1: 1,\n e2: 2\n} : f : g;");
bt( 'function void(void) {}' );
bt( 'if(!a)foo();', 'if (!a) foo();' );
bt( 'a=~a', 'a = ~a' );
bt( 'a;/*comment*/b;', "a;\n/*comment*/\nb;" );
bt( 'if(a)break;', "if (a) break;" );
bt( 'if(a){break}', "if (a) {\n break\n}" );
bt( 'if((a))foo();', 'if ((a)) foo();' );
bt( 'for(var i=0;;)', 'for (var i = 0;;)' );
bt( 'a++;', 'a++;' );
bt( 'for(;;i++)', 'for (;; i++)' );
bt( 'for(;;++i)', 'for (;; ++i)' );
bt( 'return(1)', 'return (1)' );
bt( 'try{a();}catch(b){c();}finally{d();}', "try {\n a();\n} catch(b) {\n c();\n} finally {\n d();\n}" );
bt('(xx)()'); # magic function call
bt('a[1]()'); # another magic function call
bt( 'if(a){b();}else if(c) foo();', "if (a) {\n b();\n} else if (c) foo();" );
bt( 'switch(x) {case 0: case 1: a(); break; default: break}', "switch (x) {\ncase 0:\ncase 1:\n a();\n break;\ndefault:\n break\n}" );
bt( 'switch(x){case -1:break;case !y:break;}', "switch (x) {\ncase -1:\n break;\ncase !y:\n break;\n}" );
bt( 'a !== b' );
bt( 'if (a) b(); else c();', "if (a) b();\nelse c();" );
bt( "// comment\n(function something() {})"); # typical greasemonkey start
bt( "{\n\n x();\n\n}"); # was: duplicating newlines
bt( 'if (a in b) foo();');
bt( '{a:1, b:2}', "{\n a: 1,\n b: 2\n}" );
bt( 'a={1:[-1],2:[+1]}', "a = {\n 1: [-1],\n 2: [+1]\n}" );
bt( 'var l = {\'a\':\'1\', \'b\':\'2\'}', "var l = {\n 'a': '1',\n 'b': '2'\n}" );
bt( 'if (template.user[n] in bk) foo();');
bt( '{{}/z/}', "{\n {}\n /z/\n}" );
bt( 'return 45', "return 45" );
bt( 'If[1]', "If[1]" );
bt( 'Then[1]', "Then[1]" );
bt( 'a = 1e10', "a = 1e10" );
bt( 'a = 1.3e10', "a = 1.3e10" );
bt( 'a = 1.3e-10', "a = 1.3e-10" );
bt( 'a = -1.3e-10', "a = -1.3e-10" );
bt( 'a = 1e-10', "a = 1e-10" );
bt( 'a = e - 10', "a = e - 10" );
bt( 'a = 11-10', "a = 11 - 10" );
bt( "a = 1;// comment\n", "a = 1; // comment" );
bt( "a = 1; // comment\n", "a = 1; // comment" );
bt( "a = 1;\n // comment\n", "a = 1;\n// comment" );

bt( "if (a) {\n do();\n}"); # was: extra space appended
bt( "if\n(a)\nb();", "if (a) b();" ); # test for proper newline removal

bt( "if (a) {\n// comment\n}else{\n// comment\n}", "if (a) {\n // comment\n} else {\n // comment\n}" ); # if/else statement with empty body
bt( "if (a) {\n// comment\n// comment\n}", "if (a) {\n // comment\n // comment\n}" ); # multiple comments indentation
bt( "if (a) b() else c();", "if (a) b()\nelse c();" );
bt( "if (a) b() else if c() d();", "if (a) b()\nelse if c() d();" );

bt("{}");
bt("{\n\n}");
bt("do { a(); } while ( 1 );", "do {\n a();\n} while (1);");
bt("do {} while (1);");
bt("do {\n} while (1);", "do {} while (1);");
bt("do {\n\n} while (1);");
bt("var a = x(a, b, c)");
bt( "delete x if (a) b();", "delete x\nif (a) b();" );
bt( "delete x[x] if (a) b();", "delete x[x]\nif (a) b();" );
bt( "for(var a=1,b=2)", "for (var a = 1, b = 2)" );
bt( "for(var a=1,b=2,c=3)", "for (var a = 1, b = 2, c = 3)" );
bt( "for(var a=1,b=2,c=3;d<3;d++)", "for (var a = 1, b = 2, c = 3; d < 3; d++)" );
bt( "function x(){(a||b).c()}", "function x() {\n (a || b).c()\n}" );
bt( "function x(){return - 1}", "function x() {\n return -1\n}" );
bt( "function x(){return ! a}", "function x() {\n return !a\n}" );

bt("a = 'a'\nb = 'b'");
bt("a = /reg/exp");
bt("a = /reg/");
bt('/abc/.test()');
bt('/abc/i.test()');
bt( "{/abc/i.test()}", "{\n /abc/i.test()\n}" );

bt( "{x=#1=[]}", "{\n x = #1=[]\n}");
bt( "{a:#1={}}", "{\n a: #1={}\n}");
bt( "{a:#1#}", "{\n a: #1#\n}" );
test_beautifier( "{a:#1", "{\n a: #1" ); # incomplete
test_beautifier( "{a:#", "{\n a: #" ); # incomplete

test_beautifier( "<!--\nvoid();\n// -->", "<!--\nvoid();\n// -->");

test_beautifier( "a=/regexp", "a = /regexp" ); # incomplete regexp

bt( "{a:#1=[],b:#1#,c:#999999#}", "{\n a: #1=[],\n b: #1#,\n c: #999999#\n}" );

bt("a = 1e+2");
bt("a = 1e-2");
bt( "do{x()}while(a>1)", "do {\n x()\n} while (a > 1)" );

bt( "x(); /reg/exp.match(something)", "x();\n/reg/exp.match(something)" );

bt("something();(", "something();\n(");

bt("function namespace::something()");

test_beautifier( "<!--\nsomething();\n-->", "<!--\nsomething();\n-->" );
test_beautifier( "<!--\nif(i<0){bla();}\n-->", "<!--\nif (i < 0) {\n bla();\n}\n-->");

test_beautifier( "<!--\nsomething();\n-->\n<!--\nsomething();\n-->", "<!--\nsomething();\n-->\n<!--\nsomething();\n-->");
test_beautifier( "<!--\nif(i<0){bla();}\n-->\n<!--\nif(i<0){bla();}\n-->", "<!--\nif (i < 0) {\n bla();\n}\n-->\n<!--\nif (i < 0) {\n bla();\n}\n-->");

bt( '{foo();--bar;}', "{\n foo();\n --bar;\n}");
bt( '{foo();++bar;}', "{\n foo();\n ++bar;\n}");
bt( '{--bar;}', "{\n --bar;\n}");
bt( '{++bar;}', "{\n ++bar;\n}");

# regexps
bt( 'a(/abc\\/\\/def/);b()', "a(/abc\\/\\/def/);\nb()" );
bt( 'a(/a[b\\[\\]c]d/);b()', "a(/a[b\\[\\]c]d/);\nb()" );
test_beautifier('a(/a[b\\[', "a(/a[b\\["); # incomplete char class
# allow unescaped / in char classes
bt( 'a(/[a/b]/);b()', "a(/[a/b]/);\nb()" );

bt( 'a=[[1,2],[4,5],[7,8]]', "a = [\n [1, 2],\n [4, 5],\n [7, 8]]" );
bt( 'a=[a[1],b[4],c[d[7]]]', "a = [a[1], b[4], c[d[7]]]" );
bt( '[1,2,[3,4,[5,6],7],8]', "[1, 2, [3, 4, [5, 6], 7], 8]" );

bt( '[[["1","2"],["3","4"]],[["5","6","7"],["8","9","0"]],[["1","2","3"],["4","5","6","7"],["8","9","0"]]]',
qq~[\n [\n ["1", "2"],\n ["3", "4"]],\n [\n ["5", "6", "7"],\n ["8", "9", "0"]],\n [\n ["1", "2", "3"],\n ["4", "5", "6", "7"],\n ["8", "9", "0"]]]~ );

bt( '{[x()[0]];indent;}', "{\n [x()[0]];\n indent;\n}" );

$opts->{space_after_anon_function} = 1;

bt( "// comment 1\n(function()", "// comment 1\n(function ()"); # typical greasemonkey start
bt( "var a1, b1, c1, d1 = 0, c = function() {}, d = '';", "var a1, b1, c1, d1 = 0,\nc = function () {},\nd = '';");
bt( 'var o1=$.extend(a,function(){alert(x);}', "var o1 = \$.extend(a, function () {\n alert(x);\n}");
bt( 'var o1=$.extend(a);function(){alert(x);}', "var o1 = \$.extend(a);\nfunction () {\n alert(x);\n}" );

$opts->{space_after_anon_function} = 0;

bt( "// comment 2\n(function()", "// comment 2\n(function()"); # typical greasemonkey start
bt( "var a2, b2, c2, d2 = 0, c = function() {}, d = '';", "var a2, b2, c2, d2 = 0,\nc = function() {},\nd = '';");
bt( 'var o2=$.extend(a,function(){alert(x);}', "var o2 = \$.extend(a, function() {\n alert(x);\n}");
bt( 'var o2=$.extend(a);function(){alert(x);}', "var o2 = \$.extend(a);\nfunction() {\n alert(x);\n}");
bt( '{[y[a]];keep_indent;}', "{\n [y[a]];\n keep_indent;\n}");
bt( 'if (x) {y} else { if (x) {y}}', "if (x) {\n y\n} else {\n if (x) {\n y\n }\n}" );

$opts->{indent_size} = 1;
$opts->{indent_char} = ' ';

bt( '{ one_char() }', "{\n one_char()\n}" );

$opts->{indent_size} = 4;
$opts->{indent_char} = ' ';

bt( '{ one_char() }', "{\n one_char()\n}" );

$opts->{indent_size} = 1;
$opts->{indent_char} = "\t";

# FIXME
#bt( '{ one_char() }', "{\n\tone_char()\n}" );

$opts->{preserve_newlines} = 0;
bt( "var\na=dont_preserve_newlines", "var a = dont_preserve_newlines" );

$opts->{preserve_newlines} = 1;
bt( "var\na=do_preserve_newlines", "var\na = do_preserve_newlines" );

done_testing( $tests_num );

1;
perl-JavaScript-Beautifier-0.17/t/pod.t000064400000000000000000000003501131653723000177330ustar00rootroot00000000000000#!perl -T

use strict;
use warnings;
use Test::More;

# Ensure a recent version of Test::Pod
my $min_tp = 1.22;
eval "use Test::Pod $min_tp";
plan skip_all => "Test::Pod $min_tp required for testing POD" if $@;

all_pod_files_ok();
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin