jqueryplugingen 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -1
- data/Manifest.txt +6 -1
- data/README.rdoc +5 -2
- data/lib/jquery_plugin_gen/compiletask.rb +166 -0
- data/lib/jquery_plugin_gen/generator.rb +1 -4
- data/lib/jquery_plugin_gen/support/build.rake +13 -0
- data/lib/jquery_plugin_gen/support/package.rake +13 -0
- data/lib/jquery_plugin_gen/tasks.rb +1 -1
- data/lib/jquery_plugin_gen.rb +1 -1
- data/lib/packer/Pack.pm +467 -0
- data/lib/packer/ParseMaster.pm +207 -0
- data/lib/packer/jsPacker.pl +163 -0
- data/lib/templates/Rakefile.erb +7 -1
- metadata +8 -3
- data/lib/templates/Makefile.erb +0 -76
data/History.txt
CHANGED
@@ -1,9 +1,21 @@
|
|
1
|
+
== 0.1.3 2009-06-08
|
2
|
+
|
3
|
+
* Add rake tasks for build/dist plugins:
|
4
|
+
* Add clean rake task
|
5
|
+
* Replace Makefile
|
6
|
+
* Delegate build tasks to gem rakefiles rather than generate
|
7
|
+
* Add to task folder to generation and then in Rakefile scan that folder for custom tasks
|
8
|
+
|
9
|
+
== 0.1.2 2009-06-07
|
10
|
+
|
11
|
+
* Be able to download jquery tmbundles into Textmate:
|
12
|
+
* Add rake task for tmbundle loading from gem or from svn latest
|
13
|
+
|
1
14
|
== 0.1.1 2009-06-06
|
2
15
|
|
3
16
|
* Be able to download jquery files into library:
|
4
17
|
* jQuery core, ui and themes with rake
|
5
18
|
* Add option to install different versions of libraries
|
6
|
-
* Add rake task for tmbundle loading from gem or from svn latest
|
7
19
|
|
8
20
|
== 0.1.0 2009-05-30
|
9
21
|
|
data/Manifest.txt
CHANGED
@@ -162,14 +162,19 @@ bundles/JavaScript.tmbundle/info.plist
|
|
162
162
|
jQuery-Plugin-Generator.tmproj
|
163
163
|
lib/jqp/cli.rb
|
164
164
|
lib/jquery_plugin_gen.rb
|
165
|
+
lib/jquery_plugin_gen/compiletask.rb
|
165
166
|
lib/jquery_plugin_gen/generator.rb
|
166
167
|
lib/jquery_plugin_gen/quick_template.rb
|
168
|
+
lib/jquery_plugin_gen/support/build.rake
|
167
169
|
lib/jquery_plugin_gen/support/bundles.rake
|
168
170
|
lib/jquery_plugin_gen/support/jquery.rake
|
171
|
+
lib/jquery_plugin_gen/support/package.rake
|
169
172
|
lib/jquery_plugin_gen/tasks.rb
|
173
|
+
lib/packer/Pack.pm
|
174
|
+
lib/packer/ParseMaster.pm
|
175
|
+
lib/packer/jsPacker.pl
|
170
176
|
lib/templates/History.txt.erb
|
171
177
|
lib/templates/README.txt.erb
|
172
|
-
lib/templates/Makefile.erb
|
173
178
|
lib/templates/Rakefile.erb
|
174
179
|
lib/templates/example.html.erb
|
175
180
|
lib/templates/src/plugin.js.erb
|
data/README.rdoc
CHANGED
@@ -10,11 +10,14 @@ Generate the structure of jquery plugins easily. Manage library dependencies suc
|
|
10
10
|
== FEATURES/PROBLEMS:
|
11
11
|
|
12
12
|
* be able to use the produced code on linux and windows (need jqp.bat)
|
13
|
+
* bundle up jsspec
|
14
|
+
* include qunit
|
13
15
|
* add acceptance test
|
14
16
|
* add hoe-type features for updating plugins to jquery plugin page (as rake tasks)
|
15
|
-
* be able to bundle library dependencies
|
16
|
-
* be able to switch between local and remote libraries in actual html pages
|
17
|
+
* be able to bundle/package library dependencies
|
18
|
+
* be able to switch between local and remote libraries in actual html pages (perhaps this is the release bundle)
|
17
19
|
* be able to generate new modules and update html pages (as rake task or generator)
|
20
|
+
* nice to remove option -p for project "jpq myplugin"
|
18
21
|
|
19
22
|
== SYNOPSIS:
|
20
23
|
|
@@ -0,0 +1,166 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Define a compile task libarary to aid in the definition of
|
4
|
+
# redistributable package files of javascript/jquery plugins.
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'rake/tasklib'
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
module Rake
|
11
|
+
|
12
|
+
# Create a compiling task that will build the project into
|
13
|
+
# distributable files (e.g a single and a packed js file with compression).
|
14
|
+
#
|
15
|
+
# The CompileTask will create the following targets:
|
16
|
+
#
|
17
|
+
# [<b>:compile</b>]
|
18
|
+
# Create all the requested package files.
|
19
|
+
#
|
20
|
+
# [<b>:clobber_compile</b>]
|
21
|
+
# Delete all the package files. This target is automatically
|
22
|
+
# added to the main clobber target.
|
23
|
+
#
|
24
|
+
# [<b>:recompile</b>]
|
25
|
+
# Rebuild the package files from scratch, even if they are not out
|
26
|
+
# of date.
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
#
|
30
|
+
# JqueryPluginGen::CompileTask.new('query.plugin') do |p|
|
31
|
+
# p.js_files.include("src/**/*.js")
|
32
|
+
# p.css_files.include("src/css/**/*.css")
|
33
|
+
# p.image_files.include("src/images/**/*.*")
|
34
|
+
# p.js_dir = "src"
|
35
|
+
# p.images_dir = "images"
|
36
|
+
# p.css_dir = "css"
|
37
|
+
# p.package_files.include("README.txt", "HISTORY.txt")
|
38
|
+
# p.package_dir = "build"
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
|
42
|
+
class CompileTask < TaskLib
|
43
|
+
|
44
|
+
# Name of the plugin files (don't add .js, eg 'jquery.mywidget').
|
45
|
+
attr_accessor :name
|
46
|
+
|
47
|
+
# Directory used to store the package files (default is 'images').
|
48
|
+
attr_accessor :images_dir
|
49
|
+
|
50
|
+
# Directory used to store the package files (default is 'css').
|
51
|
+
attr_accessor :css_dir
|
52
|
+
|
53
|
+
# Directory used to store the package files (default is 'build').
|
54
|
+
attr_accessor :package_dir
|
55
|
+
|
56
|
+
# True if the single js file is compiled using SED (default is true).
|
57
|
+
attr_accessor :need_sed
|
58
|
+
|
59
|
+
# True if the single js file is compressed using PACKER (default is true).
|
60
|
+
attr_accessor :need_packer
|
61
|
+
|
62
|
+
# List of files to be included in the package.
|
63
|
+
attr_accessor :package_files
|
64
|
+
|
65
|
+
# List of files to be included in the package.
|
66
|
+
attr_accessor :js_files
|
67
|
+
|
68
|
+
# List of files to be included in the package.
|
69
|
+
attr_accessor :css_files
|
70
|
+
|
71
|
+
# List of files to be included in the package.
|
72
|
+
attr_accessor :image_files
|
73
|
+
|
74
|
+
# Create a Compile Task
|
75
|
+
def initialize(name)
|
76
|
+
init(name)
|
77
|
+
yield self if block_given?
|
78
|
+
define unless name.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
# Initialization that bypasses the "yield self" and "define" step.
|
82
|
+
def init(name)
|
83
|
+
@name = name
|
84
|
+
@package_files = Rake::FileList["README.txt", "HISTORY.txt"]
|
85
|
+
@package_dir = 'build'
|
86
|
+
@need_sed = true
|
87
|
+
@need_packer = true
|
88
|
+
@images_dir = 'images'
|
89
|
+
@css_dir = 'css'
|
90
|
+
@js_dir = 'src'
|
91
|
+
@js_files = Rake::FileList.new
|
92
|
+
@js_files.include("#{@js_dir}/**/*.js")
|
93
|
+
@image_files = Rake::FileList.new
|
94
|
+
@image_files.include("#{@js_dir}/#{@image_dir}/**/*.*")
|
95
|
+
@css_files = Rake::FileList.new
|
96
|
+
@css_files.include("#{@js_dir}/#{@css_dir}/**/*.css")
|
97
|
+
end
|
98
|
+
|
99
|
+
# Create the tasks defined by this task library.
|
100
|
+
def define
|
101
|
+
fail "Name required (or :noversion)" if @name.nil?
|
102
|
+
@name = nil if :noname == @name
|
103
|
+
|
104
|
+
|
105
|
+
desc "Build all the packages"
|
106
|
+
task :compile => :pack do
|
107
|
+
[images_dir, css_dir].each { |dir| mkdir_p("#{package_dir_path}/#{dir}") }
|
108
|
+
FileUtils.cp(image_files, package_images_path)
|
109
|
+
FileUtils.cp(css_files, package_css_path)
|
110
|
+
FileUtils.cp(package_files, package_dir_path)
|
111
|
+
end
|
112
|
+
|
113
|
+
desc "Force a rebuild of the package files"
|
114
|
+
task :recompile => [:clobber_compile, :compile]
|
115
|
+
|
116
|
+
desc "Remove compile products"
|
117
|
+
task :clobber_compile do
|
118
|
+
FileUtils.rm_r(package_dir_path) rescue nil
|
119
|
+
end
|
120
|
+
|
121
|
+
desc "Merge js files into one"
|
122
|
+
task :merge do
|
123
|
+
`#{sed_command}`
|
124
|
+
end
|
125
|
+
|
126
|
+
desc "Compress js files to min"
|
127
|
+
task :pack => :merge do
|
128
|
+
`#{packer_command}`
|
129
|
+
end
|
130
|
+
|
131
|
+
task :clobber => [:clobber_compile]
|
132
|
+
|
133
|
+
self
|
134
|
+
end
|
135
|
+
|
136
|
+
def package_dir_path
|
137
|
+
"#{package_dir}"
|
138
|
+
end
|
139
|
+
|
140
|
+
def package_css_path
|
141
|
+
"#{package_dir_path}/#{css_dir}"
|
142
|
+
end
|
143
|
+
|
144
|
+
def package_images_path
|
145
|
+
"#{package_dir_path}/#{images_dir}"
|
146
|
+
end
|
147
|
+
|
148
|
+
def package_js
|
149
|
+
"#{package_dir_path}/#{name}.js"
|
150
|
+
end
|
151
|
+
|
152
|
+
def packed_js
|
153
|
+
"#{package_dir_path}/#{name}.min.js"
|
154
|
+
end
|
155
|
+
|
156
|
+
def sed_command
|
157
|
+
"sed -e '1 s/^\xEF\xBB\xBF//' #{js_files} > #{package_js}"
|
158
|
+
end
|
159
|
+
|
160
|
+
def packer_command
|
161
|
+
"perl -I #{File.dirname(__FILE__)}/../packer #{File.dirname(__FILE__)}/../packer/jsPacker.pl -i #{package_js} -o #{packed_js} -e62"
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
@@ -3,10 +3,8 @@ require 'fileutils'
|
|
3
3
|
module JqueryPluginGen
|
4
4
|
class Generator
|
5
5
|
|
6
|
-
X = 'FI' + 'X'
|
7
|
-
|
8
6
|
def self.base_dirs
|
9
|
-
%w(src lib test
|
7
|
+
%w(src lib test src/images src/css test/data tasks)
|
10
8
|
end
|
11
9
|
|
12
10
|
def self.execute(args)
|
@@ -35,7 +33,6 @@ module JqueryPluginGen
|
|
35
33
|
|
36
34
|
details = args
|
37
35
|
files = {
|
38
|
-
"Makefile" => QuickTemplate.erb('Makefile', details),
|
39
36
|
"History.txt" => QuickTemplate.erb('History.txt', details),
|
40
37
|
"README.txt" => QuickTemplate.erb('README.txt', details),
|
41
38
|
"src/#{file_name}.js" => QuickTemplate.erb('src/plugin.js', details),
|
@@ -0,0 +1,13 @@
|
|
1
|
+
begin
|
2
|
+
%w[rake/clean].each { |f| require f }
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
+
%w[rake/clean].each { |f| require f }
|
6
|
+
end
|
7
|
+
|
8
|
+
CLEAN.include %w( build )
|
9
|
+
|
10
|
+
require 'jquery_plugin_gen/compiletask'
|
11
|
+
|
12
|
+
desc "Compile tasks"
|
13
|
+
Rake::CompileTask.new('jquery.plugin')
|
@@ -0,0 +1,13 @@
|
|
1
|
+
begin
|
2
|
+
%w[rake/packagetask].each { |f| require f }
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
+
%w[rake/packagetask].each { |f| require f }
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "Package"
|
9
|
+
Rake::PackageTask.new("#{PLUGIN}", "#{VERSION}") do |p|
|
10
|
+
p.need_tar = true
|
11
|
+
p.need_zip = true
|
12
|
+
p.package_files.include("build/**/*.*")
|
13
|
+
end
|
data/lib/jquery_plugin_gen.rb
CHANGED
data/lib/packer/Pack.pm
ADDED
@@ -0,0 +1,467 @@
|
|
1
|
+
#Pack (July 2005)
|
2
|
+
# Based on "Pack.js" by Dean Edwards <http://dean.edwards.name/>
|
3
|
+
# Ported to Perl by Rob Seiler, ELR Software Pty Ltd <http://www.elr.com.au>
|
4
|
+
# Copyright 2005. License <http://creativecommons.org/licenses/LGPL/2.1/>
|
5
|
+
|
6
|
+
package Pack;
|
7
|
+
use strict;
|
8
|
+
use Data::Dumper;
|
9
|
+
|
10
|
+
use ParseMaster;
|
11
|
+
|
12
|
+
# Package wide variable declarations
|
13
|
+
use vars qw/$VERSION $PM_VERSION
|
14
|
+
$_X_encodePrivate $_JSunpack $_JSdecode %baseLookup
|
15
|
+
$_X_encode10 $_X_encode36 $_X_encode62 $_X_encode95
|
16
|
+
$_JSencode10 $_JSencode36 $_JSencode62 $_JSencode95
|
17
|
+
@_X_parsers
|
18
|
+
$_X_script $_X_encoding $_X_fastDecode $_X_specialChars
|
19
|
+
/;
|
20
|
+
$VERSION = '024';
|
21
|
+
$PM_VERSION = $ParseMaster::VERSION;
|
22
|
+
|
23
|
+
# Package wide constants
|
24
|
+
my $X_IGNORE = q{$1};
|
25
|
+
my $X_ENCODE = q/\x24encode\(\x24count\)/; # NB: requires g modifier
|
26
|
+
my $PERL = 'perl'; # Flag to indicate whether we need to use one of our "internal" Perl encoding functions
|
27
|
+
my $JSCRIPT = 'jscript'; # or embed a pre-build JScript encoding function
|
28
|
+
########################################
|
29
|
+
|
30
|
+
##################
|
31
|
+
sub pack($$$$) { # require 4 arguments
|
32
|
+
##################
|
33
|
+
#print Dumper(@_);
|
34
|
+
($_X_script, $_X_encoding, $_X_fastDecode, $_X_specialChars) = @_;
|
35
|
+
# validate parameters (sort of!)
|
36
|
+
$_X_script .= "\n";
|
37
|
+
$_X_encoding = ($_X_encoding > 95) ? 95 : $_X_encoding;
|
38
|
+
|
39
|
+
@_X_parsers = (); # Reset parsers
|
40
|
+
|
41
|
+
####################
|
42
|
+
sub _X_pack($) { # require 1 argument
|
43
|
+
####################
|
44
|
+
# apply all parsing routines
|
45
|
+
my $X_script = shift;
|
46
|
+
for (my $i = 0; $i<scalar(@_X_parsers); $i++) {
|
47
|
+
my $X_parse = $_X_parsers[$i];
|
48
|
+
$X_script = &$X_parse($X_script);
|
49
|
+
}
|
50
|
+
return $X_script;
|
51
|
+
};
|
52
|
+
|
53
|
+
######################
|
54
|
+
sub _X_addParser { #
|
55
|
+
######################
|
56
|
+
# keep a list of parsing functions, they'll be executed all at once
|
57
|
+
my $X_parser = shift;
|
58
|
+
push (@_X_parsers,$X_parser);
|
59
|
+
}
|
60
|
+
|
61
|
+
#############################
|
62
|
+
sub _X_basicCompression { #
|
63
|
+
#############################
|
64
|
+
# zero encoding - just removal of white space and comments
|
65
|
+
my $X_script = shift;
|
66
|
+
my $parser = ParseMaster->new();
|
67
|
+
# make safe
|
68
|
+
$parser->escapeChar("\\");
|
69
|
+
# protect strings
|
70
|
+
$parser->add(q/'[^'\n\r]*'/, $X_IGNORE);
|
71
|
+
$parser->add(q/"[^"\n\r]*"/, $X_IGNORE);
|
72
|
+
# remove comments
|
73
|
+
$parser->add(q/\/\/[^\n\r]*[\n\r]/);
|
74
|
+
$parser->add(q/\/\*[^*]*\*+([^\/][^*]*\*+)*\//);
|
75
|
+
# protect regular expressions
|
76
|
+
$parser->add(q/\s+(\/[^\/\n\r\*][^\/\n\r]*\/g?i?)/, q{$2}); # IGNORE
|
77
|
+
$parser->add(q/[^\w\x24\/'"*)\?:]\/[^\/\n\r\*][^\/\n\r]*\/g?i?/, $X_IGNORE);
|
78
|
+
# remove: ;;; doSomething();
|
79
|
+
$parser->add(q/;;[^\n\r]+[\n\r]/) if ($_X_specialChars);
|
80
|
+
# remove redundant semi-colons
|
81
|
+
$parser->add(q/;+\s*([};])/, q{$2});
|
82
|
+
# remove white-space
|
83
|
+
$parser->add(q/(\b|\x24)\s+(\b|\x24)/, q{$2 $3});
|
84
|
+
$parser->add(q/([+\-])\s+([+\-])/, q{$2 $3});
|
85
|
+
$parser->add(q/\s+/, '');
|
86
|
+
# done
|
87
|
+
return $parser->exec($X_script);
|
88
|
+
}
|
89
|
+
|
90
|
+
###############################
|
91
|
+
sub _X_encodeSpecialChars { #
|
92
|
+
###############################
|
93
|
+
my $X_script = shift;
|
94
|
+
my $parser = ParseMaster->new();
|
95
|
+
# replace: $name -> n, $$name -> $$na
|
96
|
+
$parser->add(q/((\x24+)([a-zA-Z\x24_]+))(\d*)/,
|
97
|
+
sub {
|
98
|
+
my $X_offset = pop;
|
99
|
+
my @X_match = @_;
|
100
|
+
my $X_length = length($X_match[$X_offset+2]);
|
101
|
+
my $lengthnext = length($X_match[$X_offset+3]);
|
102
|
+
my $X_start = $X_length - ((($X_length - $lengthnext) > 0) ? ($X_length - $lengthnext) : 0);
|
103
|
+
my $str = $X_match[$X_offset+1];
|
104
|
+
$str = substr($str,$X_start,$X_length) . $X_match[$X_offset+4];
|
105
|
+
return "$str";
|
106
|
+
});
|
107
|
+
# replace: _name -> _0, double-underscore (__name) is ignored
|
108
|
+
my $X_regexp = q/\b_[A-Za-z\d]\w*/;
|
109
|
+
# build the word list
|
110
|
+
my %X_keywords = &_X_analyze($X_script, $X_regexp, $_X_encodePrivate);
|
111
|
+
#print Dumper(%X_keywords);
|
112
|
+
# quick ref
|
113
|
+
my $X_encoded = \$X_keywords{X_encoded}; # eg _private1 => '_0',_private2 => '_1';
|
114
|
+
#print Dumper($X_encoded);
|
115
|
+
$parser->add($X_regexp, sub {my $X_offset = pop; my @X_match = @_; return ${$X_encoded}->{$X_match[$X_offset]};});
|
116
|
+
|
117
|
+
return $parser->exec($X_script);
|
118
|
+
};
|
119
|
+
|
120
|
+
###########################
|
121
|
+
sub _X_encodeKeywords { #
|
122
|
+
###########################
|
123
|
+
my $X_script = shift;
|
124
|
+
# escape high-ascii values already in the script (i.e. in strings)
|
125
|
+
if ($_X_encoding > 62) {$X_script = &_X_escape95($X_script)};
|
126
|
+
# create the parser
|
127
|
+
my $parser = ParseMaster->new();
|
128
|
+
my $X_encode = &_X_getEncoder($_X_encoding,$PERL);
|
129
|
+
# for high-ascii, don't encode single character low-ascii
|
130
|
+
my $X_regexp = ($_X_encoding > 62) ? q/\w\w+/ : q/\w+/;
|
131
|
+
# build the word list
|
132
|
+
my %X_keywords = &_X_analyze($X_script, $X_regexp, $X_encode);
|
133
|
+
#print Dumper(%X_keywords);
|
134
|
+
my $X_encoded = \$X_keywords{X_encoded}; # eg alert => 2, function => 10 etc
|
135
|
+
# encode
|
136
|
+
$parser->add($X_regexp, sub {my $X_offset = pop; my @X_match = @_; return ${$X_encoded}->{$X_match[$X_offset]};});
|
137
|
+
# if encoded, wrap the script in a decoding function
|
138
|
+
|
139
|
+
return $X_script && _X_bootStrap(\$parser->exec($X_script), \%X_keywords);
|
140
|
+
}
|
141
|
+
|
142
|
+
####################
|
143
|
+
sub _X_analyze { #
|
144
|
+
####################
|
145
|
+
#print Dumper(@_);
|
146
|
+
my ($X_script, $X_regexp, $X_encode) = @_;
|
147
|
+
# analyse
|
148
|
+
# retreive all words in the script
|
149
|
+
my @X_all = $X_script =~ m/$X_regexp/g; # Save all captures in a list context
|
150
|
+
my %XX_sorted = (); # list of words sorted by frequency
|
151
|
+
my %XX_encoded = (); # dictionary of word->encoding
|
152
|
+
my %XX_protected = (); # instances of "protected" words
|
153
|
+
if (@X_all) {
|
154
|
+
my @X_unsorted = (); # same list, not sorted
|
155
|
+
my %X_protected = (); # "protected" words (dictionary of word->"word")
|
156
|
+
my %X_values = (); # dictionary of charCode->encoding (eg. 256->ff)
|
157
|
+
my %X_count = (); # word->count
|
158
|
+
my $i = scalar(@X_all); my $j = 0; my $X_word = '';
|
159
|
+
# count the occurrences - used for sorting later
|
160
|
+
do {
|
161
|
+
$X_word = '$' . $X_all[--$i];
|
162
|
+
if (!exists($X_count{$X_word})) {
|
163
|
+
$X_count{$X_word} = [0,$i]; # Store both the usage count and original array position (ie a secondary sort key)
|
164
|
+
$X_unsorted[$j] = $X_word;
|
165
|
+
# make a dictionary of all of the protected words in this script
|
166
|
+
# these are words that might be mistaken for encoding
|
167
|
+
$X_values{$j} = &$X_encode($j);
|
168
|
+
my $v = '$'.$X_values{$j};
|
169
|
+
$X_protected{$v} = $j++;
|
170
|
+
}
|
171
|
+
# increment the word counter
|
172
|
+
$X_count{$X_word}[0]++;
|
173
|
+
} while ($i);
|
174
|
+
#print Dumper (%X_values);
|
175
|
+
#print Dumper (@X_unsorted);
|
176
|
+
#print Dumper (%X_protected);
|
177
|
+
# prepare to sort the word list, first we must protect
|
178
|
+
# words that are also used as codes. we assign them a code
|
179
|
+
# equivalent to the word itself.
|
180
|
+
# e.g. if "do" falls within our encoding range
|
181
|
+
# then we store keywords["do"] = "do";
|
182
|
+
# this avoids problems when decoding
|
183
|
+
$i = scalar(@X_unsorted);
|
184
|
+
do {
|
185
|
+
$X_word = $X_unsorted[--$i];
|
186
|
+
if (exists($X_protected{$X_word})) {
|
187
|
+
$XX_sorted{$X_protected{$X_word}} = substr($X_word,1);
|
188
|
+
$XX_protected{$X_protected{$X_word}} = 1; # true
|
189
|
+
$X_count{$X_word}[0] = 0;
|
190
|
+
}
|
191
|
+
} while ($i);
|
192
|
+
#print Dumper (%XX_protected);
|
193
|
+
#print Dumper (%XX_sorted);
|
194
|
+
#print Dumper (%X_count);
|
195
|
+
# sort the words by frequency
|
196
|
+
# Sort with count a primary key and original array order as secondary key - which is apparently the default in javascript!
|
197
|
+
@X_unsorted = sort ({($X_count{$b}[0] - $X_count{$a}[0]) or ($X_count{$b}[1] <=> $X_count{$a}[1])} @X_unsorted);
|
198
|
+
#print Dumper (@X_unsorted) . "\n";
|
199
|
+
|
200
|
+
$j = 0;
|
201
|
+
# because there are "protected" words in the list
|
202
|
+
# we must add the sorted words around them
|
203
|
+
do {
|
204
|
+
if (!exists($XX_sorted{$i})) {$XX_sorted{$i} = substr($X_unsorted[$j++],1)}
|
205
|
+
$XX_encoded{$XX_sorted{$i}} = $X_values{$i};
|
206
|
+
} while (++$i < scalar(@X_unsorted));
|
207
|
+
}
|
208
|
+
#print Dumper(X_sorted => \%XX_sorted, X_encoded => \%XX_encoded, X_protected => \%XX_protected);
|
209
|
+
return (X_sorted => \%XX_sorted, X_encoded => \%XX_encoded, X_protected => \%XX_protected);
|
210
|
+
}
|
211
|
+
|
212
|
+
######################
|
213
|
+
sub _X_bootStrap { #
|
214
|
+
######################
|
215
|
+
# build the boot function used for loading and decoding
|
216
|
+
my ($X_packed, $X_keywords) = @_; # Reference arguments!
|
217
|
+
#print Dumper ($X_keywords) . "\n";
|
218
|
+
|
219
|
+
# $packed: the packed script - dereference and escape
|
220
|
+
$X_packed = "'" . &_X_escape($$X_packed) ."'";
|
221
|
+
|
222
|
+
my %sorted = %{$$X_keywords{X_sorted}}; # Dereference to local variables
|
223
|
+
my %protected = %{$$X_keywords{X_protected}}; # for simplicity
|
224
|
+
|
225
|
+
my @sorted = ();
|
226
|
+
foreach my $key (keys %sorted) {$sorted[$key] = $sorted{$key}}; # Convert hash to a standard list
|
227
|
+
|
228
|
+
# ascii: base for encoding
|
229
|
+
my $X_ascii = ((scalar(@sorted) > $_X_encoding) ? $_X_encoding : scalar(@sorted)) || 1;
|
230
|
+
|
231
|
+
# count: number of (unique {RS}) words contained in the script
|
232
|
+
my $X_count = scalar(@sorted); # Use $X_count for assigning $X_ascii
|
233
|
+
|
234
|
+
# keywords: list of words contained in the script
|
235
|
+
foreach my $i (keys %protected) {$sorted[$i] = ''}; # Blank out protected words
|
236
|
+
#print Dumper(@sorted) . "\n";
|
237
|
+
|
238
|
+
# convert from a string to an array - prepare keywords as a JScript string->array {RS}
|
239
|
+
$X_keywords = "'" . join('|',@sorted) . "'.split('|')";
|
240
|
+
|
241
|
+
# encode: encoding function (used for decoding the script)
|
242
|
+
my $X_encode = $_X_encoding > 62 ? $_JSencode95 : &_X_getEncoder($X_ascii,$JSCRIPT); # This is a JScript function (as a string)
|
243
|
+
$X_encode =~ s/_encoding/\x24ascii/g; $X_encode =~ s/arguments\.callee/\x24encode/g;
|
244
|
+
my $X_inline = '$count' . ($X_ascii > 10 ? '.toString($ascii)' : '');
|
245
|
+
|
246
|
+
# decode: code snippet to speed up decoding
|
247
|
+
my $X_decode = '';
|
248
|
+
if ($_X_fastDecode) {
|
249
|
+
# create the decoder
|
250
|
+
$X_decode = &_X_getFunctionBody($_JSdecode); # ie from the Javascript literal function
|
251
|
+
if ($_X_encoding > 62) {$X_decode =~ s/\\\\w/[\\xa1-\\xff]/g}
|
252
|
+
# perform the encoding inline for lower ascii values
|
253
|
+
elsif ($X_ascii < 36) {$X_decode =~ s/$X_ENCODE/$X_inline/g}
|
254
|
+
# special case: when $X_count==0 there ar no keywords. i want to keep
|
255
|
+
# the basic shape of the unpacking funcion so i'll frig the code...
|
256
|
+
if (!$X_count) {$X_decode =~ s/(\x24count)\s*=\s*1/$1=0/}
|
257
|
+
}
|
258
|
+
|
259
|
+
# boot function
|
260
|
+
my $X_unpack = $_JSunpack;
|
261
|
+
if ($_X_fastDecode) {
|
262
|
+
# insert the decoder
|
263
|
+
$X_unpack =~ s/\{/\{$X_decode;/;
|
264
|
+
}
|
265
|
+
$X_unpack =~ s/"/'/g;
|
266
|
+
if ($_X_encoding > 62) { # high-ascii
|
267
|
+
# get rid of the word-boundaries for regexp matches
|
268
|
+
$X_unpack =~ s/'\\\\b'\s*\+|\+\s*'\\\\b'//g; # Not checked! {RS}
|
269
|
+
}
|
270
|
+
if ($X_ascii > 36 || $_X_encoding > 62 || $_X_fastDecode) {
|
271
|
+
# insert the encode function
|
272
|
+
$X_unpack =~ s/\{/\{\$encode=$X_encode;/;
|
273
|
+
} else {
|
274
|
+
# perform the encoding inline
|
275
|
+
$X_unpack =~ s/$X_ENCODE/$X_inline/;
|
276
|
+
}
|
277
|
+
|
278
|
+
# arguments {RS} Do this before using &pack because &pack changes the pack parameters (eg $fastDecode) in Perl!!
|
279
|
+
my $X_params = "$X_packed,$X_ascii,$X_count,$X_keywords"; # Interpolate to comma separated string
|
280
|
+
if ($_X_fastDecode) {
|
281
|
+
# insert placeholders for the decoder
|
282
|
+
$X_params .= ',0,{}';
|
283
|
+
}
|
284
|
+
|
285
|
+
# pack the boot function too
|
286
|
+
$X_unpack = &pack($X_unpack,0,0,1);
|
287
|
+
|
288
|
+
# the whole thing
|
289
|
+
return "eval(" . $X_unpack . "(" . $X_params . "))\n";
|
290
|
+
};
|
291
|
+
|
292
|
+
#######################
|
293
|
+
sub _X_getEncoder { #
|
294
|
+
#######################
|
295
|
+
# mmm.. ..which one do i need ?? ({RS} Perl or JScript ??)
|
296
|
+
my ($X_ascii,$language) = @_;
|
297
|
+
my $perl_encoder = ($X_ascii > 10) ? ($X_ascii > 36) ? ($X_ascii > 62) ? $_X_encode95 : $_X_encode62 : $_X_encode36 : $_X_encode10;
|
298
|
+
my $jscript_encoder = ($X_ascii > 10) ? ($X_ascii > 36) ? ($X_ascii > 62) ? $_JSencode95 : $_JSencode62 : $_JSencode36 : $_JSencode10;
|
299
|
+
return ($language eq $JSCRIPT) ? $jscript_encoder : $perl_encoder;
|
300
|
+
};
|
301
|
+
|
302
|
+
#############################
|
303
|
+
# Perl versions of encoders #
|
304
|
+
#############################
|
305
|
+
# base10 zero encoding - characters: 0123456789
|
306
|
+
$_X_encode10 = sub {return &_encodeBase(shift,10)};
|
307
|
+
# base36 - characters: 0123456789abcdefghijklmnopqrstuvwxyz
|
308
|
+
$_X_encode36 = sub {return &_encodeBase(shift,36)};
|
309
|
+
# base62 - characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
|
310
|
+
$_X_encode62 = sub {return &_encodeBase(shift,62)};
|
311
|
+
# high-ascii values - characters: ����������������������������������������������������������������������������������������������
|
312
|
+
$_X_encode95 = sub {return &_encodeBase(shift,95)};
|
313
|
+
# Lookup character sets for baseN encoding
|
314
|
+
$baseLookup{10} = [(0..9)[0..9]]; # base 10
|
315
|
+
$baseLookup{36} = [(0..9,'a'..'z')[0..35]]; # base 36
|
316
|
+
$baseLookup{62} = [(0..9,'a'..'z','A'..'Z')[0..61]]; # base 62
|
317
|
+
$baseLookup{95} = (); for (my $i=0; $i<95; $i++) {$baseLookup{95}[$i] = chr($i+161)}; # base95 (high ascii)
|
318
|
+
#print Dumper(%baseLookup);
|
319
|
+
#####################
|
320
|
+
sub _encodeBase { #
|
321
|
+
#####################
|
322
|
+
# Generic base conversion function using defined lookup arrays (perl version only)
|
323
|
+
my ($X_charCode, $base) = @_;
|
324
|
+
my $X_encoded = '';
|
325
|
+
# Do we know this encoding?
|
326
|
+
if (exists ($baseLookup{$base})) {
|
327
|
+
if ($X_charCode == 0) {$X_encoded = $baseLookup{$base}[0]}
|
328
|
+
while($X_charCode > 0) {
|
329
|
+
$X_encoded = $baseLookup{$base}[$X_charCode % $base] . $X_encoded;
|
330
|
+
$X_charCode = int($X_charCode / $base);
|
331
|
+
}
|
332
|
+
}
|
333
|
+
else {$X_encoded = "$X_charCode"} # default is to return unchanged (ie as for base 10) if no baselookup is available
|
334
|
+
return $X_encoded;
|
335
|
+
};
|
336
|
+
|
337
|
+
#############################
|
338
|
+
$_X_encodePrivate = sub { #
|
339
|
+
#############################
|
340
|
+
# special _chars
|
341
|
+
my $X_charCode = shift;
|
342
|
+
return '_' . $X_charCode;
|
343
|
+
};
|
344
|
+
|
345
|
+
############################
|
346
|
+
sub _X_escape($script) { #
|
347
|
+
############################
|
348
|
+
# protect characters used by the parser
|
349
|
+
my $X_script = shift;
|
350
|
+
$X_script =~ s/([\\'])/\\$1/g;
|
351
|
+
return $X_script;
|
352
|
+
};
|
353
|
+
|
354
|
+
#####################
|
355
|
+
sub _X_escape95 { #
|
356
|
+
#####################
|
357
|
+
# protect high-ascii characters already in the script
|
358
|
+
my $X_script = shift;
|
359
|
+
$X_script =~ s/([\xa1-\xff])/sprintf("\\x%1x",ord($1))/eg;
|
360
|
+
return $X_script;
|
361
|
+
};
|
362
|
+
|
363
|
+
############################
|
364
|
+
sub _X_getFunctionBody { #
|
365
|
+
############################
|
366
|
+
# extract the body of a function (ie between opening/closing {}) - consistent with Dean Edwards approach
|
367
|
+
my $X_function = shift;
|
368
|
+
$X_function =~ m/^.*\{(.*)\}*$/sg; # Multiline, global (greedy)
|
369
|
+
my $start = index($X_function,'{');
|
370
|
+
my $end = rindex($X_function,'}');
|
371
|
+
$X_function = substr($X_function,($start+1),($end-1-$start));
|
372
|
+
return $X_function;
|
373
|
+
};
|
374
|
+
|
375
|
+
######################
|
376
|
+
sub _X_globalize { #
|
377
|
+
######################
|
378
|
+
# set the global flag on a RegExp (you have to create a new one) !!! Unused in perl version
|
379
|
+
# my $X_regexp = shift;
|
380
|
+
};
|
381
|
+
|
382
|
+
# build the parsing routine
|
383
|
+
&_X_addParser(\&_X_basicCompression);
|
384
|
+
&_X_addParser(\&_X_encodeSpecialChars) if ($_X_specialChars);
|
385
|
+
&_X_addParser(\&_X_encodeKeywords) if ($_X_encoding);
|
386
|
+
|
387
|
+
# go!
|
388
|
+
return &_X_pack($_X_script);
|
389
|
+
}
|
390
|
+
|
391
|
+
########################
|
392
|
+
# Javascript Literals #
|
393
|
+
########################
|
394
|
+
|
395
|
+
# JScript function "_unpack" - from DeanEdwards pack.js (NB: No ";" after final "}")
|
396
|
+
($_JSunpack) = <<'END_JSCRIPT_UNPACK';
|
397
|
+
/* unpacking function - this is the boot strap function */
|
398
|
+
/* data extracted from this packing routine is passed to */
|
399
|
+
/* this function when decoded in the target */
|
400
|
+
function($packed, $ascii, $count, $keywords, $encode, $decode) {
|
401
|
+
while ($count--)
|
402
|
+
if ($keywords[$count])
|
403
|
+
$packed = $packed.replace(new RegExp('\\b' + $encode($count) + '\\b', 'g'), $keywords[$count]);
|
404
|
+
/* RS_Debug = $packed; */ /* {RS} !!!!!!!!! */
|
405
|
+
return $packed;
|
406
|
+
}
|
407
|
+
END_JSCRIPT_UNPACK
|
408
|
+
|
409
|
+
# JScript function "_decode" - from DeanEdwards pack.js
|
410
|
+
($_JSdecode) = <<'END_JSCRIPT_DECODE';
|
411
|
+
/* code-snippet inserted into the unpacker to speed up decoding */
|
412
|
+
function() {
|
413
|
+
/* does the browser support String.replace where the */
|
414
|
+
/* replacement value is a function? */
|
415
|
+
if (!''.replace(/^/, String)) {
|
416
|
+
/* decode all the values we need */
|
417
|
+
while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count);
|
418
|
+
/* global replacement function */
|
419
|
+
$keywords = [function($encoded){return $decode[$encoded]}];
|
420
|
+
/* generic match */
|
421
|
+
$encode = function(){return'\\w+'};
|
422
|
+
/* reset the loop counter - we are now doing a global replace */
|
423
|
+
$count = 1;
|
424
|
+
}
|
425
|
+
};
|
426
|
+
END_JSCRIPT_DECODE
|
427
|
+
|
428
|
+
# JScript versions of encoders
|
429
|
+
($_JSencode10) = <<'END_JSCRIPT_ENCODE10';
|
430
|
+
/* zero encoding */
|
431
|
+
/* characters: 0123456789 */
|
432
|
+
function($charCode) {
|
433
|
+
return $charCode;
|
434
|
+
};
|
435
|
+
END_JSCRIPT_ENCODE10
|
436
|
+
|
437
|
+
($_JSencode36) = <<'END_JSCRIPT_ENCODE36';
|
438
|
+
/* inherent base36 support */
|
439
|
+
/* characters: 0123456789abcdefghijklmnopqrstuvwxyz */
|
440
|
+
function($charCode) {
|
441
|
+
return $charCode.toString(36);
|
442
|
+
};
|
443
|
+
END_JSCRIPT_ENCODE36
|
444
|
+
|
445
|
+
($_JSencode62) = <<'END_JSCRIPT_ENCODE62';
|
446
|
+
/* hitch a ride on base36 and add the upper case alpha characters */
|
447
|
+
/* characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ */
|
448
|
+
function($charCode) {
|
449
|
+
return ($charCode < _encoding ? '' : arguments.callee(parseInt($charCode / _encoding))) +
|
450
|
+
(($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36));
|
451
|
+
};
|
452
|
+
END_JSCRIPT_ENCODE62
|
453
|
+
|
454
|
+
($_JSencode95) = <<'END_JSCRIPT_ENCODE95';
|
455
|
+
/* use high-ascii values */
|
456
|
+
/* characters: ���������������������������������������������������������������������������������������������� */
|
457
|
+
function($charCode) {
|
458
|
+
return ($charCode < _encoding ? '' : arguments.callee($charCode / _encoding)) +
|
459
|
+
String.fromCharCode($charCode % _encoding + 161);
|
460
|
+
};
|
461
|
+
END_JSCRIPT_ENCODE95
|
462
|
+
|
463
|
+
###########
|
464
|
+
# END #
|
465
|
+
###########
|
466
|
+
1; # Pack #
|
467
|
+
###########
|
@@ -0,0 +1,207 @@
|
|
1
|
+
#ParseMaster (July 25 2005)
|
2
|
+
# Based on "ParseMaster.js" by Dean Edwards <http://dean.edwards.name/>
|
3
|
+
# Ported to Perl by Rob Seiler, ELR Software Pty Ltd <http://www.elr.com.au>
|
4
|
+
# Copyright 2005. License <http://creativecommons.org/licenses/LGPL/2.1/>
|
5
|
+
|
6
|
+
package ParseMaster;
|
7
|
+
use strict;
|
8
|
+
use Data::Dumper;
|
9
|
+
|
10
|
+
# Package wide variable declarations
|
11
|
+
use vars qw/$VERSION
|
12
|
+
@_X_escaped @_X_patterns
|
13
|
+
/;
|
14
|
+
|
15
|
+
$VERSION = '017';
|
16
|
+
|
17
|
+
# constants
|
18
|
+
my $X_EXPRESSION = 0;
|
19
|
+
my $X_REPLACEMENT = 1;
|
20
|
+
my $X_LENGTH = 2;
|
21
|
+
|
22
|
+
# re's used to determine nesting levels
|
23
|
+
my $X_GROUPS = qr/\(/o; # NB: Requires g modifier!
|
24
|
+
my $X_SUB_REPLACE = qr/\$\d/o;
|
25
|
+
my $X_INDEXED = qr/^\$\d+$/o;
|
26
|
+
my $XX_ESCAPE = qr/\\./o; # NB: Requires g modifier!
|
27
|
+
my $XX_DELETED = qr/\001[^\001]*\001/o; # NB: Requires g modifier!
|
28
|
+
my $DIGIT = qr/[^\D]/o; # Yep - this is a digit - contains no non-digits
|
29
|
+
|
30
|
+
# Constructor
|
31
|
+
sub new {
|
32
|
+
my $class = shift;
|
33
|
+
my $self = {};
|
34
|
+
@_X_escaped = (); # Re-initialize global for each instance
|
35
|
+
@_X_patterns = (); # Re-initialize global for each instance
|
36
|
+
# Instance variables - access by similarly named set/get functions
|
37
|
+
$self->{_ignoreCase_} = 0;
|
38
|
+
$self->{_escapeChar_} = '';
|
39
|
+
bless ($self, $class);
|
40
|
+
return $self;
|
41
|
+
}
|
42
|
+
|
43
|
+
sub ignoreCase {
|
44
|
+
my ($self, $value) = @_;
|
45
|
+
if (defined($value)) {
|
46
|
+
$self->{_ignoreCase_} = $value;
|
47
|
+
}
|
48
|
+
return $self->{_ignoreCase_};
|
49
|
+
}
|
50
|
+
|
51
|
+
sub escapeChar{
|
52
|
+
my ($self, $value) = @_;
|
53
|
+
if (defined($value)) {
|
54
|
+
$self->{_escapeChar_} = $value;
|
55
|
+
}
|
56
|
+
return $self->{_escapeChar_};
|
57
|
+
}
|
58
|
+
|
59
|
+
#######################
|
60
|
+
# Public Parsemaster functions
|
61
|
+
|
62
|
+
my $X_DELETE = sub(@$) {
|
63
|
+
my $X_offset = pop;
|
64
|
+
my @X_match = @_;
|
65
|
+
return (chr(001) . $X_match[$X_offset] . chr(001));
|
66
|
+
}; # NB semicolon required for closure!
|
67
|
+
|
68
|
+
# create and add a new pattern to the patterns collection
|
69
|
+
sub add {
|
70
|
+
my ($self, $expression, $X_replacement) = @_;
|
71
|
+
if (!$X_replacement) {$X_replacement = $X_DELETE};
|
72
|
+
|
73
|
+
# count the number of sub-expressions
|
74
|
+
my $temp = &_X_internalEscape($expression);
|
75
|
+
my $length = 1; # Always at least one because each pattern is itself a sub-expression
|
76
|
+
$length += $temp =~ s/$X_GROUPS//g; # One way to count the left capturing parentheses in the regexp string
|
77
|
+
|
78
|
+
# does the pattern deal with sub-expressions?
|
79
|
+
if ((ref($X_replacement) ne "CODE") && ($X_replacement =~ m/$X_SUB_REPLACE/)) {
|
80
|
+
if ($X_replacement =~ m/$X_INDEXED/) { # a simple lookup? (eg "$2")
|
81
|
+
# store the index (used for fast retrieval of matched strings)
|
82
|
+
$X_replacement = substr($X_replacement,1) - 1;
|
83
|
+
}
|
84
|
+
else { # a complicated lookup (eg "Hello $2 $1")
|
85
|
+
my $i = $length;
|
86
|
+
while ($i) { # Had difficulty getting Perl to do Dean's splitting and joining of strings containing $'s
|
87
|
+
my $str = '$a[$o+' . ($i-1) . ']'; # eg $a[$o+1]
|
88
|
+
$X_replacement =~ s/\$$i/$str/; # eg $2 $3 -> $a[$o+1] $a[$o+2]
|
89
|
+
$i--;
|
90
|
+
}
|
91
|
+
# build a function to do the lookup - returns interpolated string of array lookups
|
92
|
+
$X_replacement = eval('sub {my $o=pop; my @a=@_; return "' . $X_replacement . '"};');
|
93
|
+
}
|
94
|
+
}
|
95
|
+
else {}
|
96
|
+
# pass the modified arguments
|
97
|
+
&_X_add($expression || q/^$/, $X_replacement, $length);
|
98
|
+
}
|
99
|
+
|
100
|
+
# execute the global replacement
|
101
|
+
sub exec {
|
102
|
+
#print Dumper(@_X_patterns);
|
103
|
+
my ($self, $X_string) = @_;
|
104
|
+
my $escChar = $self->escapeChar();
|
105
|
+
my $ignoreCase = $self->ignoreCase();
|
106
|
+
my ($regexp,$captures) = &_getPatterns(); # Concatenated and parenthesized regexp eg '(regex1)|(regex2)|(regex3)' etc
|
107
|
+
$X_string = &_X_escape($X_string, $escChar);
|
108
|
+
if ($ignoreCase) {$X_string =~ s/$regexp/{&_X_replacement(&_matchVars($captures,\$X_string))}/gie} # Pass $X_String as a
|
109
|
+
else {$X_string =~ s/$regexp/{&_X_replacement(&_matchVars($captures,\$X_string))}/ge} # reference for speed
|
110
|
+
|
111
|
+
$X_string = &_X_unescape($X_string, $escChar);
|
112
|
+
$X_string =~ s/$XX_DELETED//g;
|
113
|
+
return $X_string;
|
114
|
+
}
|
115
|
+
|
116
|
+
sub _X_add {
|
117
|
+
push (@_X_patterns, [@_]); # Save each argument set as is into an array of arrays
|
118
|
+
}
|
119
|
+
|
120
|
+
# this is the global replace function (it's quite complicated)
|
121
|
+
sub _X_replacement {
|
122
|
+
my (@arguments) = @_;
|
123
|
+
#print Dumper (@arguments);
|
124
|
+
if ($arguments[0] le '') {return ''}
|
125
|
+
# Dereference last index (source String) here - faster than in _matchVars (maybe not needed at all?)
|
126
|
+
$arguments[$#arguments] = ${$arguments[$#arguments]};
|
127
|
+
my $i = 1;
|
128
|
+
# loop through the patterns
|
129
|
+
for (my $j=0; $j<scalar(@_X_patterns); $j++) { # Loop through global all @_X_patterns
|
130
|
+
my @X_pattern = @{$_X_patterns[$j]};
|
131
|
+
# do we have a result? NB: "if ($arguments[$i])" as in Dean's Javascript is false for the value 0!!!
|
132
|
+
if ((defined $arguments[$i]) && ($arguments[$i] gt '')) {
|
133
|
+
my $X_replacement = $X_pattern[$X_REPLACEMENT];
|
134
|
+
# switch on type of $replacement
|
135
|
+
if (ref($X_replacement) eq "CODE") { # function
|
136
|
+
return &$X_replacement(@arguments,$i);
|
137
|
+
}
|
138
|
+
elsif ($X_replacement =~ m/$DIGIT/) { # number (contains no non-digits)
|
139
|
+
return $arguments[$X_replacement + $i];
|
140
|
+
}
|
141
|
+
else { # default
|
142
|
+
return $X_replacement; # default
|
143
|
+
}
|
144
|
+
} # skip over references to sub-expressions
|
145
|
+
else {$i += $X_pattern[$X_LENGTH]}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
#######################
|
150
|
+
# Private functions
|
151
|
+
#######################
|
152
|
+
|
153
|
+
# encode escaped characters
|
154
|
+
sub _X_escape {
|
155
|
+
my ($X_string, $X_escapeChar) = @_;
|
156
|
+
if ($X_escapeChar) {
|
157
|
+
my $re = '\\'.$X_escapeChar.'(.)';
|
158
|
+
$X_string =~ s/$re/{push(@_X_escaped,$1); $X_escapeChar}/ge;
|
159
|
+
}
|
160
|
+
return $X_string;
|
161
|
+
}
|
162
|
+
|
163
|
+
# decode escaped characters
|
164
|
+
sub _X_unescape {
|
165
|
+
my ($X_string, $X_escapeChar) = @_;
|
166
|
+
if ($X_escapeChar) { # We'll only do this if there is an $X_escapeChar!
|
167
|
+
my $re = '\\'.$X_escapeChar;
|
168
|
+
$X_string =~ s/$re/{$X_escapeChar . (shift(@_X_escaped))}/ge; # Don't use Dean Edwards as below 'or' here - because zero will return ''!
|
169
|
+
# $X_string =~ s/$re/{$X_escapeChar . (shift(@_X_escaped) || '')}/ge;
|
170
|
+
}
|
171
|
+
return $X_string;
|
172
|
+
}
|
173
|
+
|
174
|
+
sub _X_internalEscape {
|
175
|
+
my ($string) = shift;
|
176
|
+
$string =~ s/$XX_ESCAPE//g;
|
177
|
+
return $string;
|
178
|
+
}
|
179
|
+
|
180
|
+
# Builds an array of match variables to (approximately) emulate that available in Javascript String.replace()
|
181
|
+
sub _matchVars {
|
182
|
+
my ($m,$sref) = @_;
|
183
|
+
my @args = (1..$m); # establish the number potential memory variables
|
184
|
+
my @mv = map {eval("\$$_")} @args; # matchvarv[1..m] = the memory variables $1 .. $m
|
185
|
+
unshift (@mv, $&); # matchvar[0] = the substring that matched
|
186
|
+
push (@mv, length($`)); # matchvar[m+1] = offset within the source string where the match occurred (= length of prematch string)
|
187
|
+
push (@mv, $sref); # matchvar[m+2] = reference to full source string (dereference in caller if/when needed)
|
188
|
+
#print Dumper (@mv);
|
189
|
+
return @mv;
|
190
|
+
}
|
191
|
+
|
192
|
+
sub _getPatterns {
|
193
|
+
my @Patterns = ();
|
194
|
+
my $lcp = 0;
|
195
|
+
for (my $i=0; $i<scalar(@_X_patterns); $i++) { # Loop through global all @_patterns
|
196
|
+
push (@Patterns, $_X_patterns[$i][$X_EXPRESSION]); # accumulate the expressions
|
197
|
+
$lcp += $_X_patterns[$i][$X_LENGTH]; # sum the left capturing parenthesis counts
|
198
|
+
}
|
199
|
+
my $str = "(" . join(')|(',@Patterns). ")"; # enclose each pattern in () separated by "|"
|
200
|
+
return ($str, $lcp);
|
201
|
+
}
|
202
|
+
|
203
|
+
##################
|
204
|
+
# END #
|
205
|
+
##################
|
206
|
+
1; # ParseMaster #
|
207
|
+
##################
|
@@ -0,0 +1,163 @@
|
|
1
|
+
#!perl
|
2
|
+
#jsPacker (July 2005)
|
3
|
+
#
|
4
|
+
use strict;
|
5
|
+
use Pack;
|
6
|
+
use vars qw($PROGNAME $VERSION
|
7
|
+
$opt_h $opt_q $opt_v $opt_i $opt_o $opt_e $opt_f $opt_s);
|
8
|
+
use Getopt::Std;
|
9
|
+
|
10
|
+
$PROGNAME = $0;
|
11
|
+
$VERSION = '1.00b';
|
12
|
+
|
13
|
+
my $Description = 'A JavaScript Compressor/Obfuscator';
|
14
|
+
my $Version = "v$VERSION\[p$Pack::VERSION-pm$Pack::PM_VERSION\]";
|
15
|
+
|
16
|
+
# "English" versions of settings
|
17
|
+
my %ENCODINGS = (0=>'None', 10=>'Decimal', 36=>'Normal', 62=>'Normal', 95=>'High-ascii');
|
18
|
+
my %SETTINGS = (0=>'No', 1=>'Yes');
|
19
|
+
|
20
|
+
exit(0) if &main();
|
21
|
+
exit(1);
|
22
|
+
|
23
|
+
################
|
24
|
+
# Sub-routines #
|
25
|
+
################
|
26
|
+
# Main program
|
27
|
+
sub main {
|
28
|
+
# Get command line options
|
29
|
+
&getopts('hqvfsi:o:e:');
|
30
|
+
$opt_h ||= 0; # $opt_h shows usage and exits
|
31
|
+
$opt_q ||= 0; # $opt_q sets quiet mode (no stdout output)
|
32
|
+
$opt_v ||= 0; # $opt_v shows version and exits
|
33
|
+
$opt_i ||= ''; # $opt_i is input file. Required!
|
34
|
+
$opt_o ||= ''; # $opt_o is output file. If not set, use standard output
|
35
|
+
$opt_e ||= 0; # $opt_e encoding level (0,10,36,62,95)
|
36
|
+
$opt_f ||= 0; # $opt_f use fast decoding
|
37
|
+
$opt_s ||= 0; # $opt_x use special characters
|
38
|
+
|
39
|
+
# Display help or version if requested
|
40
|
+
if ($opt_h) {&usage("help")}
|
41
|
+
if ($opt_v) {&usage("version")}
|
42
|
+
|
43
|
+
# Constrain encoding level, fastdecoding and specialcharacters to allowed limits
|
44
|
+
$opt_e = ($opt_e > 0) ? ($opt_e > 10) ? ($opt_e > 36) ? ($opt_e > 62) ? 95 : 62 : 36 : 10 : 0;
|
45
|
+
$opt_f = ($opt_f) ? 1 : 0;
|
46
|
+
$opt_s = ($opt_s) ? 1 : 0;
|
47
|
+
|
48
|
+
# Do the job if an input file is specified
|
49
|
+
if ($opt_i) {
|
50
|
+
# Read the source script
|
51
|
+
my $script = &readInputFile($opt_i);
|
52
|
+
# Pack the source script
|
53
|
+
my $packedscript = &Pack::pack($script,$opt_e, $opt_f, $opt_s);
|
54
|
+
# Show what happened (if not in quiet mode)
|
55
|
+
if (!$opt_q) {showJobDetails($opt_i, $opt_o, $opt_e, $opt_f,$opt_s,\$script,\$packedscript)}
|
56
|
+
# Output the packed script
|
57
|
+
if ($opt_o) {&writeOutputFile($opt_o,\$packedscript)} # to output file if specifed
|
58
|
+
else {print "$packedscript"} # otherwise to STDOUT
|
59
|
+
}
|
60
|
+
else { # If no input file is specified, display help
|
61
|
+
&usage();
|
62
|
+
}
|
63
|
+
return(1);
|
64
|
+
}
|
65
|
+
|
66
|
+
######################
|
67
|
+
sub showJobDetails { #
|
68
|
+
######################
|
69
|
+
# Show details of input/output files, settings and compression ratio
|
70
|
+
my ($inputfile, $outputfile,
|
71
|
+
$encoding, $fastdecode, $specialchars,
|
72
|
+
$instringref, $outstringref) = @_;
|
73
|
+
print "$PROGNAME $Version\n";
|
74
|
+
print "\tSource file : ";
|
75
|
+
print "\"$inputfile\"\n";
|
76
|
+
print (($outputfile) ? ("\tOutput file : \"$outputfile\"\n") : ''); # Print only if output is going to a file
|
77
|
+
print "\tSettings : encoding=$ENCODINGS{$encoding} fastdecode=$SETTINGS{$fastdecode} specialchars=$SETTINGS{$specialchars}\n";
|
78
|
+
print "\tCompression : " . &compressionRatio($instringref, $outstringref). "\n\n";
|
79
|
+
|
80
|
+
}
|
81
|
+
|
82
|
+
#####################
|
83
|
+
sub readInputFile { #
|
84
|
+
#####################
|
85
|
+
# Read content (source script) from input file
|
86
|
+
my $filename = shift;
|
87
|
+
open(FH, $filename) || die "Error!!! Problem opening input file \"$filename\"!\n";
|
88
|
+
my @content = <FH>;
|
89
|
+
close(FH);
|
90
|
+
return join('',@content);
|
91
|
+
}
|
92
|
+
|
93
|
+
#######################
|
94
|
+
sub writeOutputFile { #
|
95
|
+
#######################
|
96
|
+
# Write content (packed script) to output file
|
97
|
+
my ($filename,$refcontent) = @_;
|
98
|
+
open(FH, ">$filename") || die "Error!!! Problem opening output file \"$filename\"\n";
|
99
|
+
print(FH $$refcontent);
|
100
|
+
close(FH);
|
101
|
+
}
|
102
|
+
|
103
|
+
########################
|
104
|
+
sub compressionRatio { #
|
105
|
+
########################
|
106
|
+
# Calculate the ratio of output string to input string
|
107
|
+
my ($sref1,$sref2) = @_;
|
108
|
+
my $ratio = (length($$sref2) / (length($$sref1)||1));
|
109
|
+
$ratio = sprintf "%.2f", $ratio;
|
110
|
+
return $ratio;
|
111
|
+
}
|
112
|
+
|
113
|
+
#############
|
114
|
+
sub usage { #
|
115
|
+
#############
|
116
|
+
# Inform user about usage, version and exit
|
117
|
+
my $showusage = 0;
|
118
|
+
my $showversion = 0;
|
119
|
+
my $params = shift;
|
120
|
+
if (defined $params) {
|
121
|
+
if ($params eq "help") {$showusage = 1;}
|
122
|
+
elsif ($params eq "version") {$showversion = 1;}
|
123
|
+
else {$showusage = 1;}
|
124
|
+
}
|
125
|
+
else {$showversion = 1;}
|
126
|
+
if ($showversion) {
|
127
|
+
print<<EOT;
|
128
|
+
|
129
|
+
$PROGNAME $Version
|
130
|
+
$Description
|
131
|
+
\tBased on "Packer.js" by Dean Edwards <http://dean.edwards.name/>
|
132
|
+
\tPorted to Perl by Rob Seiler, ELR Software Pty Ltd <http://www.elr.com.au>
|
133
|
+
\tCopyright 2005. License <http://creativecommons.org/licenses/LGPL/2.1/>
|
134
|
+
Use "$PROGNAME -h" for options
|
135
|
+
EOT
|
136
|
+
exit(1);
|
137
|
+
}
|
138
|
+
if ($showusage) {
|
139
|
+
print<<EOT;
|
140
|
+
|
141
|
+
$PROGNAME $Version
|
142
|
+
$Description
|
143
|
+
Usage:
|
144
|
+
\t$PROGNAME -i inputfile [-o outputfile] [-eX] [-f] [-s] [-qvh]\n
|
145
|
+
\t-i <inputfile> (eg -i myscript.js)
|
146
|
+
\t-o <outputfile> (eg -o myscript-p.js)
|
147
|
+
\t-eN <encoding> [0=None 10=Numeric 62=Normal(alphanumeric) 95=High-ascii]
|
148
|
+
\t-f <fast decode>
|
149
|
+
\t-s <special characters>
|
150
|
+
\t-q quiet mode
|
151
|
+
\t-v version
|
152
|
+
\t-h help
|
153
|
+
|
154
|
+
Examples:
|
155
|
+
\t$PROGNAME -i myscript.js
|
156
|
+
\t$PROGNAME -i myscript.js -o packed.js
|
157
|
+
\t$PROGNAME -i myscript.js -o packed.js -e10 -f -s
|
158
|
+
\t$PROGNAME -i myscript.js -e95 -fsq > packed.js
|
159
|
+
|
160
|
+
EOT
|
161
|
+
exit(1);
|
162
|
+
}
|
163
|
+
}
|
data/lib/templates/Rakefile.erb
CHANGED
@@ -3,7 +3,13 @@ require 'rubygems' unless ENV['NO_RUBYGEMS']
|
|
3
3
|
|
4
4
|
require 'jquery_plugin_gen/tasks'
|
5
5
|
|
6
|
-
|
6
|
+
PLUGIN = '<%= details[:project] %>'
|
7
|
+
VERSION = '<%= details[:version] %>'
|
8
|
+
|
9
|
+
# Load your custom tasks from tasks folder
|
10
|
+
Dir.glob("tasks/*.rake").each{ |t| import t rescue nil }
|
11
|
+
|
12
|
+
# Alternatively, create any new tasks here
|
7
13
|
# task :default => [:task, :dependencies] do
|
8
14
|
# yours
|
9
15
|
# end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jqueryplugingen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- toddb
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-07 00:00:00 +12:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -211,14 +211,19 @@ files:
|
|
211
211
|
- jQuery-Plugin-Generator.tmproj
|
212
212
|
- lib/jqp/cli.rb
|
213
213
|
- lib/jquery_plugin_gen.rb
|
214
|
+
- lib/jquery_plugin_gen/compiletask.rb
|
214
215
|
- lib/jquery_plugin_gen/generator.rb
|
215
216
|
- lib/jquery_plugin_gen/quick_template.rb
|
217
|
+
- lib/jquery_plugin_gen/support/build.rake
|
216
218
|
- lib/jquery_plugin_gen/support/bundles.rake
|
217
219
|
- lib/jquery_plugin_gen/support/jquery.rake
|
220
|
+
- lib/jquery_plugin_gen/support/package.rake
|
218
221
|
- lib/jquery_plugin_gen/tasks.rb
|
222
|
+
- lib/packer/Pack.pm
|
223
|
+
- lib/packer/ParseMaster.pm
|
224
|
+
- lib/packer/jsPacker.pl
|
219
225
|
- lib/templates/History.txt.erb
|
220
226
|
- lib/templates/README.txt.erb
|
221
|
-
- lib/templates/Makefile.erb
|
222
227
|
- lib/templates/Rakefile.erb
|
223
228
|
- lib/templates/example.html.erb
|
224
229
|
- lib/templates/src/plugin.js.erb
|
data/lib/templates/Makefile.erb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
VERSION = <%= details[:version] %>
|
2
|
-
|
3
|
-
SRC_DIR = src
|
4
|
-
BUILD_DIR = build
|
5
|
-
DIST_DIR = dist/${VERSION}
|
6
|
-
|
7
|
-
JS_FILES = ${SRC_DIR}/<%= details[:project] %>.js
|
8
|
-
|
9
|
-
RELEASE_FILES = README.txt HISTORY.txt
|
10
|
-
IMAGES = ${SRC_DIR}/images/*
|
11
|
-
CSS = ${SRC_DIR}/css/*
|
12
|
-
|
13
|
-
IMAGES_DIST = ${BUILD_DIR}/images
|
14
|
-
CSS_DIST = ${BUILD_DIR}/css
|
15
|
-
|
16
|
-
WE = ${BUILD_DIR}/jquery.<%= details[:project] %>.js
|
17
|
-
WE_PACK = ${BUILD_DIR}/jquery.<%= details[:project] %>.pack.js
|
18
|
-
|
19
|
-
WE_ARCH = ${DIST_DIR}/jquery.<%= details[:project] %>.tar.gz
|
20
|
-
WE_RELEASE = ${DIST_DIR}/jquery.<%= details[:project] %>-${VERSION}.tar.gz
|
21
|
-
|
22
|
-
MERGE = sed -e '1 s/^\xEF\xBB\xBF//' ${JS_FILES} > ${WE}
|
23
|
-
PACKER = perl -I$ lib/packer lib/packer/jsPacker.pl -i ${WE} -o ${WE_PACK} -e62
|
24
|
-
|
25
|
-
all: archive
|
26
|
-
|
27
|
-
merge:
|
28
|
-
|
29
|
-
@@echo " - Cleaning Build dir " ${BUILD_DIR}
|
30
|
-
@@rm -rf ${BUILD_DIR}
|
31
|
-
@@mkdir -p ${BUILD_DIR}
|
32
|
-
|
33
|
-
@@echo "Building" ${WE}
|
34
|
-
|
35
|
-
@@echo " - Merging files"
|
36
|
-
@@${MERGE}
|
37
|
-
|
38
|
-
@@echo ${WE} "- built"
|
39
|
-
@@echo
|
40
|
-
|
41
|
-
pack: merge
|
42
|
-
@@echo " - Packing " ${WE_PACK}
|
43
|
-
|
44
|
-
@@echo "Compressing using Packer"
|
45
|
-
@@${PACKER}
|
46
|
-
|
47
|
-
@@echo
|
48
|
-
|
49
|
-
archive: pack
|
50
|
-
|
51
|
-
@@echo " - Cleaning Build dir " ${DIST_DIR}
|
52
|
-
@@rm -rf ${DIST_DIR}
|
53
|
-
@@mkdir -p ${DIST_DIR}
|
54
|
-
|
55
|
-
@@echo "- Making archive" ${WE_RELEASE}
|
56
|
-
|
57
|
-
@@echo "Making DIST dir" ${IMAGES_DIST} ${CSS_DIST}
|
58
|
-
@@mkdir -p ${IMAGES_DIST} ${CSS_DIST}
|
59
|
-
|
60
|
-
@@echo " - Coping CSS and images"
|
61
|
-
# @@cp -R -f ${IMAGES} ${IMAGES_DIST}
|
62
|
-
@@cp -R -f ${CSS} ${CSS_DIST}
|
63
|
-
@@cp -f ${RELEASE_FILES} ${BUILD_DIR}
|
64
|
-
|
65
|
-
@@echo " - Creating release"
|
66
|
-
@@tar -cjf ${WE_RELEASE} ${BUILD_DIR}
|
67
|
-
|
68
|
-
@@echo "Building" ${WE_ARCH}
|
69
|
-
|
70
|
-
@@echo " - Creating archive"
|
71
|
-
@@rm -f ${WE_ARCH}
|
72
|
-
@@tar --exclude '.DS_Store ._' -czf ${WE_ARCH} .
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|