emcee 0.1.1
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +32 -0
- data/lib/emcee.rb +7 -0
- data/lib/emcee/compressors/html_compressor.rb +49 -0
- data/lib/emcee/helpers/action_view.rb +34 -0
- data/lib/emcee/helpers/sprockets_compressing.rb +32 -0
- data/lib/emcee/helpers/sprockets_view.rb +29 -0
- data/lib/emcee/processors/html_processor.rb +155 -0
- data/lib/emcee/railtie.rb +15 -0
- data/lib/emcee/version.rb +3 -0
- data/lib/generators/emcee/install/install_generator.rb +23 -0
- data/lib/generators/emcee/install/templates/application.html +9 -0
- data/lib/tasks/emcee_tasks.rake +4 -0
- data/test/compressors_test.rb +41 -0
- data/test/controllers_test.rb +16 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/elements/application.html +12 -0
- data/test/dummy/app/assets/elements/test/test2.html +2 -0
- data/test/dummy/app/assets/elements/test/test3.html +1 -0
- data/test/dummy/app/assets/elements/test1.html +1 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/dummy_controller.rb +4 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/dummy/index.html.erb +1 -0
- data/test/dummy/app/views/layouts/application.html.erb +15 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +12 -0
- data/test/dummy/log/test.log +2433 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/01abb54333b8d67888355b2f855692e8 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/1e24025f59396708b3bb44543bed32fc +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/219d0afb67879a67bae32b4fe4c708ac +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/32cae461a9446107294c8a0230f5080c +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/4fd1effec4d6579ba9d4f03ed156a15b +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/63ab3ecb77a01edbed6db1aca4d690fc +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/6c9d8a21af4539e19a3462e79ac4d70c +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/a69c3d00e22ad6c0d6ece35c9fd5f316 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/af6ba4ae23c6790e0f474b01ceee8dd9 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/c04739a2061e8e023568aabaa0e801d2 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cf517b62bd978b748afe38d5beb317de +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/df6cfcc50da209231a7d9e140e5bafdc +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/e0949aa3dcdcab5f8b45d30e26f6ddd2 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/e1d520d14db311ab6347be6426dac6f5 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/ffd4adb86602a60c7fcedd5d472166d3 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/070957bfe375a537750196a12d9e6d1a +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/1e24025f59396708b3bb44543bed32fc +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/219d0afb67879a67bae32b4fe4c708ac +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/32cae461a9446107294c8a0230f5080c +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/4fd1effec4d6579ba9d4f03ed156a15b +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/6c9d8a21af4539e19a3462e79ac4d70c +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/a69c3d00e22ad6c0d6ece35c9fd5f316 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/af6ba4ae23c6790e0f474b01ceee8dd9 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/cf517b62bd978b748afe38d5beb317de +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/df6cfcc50da209231a7d9e140e5bafdc +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/e0949aa3dcdcab5f8b45d30e26f6ddd2 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/fb7c86cdcce596d8b3c14ce236bf73c5 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ffd4adb86602a60c7fcedd5d472166d3 +0 -0
- data/test/dummy/vendor/assets/elements/test4.html +1 -0
- data/test/emcee_test.rb +7 -0
- data/test/helpers_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- metadata +259 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: fb57be0dd8aa54269cad7513113aecae19cc050b
|
|
4
|
+
data.tar.gz: 5b088d3adeadf5be4fddbc4896d212be3a14aa05
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9b749f99a257f213979bc70167e002e0d818bea8c8760b396a03cd937f2c08f7eda2a54b2a67f7753954331953b218ac75f7e67f53c8a2a1f3e22eef6fa35eb8
|
|
7
|
+
data.tar.gz: 8400a030e328ecd2ef69a3dfef0cd13a6a983f07f3c2f2866547ee5477c92492838d11eeba4ecfa91245a9eabaa727a3ece76ad0155a10906e48c81a479482b3
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2014 Andrew Huth
|
|
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/Rakefile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Emcee'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
Bundler::GemHelper.install_tasks
|
|
21
|
+
|
|
22
|
+
require 'rake/testtask'
|
|
23
|
+
|
|
24
|
+
Rake::TestTask.new(:test) do |t|
|
|
25
|
+
t.libs << 'lib'
|
|
26
|
+
t.libs << 'test'
|
|
27
|
+
t.pattern = 'test/**/*_test.rb'
|
|
28
|
+
t.verbose = false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
task default: :test
|
data/lib/emcee.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Emcee
|
|
2
|
+
module Compressors
|
|
3
|
+
# HtmlCompressor is our basic implementation of an html minifier. For
|
|
4
|
+
# sprockets to use it, it must have a compress method that only accepts a
|
|
5
|
+
# string and returns the compressed output.
|
|
6
|
+
#
|
|
7
|
+
# Our implementation only strips out html and javascript comments, and
|
|
8
|
+
# removes blank lines.
|
|
9
|
+
#
|
|
10
|
+
class HtmlCompressor
|
|
11
|
+
# Match html comments.
|
|
12
|
+
#
|
|
13
|
+
# <!--
|
|
14
|
+
# Comments
|
|
15
|
+
# -->
|
|
16
|
+
#
|
|
17
|
+
HTML_COMMENTS = /\<!\s*--(?:.*?)(?:--\s*\>)/m
|
|
18
|
+
|
|
19
|
+
# Match multi-line javascript/css comments.
|
|
20
|
+
#
|
|
21
|
+
# /*
|
|
22
|
+
# Comments
|
|
23
|
+
# */
|
|
24
|
+
#
|
|
25
|
+
JS_MULTI_COMMENTS = /\/\*(?:.*?)\*\//m
|
|
26
|
+
|
|
27
|
+
# Match single-line javascript comments.
|
|
28
|
+
#
|
|
29
|
+
# // Comments
|
|
30
|
+
#
|
|
31
|
+
# This does not have the /m modifier, because we only want it to match a
|
|
32
|
+
# single line at a time.
|
|
33
|
+
#
|
|
34
|
+
JS_COMMENTS = /\/\/.*$/
|
|
35
|
+
|
|
36
|
+
# Match blank lines.
|
|
37
|
+
BLANK_LINES = /^[\s]*$\n/
|
|
38
|
+
|
|
39
|
+
# Remove comments and blank lines from our html.
|
|
40
|
+
def compress(string)
|
|
41
|
+
ops = [HTML_COMMENTS, JS_MULTI_COMMENTS, JS_COMMENTS, BLANK_LINES]
|
|
42
|
+
|
|
43
|
+
ops.reduce(string) do |output, op|
|
|
44
|
+
output.gsub(op, "")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module ActionView
|
|
2
|
+
module Helpers
|
|
3
|
+
module AssetUrlHelper
|
|
4
|
+
ASSET_EXTENSIONS.merge!({ html: '.html' })
|
|
5
|
+
ASSET_PUBLIC_DIRECTORIES.merge!({ html: '/elements' })
|
|
6
|
+
|
|
7
|
+
# Convenience method for html based on javascript_path.
|
|
8
|
+
def html_path(source, options = {})
|
|
9
|
+
path_to_asset(source, { type: :html }.merge!(options))
|
|
10
|
+
end
|
|
11
|
+
alias_method :path_to_html, :html_path
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module AssetTagHelper
|
|
15
|
+
# Custom view helper used to create an html import. Will search the asset
|
|
16
|
+
# directories for the sources.
|
|
17
|
+
#
|
|
18
|
+
# html_import_tag("navigation")
|
|
19
|
+
#
|
|
20
|
+
def html_import_tag(*sources)
|
|
21
|
+
options = sources.extract_options!.stringify_keys
|
|
22
|
+
path_options = options.extract!('protocol').symbolize_keys
|
|
23
|
+
|
|
24
|
+
sources.uniq.map { |source|
|
|
25
|
+
tag_options = {
|
|
26
|
+
"rel" => "import",
|
|
27
|
+
"href" => path_to_html(source, path_options)
|
|
28
|
+
}.merge!(options)
|
|
29
|
+
tag(:link, tag_options)
|
|
30
|
+
}.join("\n").html_safe
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Sprockets
|
|
2
|
+
module Compressing
|
|
3
|
+
def html_compressor
|
|
4
|
+
@html_compressor if defined? @html_compressor
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Assign a compressor to run on 'text/html' assets.
|
|
8
|
+
#
|
|
9
|
+
# The compressor object must respond to 'compress'.
|
|
10
|
+
def html_compressor=(compressor)
|
|
11
|
+
unregister_bundle_processor 'text/html', html_compressor if html_compressor
|
|
12
|
+
@html_compressor = nil
|
|
13
|
+
return unless compressor
|
|
14
|
+
|
|
15
|
+
if compressor.is_a?(Symbol)
|
|
16
|
+
compressor = compressors['text/html'][compressor] || raise(Error, "unknown compressor: #{compressor}")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
if compressor.respond_to?(:compress)
|
|
20
|
+
klass = Class.new(Processor) do
|
|
21
|
+
@name = "html_compressor"
|
|
22
|
+
@processor = proc { |context, data| compressor.compress(data) }
|
|
23
|
+
end
|
|
24
|
+
@html_compressor = :html_compressor
|
|
25
|
+
else
|
|
26
|
+
@html_compressor = klass = compressor
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
register_bundle_processor "text/html", klass
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Sprockets
|
|
2
|
+
module Rails
|
|
3
|
+
module Helper
|
|
4
|
+
# Custom view helper used to create an html import. This same method is
|
|
5
|
+
# already defined in ActionView. We pull out the sources here, before
|
|
6
|
+
# calling back to ActionView's.
|
|
7
|
+
#
|
|
8
|
+
# Based on Sprocket's javascript_include_tag.
|
|
9
|
+
def html_import_tag(*sources)
|
|
10
|
+
options = sources.extract_options!.stringify_keys
|
|
11
|
+
if options["debug"] != false && request_debug_assets?
|
|
12
|
+
sources.map { |source|
|
|
13
|
+
#check_errors_for(source)
|
|
14
|
+
if asset = lookup_asset_for_path(source, type: :html)
|
|
15
|
+
asset.to_a.map do |a|
|
|
16
|
+
super(path_to_html(a.logical_path, debug: true), options)
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
super(source, options)
|
|
20
|
+
end
|
|
21
|
+
}.flatten.uniq.join("\n").html_safe
|
|
22
|
+
else
|
|
23
|
+
sources.push(options)
|
|
24
|
+
super(*sources)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
module Emcee
|
|
2
|
+
module Processors
|
|
3
|
+
# HtmlProcessor processes html files by doing 4 things:
|
|
4
|
+
#
|
|
5
|
+
# 1. Stripping out asset pipeline directives and processing the associated
|
|
6
|
+
# files.
|
|
7
|
+
# 2. Stripping out html imports and processing those files.
|
|
8
|
+
# 3. Stripping out external stylesheet includes, and inlining those sheets
|
|
9
|
+
# where they were called.
|
|
10
|
+
# 4. Stripping out external script tags, and inlining those scripts where
|
|
11
|
+
# they were called.
|
|
12
|
+
#
|
|
13
|
+
# It inherits from Sprocket::DirectiveProcessor, which does most of the
|
|
14
|
+
# work for us.
|
|
15
|
+
#
|
|
16
|
+
class HtmlProcessor < Sprockets::DirectiveProcessor
|
|
17
|
+
# Matches the entire header/directive block. This is everything from the
|
|
18
|
+
# top of the file, enclosed in html comments.
|
|
19
|
+
#
|
|
20
|
+
# ---
|
|
21
|
+
#
|
|
22
|
+
# \A matches the beginning of the string
|
|
23
|
+
# (?m:\s*) matches whitespace, including \n
|
|
24
|
+
# (<!--(?m:.*?)-->) matches html comments and their content
|
|
25
|
+
#
|
|
26
|
+
HEADER_PATTERN = /\A((?m:\s*)(<!--(?m:.*?)-->))+/
|
|
27
|
+
|
|
28
|
+
# Matches the an asset pipeline directive.
|
|
29
|
+
#
|
|
30
|
+
# *= require_tree .
|
|
31
|
+
#
|
|
32
|
+
# ---
|
|
33
|
+
#
|
|
34
|
+
# ^ matches the beginning of the line
|
|
35
|
+
# \W* matches any non-word character, zero or more times
|
|
36
|
+
# = matches =, obviously
|
|
37
|
+
# \s* matches any whitespace character, zero or more times
|
|
38
|
+
# (\w+.*?) matches a group of characters, starting with a letter or number
|
|
39
|
+
# $ matches the end of the line
|
|
40
|
+
#
|
|
41
|
+
DIRECTIVE_PATTERN = /^\W*=\s*(\w+.*?)$/
|
|
42
|
+
|
|
43
|
+
# Match an html import tag.
|
|
44
|
+
#
|
|
45
|
+
# <link rel="import" href="example.html">
|
|
46
|
+
#
|
|
47
|
+
IMPORT_PATTERN = /^<link .*rel=["']import["'].*>$/
|
|
48
|
+
|
|
49
|
+
# Match a stylesheet link tag.
|
|
50
|
+
#
|
|
51
|
+
# <link rel="stylesheet" href="example.css">
|
|
52
|
+
#
|
|
53
|
+
STYLESHEET_PATTERN = /^ +<link .*rel=["']stylesheet["'].*>$/
|
|
54
|
+
|
|
55
|
+
# Match a script tag.
|
|
56
|
+
#
|
|
57
|
+
# <script src="assets/example.js"></script>
|
|
58
|
+
#
|
|
59
|
+
SCRIPT_PATTERN = /^ *<script .*src=["'].+\.js["']><\/script>$/
|
|
60
|
+
|
|
61
|
+
# Match the path from the href attribute of an html import or stylesheet
|
|
62
|
+
# include tag. Captures the actual path.
|
|
63
|
+
#
|
|
64
|
+
# href="/assets/example.css"
|
|
65
|
+
#
|
|
66
|
+
HREF_PATH_PATTERN = /href=["'](?<path>[\w\.\/-]+)["']/
|
|
67
|
+
|
|
68
|
+
# Match the source path from a script tag. Captures the actual path.
|
|
69
|
+
#
|
|
70
|
+
# src="/assets/example.js"
|
|
71
|
+
#
|
|
72
|
+
SRC_PATH_PATTERN = /src=["'](?<path>[\w\.\/-]+)["']/
|
|
73
|
+
|
|
74
|
+
# Render takes the actual text of the file and does our processing to it.
|
|
75
|
+
# This is based on the standard render method on Sprockets's
|
|
76
|
+
# DirectiveProcessor.
|
|
77
|
+
#
|
|
78
|
+
def render(context, locals)
|
|
79
|
+
@context = context
|
|
80
|
+
@pathname = context.pathname
|
|
81
|
+
@directory = File.dirname(@pathname)
|
|
82
|
+
|
|
83
|
+
@header = data[HEADER_PATTERN, 0] || ""
|
|
84
|
+
@body = $' || data
|
|
85
|
+
# Ensure body ends in a new line
|
|
86
|
+
@body += "\n" if @body != "" && @body !~ /\n\Z/m
|
|
87
|
+
|
|
88
|
+
@included_pathnames = []
|
|
89
|
+
|
|
90
|
+
@result = ""
|
|
91
|
+
@result.force_encoding(body.encoding)
|
|
92
|
+
|
|
93
|
+
@has_written_body = false
|
|
94
|
+
|
|
95
|
+
process_directives
|
|
96
|
+
process_imports
|
|
97
|
+
process_stylesheets
|
|
98
|
+
process_scripts
|
|
99
|
+
process_source
|
|
100
|
+
|
|
101
|
+
@result
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
protected
|
|
105
|
+
# Scan the body for html imports. If any are found, tell sprockets to
|
|
106
|
+
# require their files like we would for a directive.
|
|
107
|
+
def process_imports
|
|
108
|
+
body.scan(IMPORT_PATTERN) do |import_tag|
|
|
109
|
+
if path = import_tag[HREF_PATH_PATTERN, :path]
|
|
110
|
+
absolute_path = File.absolute_path(path, @directory)
|
|
111
|
+
context.require_asset(absolute_path)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
@body.gsub!(IMPORT_PATTERN, "")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Scan the body for external stylesheet references. If any are found,
|
|
119
|
+
# inline the files in place of the references.
|
|
120
|
+
def process_stylesheets
|
|
121
|
+
to_inline = []
|
|
122
|
+
|
|
123
|
+
body.scan(STYLESHEET_PATTERN) do |stylesheet_tag|
|
|
124
|
+
if path = stylesheet_tag[HREF_PATH_PATTERN, :path]
|
|
125
|
+
absolute_path = File.absolute_path(path, @directory)
|
|
126
|
+
stylesheet_contents = File.read(absolute_path)
|
|
127
|
+
to_inline << [stylesheet_tag, "<style>\n" + stylesheet_contents + "</style>\n"]
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
to_inline.each do |(tag, contents)|
|
|
132
|
+
@body.gsub!(tag, contents)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Scan the body for external script references. If any are found, inline
|
|
137
|
+
# the files in place of the references.
|
|
138
|
+
def process_scripts
|
|
139
|
+
to_inline = []
|
|
140
|
+
|
|
141
|
+
body.scan(SCRIPT_PATTERN) do |script_tag|
|
|
142
|
+
if path = script_tag[SRC_PATH_PATTERN, :path]
|
|
143
|
+
absolute_path = File.absolute_path(path, @directory)
|
|
144
|
+
script_contents = File.read(absolute_path)
|
|
145
|
+
to_inline << [script_tag, "<script>\n" + script_contents + "</script>\n"]
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
to_inline.each do |(tag, contents)|
|
|
150
|
+
@body.gsub!(tag, contents)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "emcee/processors/html_processor"
|
|
2
|
+
require "emcee/compressors/html_compressor"
|
|
3
|
+
|
|
4
|
+
module Emcee
|
|
5
|
+
class Railtie < Rails::Railtie
|
|
6
|
+
initializer :add_html_processor do |app|
|
|
7
|
+
app.assets.register_mime_type "text/html", ".html"
|
|
8
|
+
app.assets.register_preprocessor "text/html", Processors::HtmlProcessor
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
initializer :add_html_compressor do |app|
|
|
12
|
+
app.assets.html_compressor = Compressors::HtmlCompressor.new
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Emcee
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
5
|
+
|
|
6
|
+
desc "Adds an html import tag into your layout, adds a manifest to assets/elements/application.html, and adds a vendor/assets/elements directory"
|
|
7
|
+
|
|
8
|
+
def copy_application_manifest
|
|
9
|
+
empty_directory "app/assets/elements"
|
|
10
|
+
copy_file "application.html", "app/assets/elements/application.html"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def create_vendor_directory
|
|
14
|
+
empty_directory "vendor/assets/elements"
|
|
15
|
+
create_file "vendor/assets/elements/.keep"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def add_html_import_to_layout
|
|
19
|
+
insert_into_file "app/views/layouts/application.html.erb", "<%= html_import_tag \"application\" %>\n\t\t", before: "<%= csrf_meta_tags %>"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* This is a manifest file that'll be compiled into application.html, which will include all the files
|
|
3
|
+
* listed below and their dependencies.
|
|
4
|
+
*
|
|
5
|
+
* Any html files within this directory, lib/assets/elements, or vendor/assets/elements
|
|
6
|
+
* can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
*= require_tree .
|
|
9
|
+
-->
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'test_Helper'
|
|
2
|
+
|
|
3
|
+
class CompressorsTest < ActiveSupport::TestCase
|
|
4
|
+
setup do
|
|
5
|
+
@compressor = Emcee::Compressors::HtmlCompressor.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
test "compressor should remove html comments" do
|
|
9
|
+
content = "<!--\nHere\nAre\nSome Comments\n-->\n<span>test</span>\n"
|
|
10
|
+
assert_equal "<span>test</span>\n", @compressor.compress(content)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test "compressor should remove multi-line javascript comments" do
|
|
14
|
+
content = "<script>\n/*\nHere\nAre\nA Bunch\nOf Comments\n*/\n</script>\n"
|
|
15
|
+
assert_equal "<script>\n</script>\n", @compressor.compress(content)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test "compressor should remove single-line javascript comments" do
|
|
19
|
+
content = "<script>\n// Here\n// Are Yet\n// Some More\n// Of The\n// Comments\n</script>\n"
|
|
20
|
+
assert_equal "<script>\n</script>\n", @compressor.compress(content)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
test "compressor should remove css comments" do
|
|
24
|
+
content = %q{
|
|
25
|
+
<style>
|
|
26
|
+
h1 {
|
|
27
|
+
/*
|
|
28
|
+
Make it pink
|
|
29
|
+
*/
|
|
30
|
+
color: pink;
|
|
31
|
+
}
|
|
32
|
+
</style>
|
|
33
|
+
}
|
|
34
|
+
assert_equal "<style>\n h1 {\n color: pink;\n }\n</style>\n", @compressor.compress(content)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test "compressor should remove blank lines" do
|
|
38
|
+
content = "<p>test</p>\n\n\n\n\n\n<p>oh yeah</p>"
|
|
39
|
+
assert_equal "<p>test</p>\n<p>oh yeah</p>", @compressor.compress(content)
|
|
40
|
+
end
|
|
41
|
+
end
|