front-compiler 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +14 -0
- data/LICENSE +20 -0
- data/README +174 -0
- data/Rakefile +82 -0
- data/bin/frontcc +53 -0
- data/init.rb +25 -0
- data/lib/front-compiler.rb +5 -0
- data/lib/front_compiler/css_source/nested_styles.rb +72 -0
- data/lib/front_compiler/css_source.rb +42 -0
- data/lib/front_compiler/html_compactor.rb +24 -0
- data/lib/front_compiler/java_script/logic_compactor.rb +135 -0
- data/lib/front_compiler/java_script/names_compactor.rb +142 -0
- data/lib/front_compiler/java_script/self_builder.rb +137 -0
- data/lib/front_compiler/java_script.rb +53 -0
- data/lib/front_compiler/source_code.rb +105 -0
- data/lib/front_compiler.rb +59 -0
- data/lib/front_compiler_helper.rb +45 -0
- data/spec/lib/front_compiler/css_source/nested_styles_spec.rb.rb +65 -0
- data/spec/lib/front_compiler/css_source_spec.rb +111 -0
- data/spec/lib/front_compiler/html_compactor_spec.rb +41 -0
- data/spec/lib/front_compiler/java_script/logic_compactor_spec.rb +363 -0
- data/spec/lib/front_compiler/java_script/names_compactor_spec.rb +219 -0
- data/spec/lib/front_compiler/java_script/self_builder_spec.rb +253 -0
- data/spec/lib/front_compiler/java_script_spec.rb +60 -0
- data/spec/lib/front_compiler/source_code_spec.rb +26 -0
- data/spec/lib/front_compiler_helper_spec.rb +34 -0
- data/spec/lib/front_compiler_spec.rb +36 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +7 -0
- metadata +82 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
* 1.0.6 (December 14, 2009) - Nikolay V. Nemshilov aka St.
|
2
|
+
* rubygem is now available
|
3
|
+
* console util was added
|
4
|
+
|
5
|
+
* 1.0.2 (April 25, 2009) - Nikolay V. Nemshilov aka St.
|
6
|
+
* Tokens negotiation process update
|
7
|
+
* The self-build script enhancement
|
8
|
+
|
9
|
+
* 1.0.0 (April 5, 2009) - Nikolay V. Nemshilov aka St.
|
10
|
+
|
11
|
+
* The Self-Build Feature was implemented
|
12
|
+
* Missed semicolons restoration feature added
|
13
|
+
* Documentation updates
|
14
|
+
* Tagged the source as version 1.0.0
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Nikolay V. Nemshilov
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
Welcome!
|
2
|
+
========
|
3
|
+
|
4
|
+
FrontCompiler is a simple collection of compactors for the JavaScript,
|
5
|
+
CSS and HTML source code. It removes trailing whitespaces, comments and
|
6
|
+
transformates the local variables to make the sourcecode shorter.
|
7
|
+
|
8
|
+
For JavaScript, it can create a more compressed self-building script
|
9
|
+
for your code, see the description below.
|
10
|
+
|
11
|
+
The library can be used as a plugin for rails. See description below.
|
12
|
+
|
13
|
+
|
14
|
+
RubyGem and Console tool
|
15
|
+
========================
|
16
|
+
|
17
|
+
FrontCompiler is now available as a rubygem at the gemcutter service
|
18
|
+
|
19
|
+
gem sources -a http://gemcutter.org
|
20
|
+
gem install front-compiler
|
21
|
+
|
22
|
+
With the rubygem you'll have a console tool called 'frontcc'
|
23
|
+
|
24
|
+
$ frontcc file0.js file1.js file2.js file3.js
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Basic Usage
|
29
|
+
===========
|
30
|
+
|
31
|
+
It's pretty simple
|
32
|
+
|
33
|
+
@c = FrontCompiler.new
|
34
|
+
|
35
|
+
@compact_js = @c.compact_js(File.open('src/something.js', 'r'));
|
36
|
+
@compact_css = @c.compact_css(File.open('src/something.css', 'r'));
|
37
|
+
@compact_html = @c.compact_html(File.open('src/something.css', 'r'));
|
38
|
+
|
39
|
+
or shorter
|
40
|
+
|
41
|
+
@compact_js = @c.compact_file('src/something.js');
|
42
|
+
@compact_css = @c.compact_file('src/something.css');
|
43
|
+
@compact_html = @c.compact_file('src/something.css');
|
44
|
+
|
45
|
+
or you can compact several files at once like that
|
46
|
+
|
47
|
+
@library_code = @c.compact_files(%w{
|
48
|
+
src/lib.js
|
49
|
+
src/lib/something.js
|
50
|
+
src/lib/another.js
|
51
|
+
})
|
52
|
+
|
53
|
+
Same for the other file-types
|
54
|
+
|
55
|
+
CSS Inlining
|
56
|
+
============
|
57
|
+
|
58
|
+
With the tool you can convert your css source in some javascript
|
59
|
+
definition so you could put the styles in the same file as your
|
60
|
+
javascript and have -1 (or several) hits to your sever.
|
61
|
+
|
62
|
+
File('public/javascripts/all_in_one.js', 'w') do |file|
|
63
|
+
file.write @c.compact_files(%w{
|
64
|
+
public/javascripts/prototype.js
|
65
|
+
public/javascripts/effects.js
|
66
|
+
public/javascripts/application.js
|
67
|
+
})
|
68
|
+
|
69
|
+
file.write @c.inline_css(
|
70
|
+
File.open('public/stylesheets/application.css').read
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
Now you have a single javascript file which contains both, javascript
|
75
|
+
and the application stylesheets in one.
|
76
|
+
|
77
|
+
NOTE: if the user have JavaScript switched off, then he won't see the
|
78
|
+
styles.
|
79
|
+
|
80
|
+
Nested CSS Handling
|
81
|
+
===================
|
82
|
+
|
83
|
+
Nested CSS is a feature when you describe your css with nested constructions
|
84
|
+
like that
|
85
|
+
|
86
|
+
div.article {
|
87
|
+
div.title {
|
88
|
+
font-weight: bold;
|
89
|
+
span.date {
|
90
|
+
color: pink;
|
91
|
+
}
|
92
|
+
}
|
93
|
+
div.text {
|
94
|
+
background: #EEE;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
Which means the same as the following code.
|
99
|
+
|
100
|
+
div.article div.title {
|
101
|
+
font-weight: bold;
|
102
|
+
}
|
103
|
+
div.article div.title span.date {
|
104
|
+
color: pink
|
105
|
+
}
|
106
|
+
div.article div.text {
|
107
|
+
background: #EEE;
|
108
|
+
}
|
109
|
+
|
110
|
+
Nested styles are more clean, simple and follows the DRY principle. The only
|
111
|
+
little problem, there's no browsers which support the feature yet. But the idea
|
112
|
+
is alive and people like it. So we have added the feature emulation in the
|
113
|
+
project.
|
114
|
+
|
115
|
+
You can create nested css descriptions and then when you compress your css
|
116
|
+
with FrontCompiler, it will be automatically converted in a correct css source
|
117
|
+
which the browsers can understand.
|
118
|
+
|
119
|
+
|
120
|
+
Rails Usage
|
121
|
+
===========
|
122
|
+
|
123
|
+
The project can be used as a usual rails plugin. Just clone the
|
124
|
+
project into your vendor/plugins/front_compiler directory and you will
|
125
|
+
have the following methods aviable both in your controllers and
|
126
|
+
templates
|
127
|
+
|
128
|
+
|
129
|
+
* compact_files(list) - compacts the files fromt the given list and
|
130
|
+
puts them in a single string. You can specify
|
131
|
+
a list of file-names here.
|
132
|
+
|
133
|
+
* compact_file(file) - compacts the given file (can be a file-name)
|
134
|
+
|
135
|
+
* compact_js(source) - returns compacted version of the given source
|
136
|
+
* compact_css(source)
|
137
|
+
* compact_html(source)
|
138
|
+
|
139
|
+
* inline_css(source) - converts the css-source in javascript
|
140
|
+
* inline_css_file(file) - converts the given css-file in a javascript
|
141
|
+
source (can be a file-name)
|
142
|
+
|
143
|
+
|
144
|
+
Self-Build Scripts
|
145
|
+
==================
|
146
|
+
|
147
|
+
FrontCompiler provides you another nice feature, the scripts self-building.
|
148
|
+
The idea is that it will convert your code into a string, replace all long
|
149
|
+
tokens by short replacements and then compile a javascript code which will
|
150
|
+
replace all the tokens back on the user's browser side.
|
151
|
+
|
152
|
+
This will give you extra 20-40% compression over the existing FrontCompiler
|
153
|
+
compression.
|
154
|
+
|
155
|
+
The browser side restoration happens pretty quick and almost invisible for
|
156
|
+
the end user.
|
157
|
+
|
158
|
+
As the feature actually change the code and requires the end script to be
|
159
|
+
executed with JavaScript, it won't work if you use JSON as a media format
|
160
|
+
without actual evaluating it as a javascript code. For this reason, to use
|
161
|
+
the feature, you need to call it specifically.
|
162
|
+
|
163
|
+
@c = FrontCompiler.new
|
164
|
+
@c.compact_js(File.open('src/something.js', 'r')).create_self_build;
|
165
|
+
|
166
|
+
If you want FrontCompiler to create self-builds by default you can just
|
167
|
+
uncomment the call in the java_script.rb file.
|
168
|
+
|
169
|
+
|
170
|
+
Enjoy!
|
171
|
+
|
172
|
+
--
|
173
|
+
The code released under terms of the MIT License
|
174
|
+
Copyright (C) 2008-2009 Nikolay V. Nemshilov aka St.
|
data/Rakefile
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/clean"
|
3
|
+
require "rake/gempackagetask"
|
4
|
+
require "rake/rdoctask"
|
5
|
+
require "rake/testtask"
|
6
|
+
require "spec/rake/spectask"
|
7
|
+
require "fileutils"
|
8
|
+
|
9
|
+
def __DIR__
|
10
|
+
File.dirname(__FILE__)
|
11
|
+
end
|
12
|
+
|
13
|
+
include FileUtils
|
14
|
+
|
15
|
+
NAME = "front_compiler"
|
16
|
+
|
17
|
+
require "lib/front_compiler"
|
18
|
+
require "lib/front_compiler_helper"
|
19
|
+
|
20
|
+
def sudo
|
21
|
+
ENV['FC_SUDO'] ||= "sudo"
|
22
|
+
sudo = windows? ? "" : ENV['FC_SUDO']
|
23
|
+
end
|
24
|
+
|
25
|
+
def windows?
|
26
|
+
(PLATFORM =~ /win32|cygwin/) rescue nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def install_home
|
30
|
+
ENV['GEM_HOME'] ? "-i #{ENV['GEM_HOME']}" : ""
|
31
|
+
end
|
32
|
+
|
33
|
+
##############################################################################
|
34
|
+
# Packaging & Installation
|
35
|
+
##############################################################################
|
36
|
+
CLEAN.include ["**/.*.sw?", "pkg", "lib/*.bundle", "*.gem", "doc/rdoc", ".config", "coverage", "cache"]
|
37
|
+
|
38
|
+
desc "Run the specs."
|
39
|
+
task :default => :specs
|
40
|
+
|
41
|
+
task :frontcompiler => [:clean, :rdoc, :package]
|
42
|
+
|
43
|
+
spec = Gem::Specification.new do |s|
|
44
|
+
s.name = NAME
|
45
|
+
s.version = FrontCompiler::VERSION
|
46
|
+
s.platform = Gem::Platform::RUBY
|
47
|
+
s.author = "Nikolay V. Nemshilov"
|
48
|
+
s.email = "nemshilov@gmail.com"
|
49
|
+
s.homepage = "http://st-on-it.blogspot.com"
|
50
|
+
s.summary = "FrontCompiler is a simple collection of compactors for the JavaScript,
|
51
|
+
CSS and HTML source code. It removes trailing whitespaces, comments and
|
52
|
+
transformates the local variables to make the sourcecode shorter."
|
53
|
+
s.bindir = "bin"
|
54
|
+
s.description = s.summary
|
55
|
+
s.executables = %w( )
|
56
|
+
s.require_path = "lib"
|
57
|
+
s.files = %w( README Rakefile init.rb install.rb uninstall.rb ) + Dir["{docs,bin,spec,lib,examples,script}/**/*"]
|
58
|
+
|
59
|
+
# rdoc
|
60
|
+
s.has_rdoc = true
|
61
|
+
s.extra_rdoc_files = %w( README )
|
62
|
+
#s.rdoc_options += RDOC_OPTS + ["--exclude", "^(app|uploads)"]
|
63
|
+
|
64
|
+
# Dependencies
|
65
|
+
# s.add_dependency "something"
|
66
|
+
# Requirements
|
67
|
+
s.required_ruby_version = ">= 1.8.4"
|
68
|
+
end
|
69
|
+
|
70
|
+
Rake::GemPackageTask.new(spec) do |package|
|
71
|
+
package.gem_spec = spec
|
72
|
+
end
|
73
|
+
|
74
|
+
desc "Run :package and install the resulting .gem"
|
75
|
+
task :install => :package do
|
76
|
+
sh %{#{sudo} gem install #{install_home} --local pkg/#{NAME}-#{FrontCompiler::VERSION}.gem --no-rdoc --no-ri}
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "Run :clean and uninstall the .gem"
|
80
|
+
task :uninstall => :clean do
|
81
|
+
sh %{#{sudo} gem uninstall #{NAME}}
|
82
|
+
end
|
data/bin/frontcc
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__),'..','lib')))
|
3
|
+
|
4
|
+
require 'front_compiler'
|
5
|
+
|
6
|
+
if ARGV.empty? || ARGV.include?('-h') || ARGV.include?('--help')
|
7
|
+
puts %Q{FrontCompiler the Ruby based JavaScript/CSS/HTML compiler
|
8
|
+
(C) 2008-2009 Nikolay Nemshilov
|
9
|
+
|
10
|
+
|
11
|
+
frontcc [options] file file file ...
|
12
|
+
|
13
|
+
options:
|
14
|
+
-h Show this help
|
15
|
+
-p Create an albeit packed script
|
16
|
+
|
17
|
+
|
18
|
+
The command supports any standard console */* selectors
|
19
|
+
and will automatically recognize file-types by extensions
|
20
|
+
}
|
21
|
+
else
|
22
|
+
cc = FrontCompiler.new
|
23
|
+
|
24
|
+
javascript = false
|
25
|
+
|
26
|
+
# creating an overall source
|
27
|
+
source = ARGV.collect{ |path| Dir[path] }.flatten.collect do |path|
|
28
|
+
if File.exists? path
|
29
|
+
src = File.open(path, 'r').read
|
30
|
+
|
31
|
+
case path.split('.').last.downcase
|
32
|
+
when "html"
|
33
|
+
throw "We don't inline HTML into JavaScript" if javascript
|
34
|
+
cc.compact_html(src)
|
35
|
+
when "css"
|
36
|
+
cc.send(javascript ? :inline_css : :compact_css, src)
|
37
|
+
when "js"
|
38
|
+
javascript = true
|
39
|
+
src =~ /;\s*\Z/ ? src : (src + ';') # <- checking the end semicolon
|
40
|
+
|
41
|
+
else
|
42
|
+
throw "Unsupported kind of file '#{path}'"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end.compact.join("")
|
46
|
+
|
47
|
+
if javascript
|
48
|
+
source = cc.compact_js(source)
|
49
|
+
source = source.create_self_build if ARGV.include?('-p')
|
50
|
+
end
|
51
|
+
|
52
|
+
puts source
|
53
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'front_compiler'))
|
2
|
+
|
3
|
+
if defined? ActionController
|
4
|
+
ActionController::Base.class_eval {
|
5
|
+
include FrontCompilerHelper
|
6
|
+
helper FrontCompilerHelper
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Rails 2.2
|
11
|
+
if defined? ActionView::Helpers::AssetTagHelper::AssetCollection
|
12
|
+
ActionView::Helpers::AssetTagHelper::JavaScriptSources.class_eval do
|
13
|
+
alias :original_joined_contents :joined_contents
|
14
|
+
def joined_contents
|
15
|
+
FrontCompiler.new.compact_js(original_joined_contents)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
ActionView::Helpers::AssetTagHelper::StylesheetSources.class_eval do
|
19
|
+
alias :original_joined_contents :joined_contents
|
20
|
+
def joined_contents
|
21
|
+
FrontCompiler.new.compact_css(original_joined_contents)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#
|
2
|
+
# This module contains the nested css handling
|
3
|
+
# it converts virtual nested css constructions to standard css constructions
|
4
|
+
#
|
5
|
+
# Copyright (C) Nikolay V. Nemshilov aka St.
|
6
|
+
#
|
7
|
+
class FrontCompiler
|
8
|
+
class FrontCompiler::CssSource < FrontCompiler::SourceCode
|
9
|
+
module NestedStyles
|
10
|
+
# overloads the constructor, to convert the styles on fly
|
11
|
+
def initialize(src, keep_as_is=false)
|
12
|
+
super src
|
13
|
+
convert_nested_styles! unless keep_as_is
|
14
|
+
end
|
15
|
+
|
16
|
+
# converts the nested styles constructions in the source
|
17
|
+
CSS_CONSTRUCTION_RE = /((\A|\}|;)\s*?([^\}\{;]+?)\s*?)\{.*?\}/m
|
18
|
+
def convert_nested_styles!
|
19
|
+
# loop though the blocks
|
20
|
+
offset = 0
|
21
|
+
while pos = index(CSS_CONSTRUCTION_RE, offset)
|
22
|
+
pos += $1.size # <- getting the actual block position
|
23
|
+
block = find_block("{}", pos)
|
24
|
+
block = block[1, block.size-1]; pos+=1 # <- remove the container
|
25
|
+
block_size = block.size
|
26
|
+
|
27
|
+
parent_rules = clean_rules_from $3 # <- the block rules list
|
28
|
+
|
29
|
+
block_sub_styles = []
|
30
|
+
|
31
|
+
# looking for a nested construction
|
32
|
+
while block_pos = block.index(CSS_CONSTRUCTION_RE)
|
33
|
+
trail_char = $2.dup
|
34
|
+
|
35
|
+
block_start = $1.dup
|
36
|
+
block_start = block_start[trail_char.size, block_start.size]
|
37
|
+
block_start_size = block_start.size
|
38
|
+
|
39
|
+
block_pos += trail_char.size # <- updating the sub-block position
|
40
|
+
|
41
|
+
# update the sub-bolock rules
|
42
|
+
clean_rules_from($3).each do |block_rule|
|
43
|
+
block_start.gsub! block_rule, parent_rules.collect{ |p_rule|
|
44
|
+
"#{p_rule} #{block_rule}"
|
45
|
+
}.join(", ")
|
46
|
+
end
|
47
|
+
|
48
|
+
# getting the construction body
|
49
|
+
block_body = find_block("{}", block_pos + block_start_size, block)
|
50
|
+
|
51
|
+
# removing the construction out of the block
|
52
|
+
block[block_pos, block_start_size + block_body.size] = ''
|
53
|
+
block_sub_styles << block_start + block_body
|
54
|
+
end
|
55
|
+
|
56
|
+
# replacing the block
|
57
|
+
self[pos, block_size] = block + block_sub_styles.join('')
|
58
|
+
|
59
|
+
offset = pos + block.size - 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
# creates a clean css-rules list out of the str
|
65
|
+
def clean_rules_from(str)
|
66
|
+
str.split(',').collect{ |rule|
|
67
|
+
rule.gsub(/\s+/, ' ').gsub(/\/\*.*?\*\//im, '').strip
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#
|
2
|
+
# The CSS sources compactor
|
3
|
+
#
|
4
|
+
# Copyright (C) Nikolay V. Nemshilov aka St.
|
5
|
+
#
|
6
|
+
require "front_compiler/css_source/nested_styles"
|
7
|
+
|
8
|
+
class FrontCompiler::CssSource < FrontCompiler::SourceCode
|
9
|
+
include NestedStyles
|
10
|
+
|
11
|
+
# removes all the comments out of the given source
|
12
|
+
def remove_comments!
|
13
|
+
string_safely do
|
14
|
+
gsub!(/\/\*.*?\*\//im, '')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# removes all the empty lines out of the source code
|
19
|
+
def remove_empty_lines!
|
20
|
+
string_safely do
|
21
|
+
gsub!(/\n\s*\n/m, "\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# removes tailing whitespaces out of the source code
|
26
|
+
def remove_trailing_spaces!
|
27
|
+
string_safely do
|
28
|
+
gsub!(/\s+/im, ' ')
|
29
|
+
gsub!(/\s*(\+|>|\||~|\{|\}|,|\)|\(|;|:|\*)\s*/im, '\1')
|
30
|
+
gsub!(/;\}/, '}')
|
31
|
+
strip!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# converts the source in such a way that it could be
|
36
|
+
# delivered with javascript in the same file
|
37
|
+
def to_javascript
|
38
|
+
"document.write(\"<style type=\\\"text/css\\\">#{
|
39
|
+
compact.gsub('"', '\"')
|
40
|
+
}</style>\");"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# The HTML sources compactor
|
3
|
+
#
|
4
|
+
# Copyright (C) Nikolay V. Nemshilov aka St.
|
5
|
+
#
|
6
|
+
class FrontCompiler::HTMLCompactor
|
7
|
+
# applies all the compactings to the given source
|
8
|
+
def minimize(source)
|
9
|
+
source = remove_comments(source)
|
10
|
+
source = remove_trailing_spaces(source)
|
11
|
+
end
|
12
|
+
|
13
|
+
# removes all the comments out of the code
|
14
|
+
def remove_comments(source)
|
15
|
+
source.gsub /<!--.*?-->/, ''
|
16
|
+
end
|
17
|
+
|
18
|
+
# remove all the trailing spaces out of the code
|
19
|
+
def remove_trailing_spaces(source)
|
20
|
+
source.gsub! /\s+/, ' '
|
21
|
+
source.gsub! />\s+/, '>'
|
22
|
+
source.gsub /\s+</, '<'
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#
|
2
|
+
# This module contains the javascript logical
|
3
|
+
# structures processor/compactor
|
4
|
+
#
|
5
|
+
# This module is a part of the JavaScript class and taken out
|
6
|
+
# just to keep the things simple
|
7
|
+
#
|
8
|
+
# Copyright (C) Nikolay V. Nemshilov aka St.
|
9
|
+
#
|
10
|
+
class FrontCompiler
|
11
|
+
class JavaScript < FrontCompiler::SourceCode
|
12
|
+
module LogicCompactor
|
13
|
+
#
|
14
|
+
# checks and compacts the script-logic
|
15
|
+
#
|
16
|
+
def compact_logic!
|
17
|
+
string_safely do
|
18
|
+
join_multiline_defs!
|
19
|
+
fix_missed_semicolons!
|
20
|
+
simplify_constructions_of self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
#
|
26
|
+
# joins constructions which split on several lines
|
27
|
+
#
|
28
|
+
MULTILINING_CHARS_RE = %w{ ? : = - + * / % ! & | < > ,
|
29
|
+
}.collect{ |c| Regexp.escape(c)}.join("|")
|
30
|
+
def join_multiline_defs!
|
31
|
+
gsub!(/\s+(#{MULTILINING_CHARS_RE})\s+/m, ' \1 ')
|
32
|
+
gsub!(/\s+(#{MULTILINING_CHARS_RE})(\S)/m, ' \1\2')
|
33
|
+
gsub!(/(\S)(#{MULTILINING_CHARS_RE})\s+/m, '\1\2 ')
|
34
|
+
|
35
|
+
gsub!(/\s*(\.)\s*/m, '\1') # <- fold object member calls
|
36
|
+
|
37
|
+
gsub!(/(\()\s+/m, '\1') # <- fold method argument defs
|
38
|
+
gsub!(/\s+(\))/m, '\1')
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# tries to simplify the short logical constructions
|
43
|
+
# which were defined as multilined but could be simplier
|
44
|
+
#
|
45
|
+
def simplify_constructions_of(src)
|
46
|
+
[/(if|for|while)\s*\(/im, /(else|do)\s*\s\{/im].each do |regexp|
|
47
|
+
offset = 0
|
48
|
+
while pos = src.index(regexp, offset)
|
49
|
+
block = name = $1.dup
|
50
|
+
block += find_block("()", pos + block.size, src)
|
51
|
+
body = find_block("{}", pos + block.size, src)
|
52
|
+
|
53
|
+
unless body == ''
|
54
|
+
block += body[/\A\s*/m]; body.strip! # removing starting empty-chars
|
55
|
+
body_code = body[1, body.size-2]
|
56
|
+
|
57
|
+
# checking if the code can be simplified
|
58
|
+
can_be_simplified = number_of_code_lines_in(body_code) == 1
|
59
|
+
|
60
|
+
# check additional 'if' constructions restrictions
|
61
|
+
if can_be_simplified and name == 'if'
|
62
|
+
# double ifs construction check
|
63
|
+
can_be_simplified &= !body_code.match(/\A\s*if\s*\(/im)
|
64
|
+
|
65
|
+
# checking the else blocks missintersections
|
66
|
+
if src[pos+block.size+body.size, 40].match(/\A\s*else(\s+|\{)/)
|
67
|
+
can_be_simplified &= !body_code.match(/(\A|[^a-z\d_$])if\s*\(/)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# try to simplify internal constructions
|
72
|
+
simplify_constructions_of body_code
|
73
|
+
|
74
|
+
if can_be_simplified
|
75
|
+
check_semicolons_in body_code
|
76
|
+
else
|
77
|
+
body_code = "{#{body_code}}"
|
78
|
+
end
|
79
|
+
|
80
|
+
src[pos+block.size, body.size] = body_code
|
81
|
+
body = body_code
|
82
|
+
end
|
83
|
+
|
84
|
+
offset = pos + block.size + body.size
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# calculates the number of code-lines in the string
|
90
|
+
def number_of_code_lines_in(src)
|
91
|
+
src = src.dup
|
92
|
+
|
93
|
+
# replacing all the method calls, blocks and lists with dummies
|
94
|
+
['[]', '()', '{}'].each do |pair|
|
95
|
+
offset = 0
|
96
|
+
while pos = src.index(pair[0,1], offset)
|
97
|
+
offset = pos + 1
|
98
|
+
block = find_block(pair, 0, src[pos, src.size])
|
99
|
+
|
100
|
+
src[pos, block.size] = pair
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# putting semicolons after try/catch/finally constructions, so they were conuted as well
|
105
|
+
src.gsub!(/(catch\s*\(\)|finally)\s*\{\}/, '\&;')
|
106
|
+
src.gsub!(/\(\)\s*\{\}/, '\&;')
|
107
|
+
|
108
|
+
# calculating the number of the lines
|
109
|
+
src.split(';').collect{ |line|
|
110
|
+
line.strip != '' ? 1 : nil
|
111
|
+
}.compact.size
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# checks if there's ommited semicolons in the code
|
116
|
+
def check_semicolons_in(src)
|
117
|
+
src[/\s*\Z/m] = ";#{src[/\s*\Z/m]}" unless src.strip[-1,1].match(/[;\}]/)
|
118
|
+
|
119
|
+
# removing bug causing semicolons after a function
|
120
|
+
src.gsub!(/(\A\s*function\s*.*?\(.*?\)\s*\{.*?\});(\s*\Z)/im) do
|
121
|
+
$1 + $2
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def fix_missed_semicolons!
|
126
|
+
gsub! /([^{}()|\[&;:=,\s])([ \t]*?\n\s*?(return|if|function|while|try|do)[^a-zA-Z_$])/, '\1;\2'
|
127
|
+
|
128
|
+
# (function(){....})(..) if(...)
|
129
|
+
gsub! /(\}\)\([^)]*\))([ \t]*?\n\s*?(return|if|function|while|try|do)[^a-zA-Z_$])/, '\1;\2'
|
130
|
+
|
131
|
+
# fixing wrong added semicolons before the if calls
|
132
|
+
gsub! /([^a-zA-Z_$](else|do));(\s+(if|while|do|try)[^a-zA-Z_$])/, '\1\3'
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|