assets-squasher 0.0.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/README.md +65 -0
- data/bin/assets-squasher +137 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 793d907e712e886eeea8903b6beb59febaadf644
|
4
|
+
data.tar.gz: e6cb4c394b955dcda52810fc2f7b64ee38e75290
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d48bcf5fc377ec8e98028c5923305b41201482e675477c6998ec027ed80bff971eea1dd0d8d0ec195d7d63e51d5ee5f9cd5944fe2cf8c0f2ec90497913e5052b
|
7
|
+
data.tar.gz: b5b9e742aec83140022599b5272fbc640370afb3e7237066ca3899bf5479b3a95259153fc6c7fb5b23d443ea625a0c73f60e5cd1e33a7486430753b64ab138ce
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# About
|
2
|
+
|
3
|
+
Assets squasher is exactly what it says on the tin: it takes an HTML file and replaces all included scripts with just one and the same for stylesheets.
|
4
|
+
|
5
|
+
One caveat here, it's meant to be used for **single page applications**. There you typically have one entry point HTML file which links all the necessary scripts and stylesheets. Like this one:
|
6
|
+
|
7
|
+
```html
|
8
|
+
<!DOCTYPE html>
|
9
|
+
|
10
|
+
<html ng-app="app" ng-controller="MainController">
|
11
|
+
<head>
|
12
|
+
<script defer src="/bower_components/angular/angular.min.js"></script>
|
13
|
+
<script defer src="/bower_components/angular-route/angular-route.min.js"></script>
|
14
|
+
<script defer src="/bower_components/angular-animate/angular-animate.min.js"></script>
|
15
|
+
<script defer src="/bower_components/angular-ui-bootstrap/dist/ui-bootstrap-tpls-0.11.0.min.js"></script>
|
16
|
+
<script defer src="/app.js"></script>
|
17
|
+
<script defer src="/services.js"></script>
|
18
|
+
|
19
|
+
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
|
20
|
+
<link rel="stylesheet" href="/bower_components/font-awesome/css/font-awesome.min.css">
|
21
|
+
<link rel="stylesheet" href="/app.css">
|
22
|
+
</head>
|
23
|
+
|
24
|
+
<body>
|
25
|
+
<div ng-view>Loading ...</div>
|
26
|
+
</body>
|
27
|
+
</html>
|
28
|
+
```
|
29
|
+
|
30
|
+
Now let's save it into `app.html` (I'm assuming that all the assets exist). When you run `bundle exec assets-asquasher app.html build.html`, you'll get `build/build.min.js` and its source map, `build/build.min.css` and also `build.html` which will look like this:
|
31
|
+
|
32
|
+
```html
|
33
|
+
<!DOCTYPE html>
|
34
|
+
|
35
|
+
<html ng-app="app" ng-controller="MainController">
|
36
|
+
<head>
|
37
|
+
<script src="/build/build.min.js"></script>
|
38
|
+
<link rel="stylesheet" href="/build/build.min.css">
|
39
|
+
</head>
|
40
|
+
|
41
|
+
<body>
|
42
|
+
<div ng-view>Loading ...</div>
|
43
|
+
</body>
|
44
|
+
</html>
|
45
|
+
```
|
46
|
+
|
47
|
+
## Why Is It Useful?
|
48
|
+
|
49
|
+
On production you want to use a single minified JS file and a single minified CSS file. Why? Because speed has significant impact on conversions. Yes, it's all cached after the first request, but how many times have you closed a web page before it even loaded?
|
50
|
+
|
51
|
+
On the other hand in development you want to include each unminified script separately, so the backtraces make sense[1].
|
52
|
+
|
53
|
+
Ultimately this the simplest solution: no need to change your code like you'd have to with say RequireJS. No need to define dependencies in an extra file – it's already there!
|
54
|
+
|
55
|
+
## Installation
|
56
|
+
|
57
|
+
```
|
58
|
+
# Assuming you have Node.js already installed.
|
59
|
+
npm -g uglify-js uglifycss
|
60
|
+
gem install assets-asquasher
|
61
|
+
```
|
62
|
+
|
63
|
+
## Footnotes
|
64
|
+
|
65
|
+
[1] Or alternatively you could use one build file with source maps, but then you have to user guard or something to constantly rebuild it.
|
data/bin/assets-squasher
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
html_file = ARGV.first
|
6
|
+
|
7
|
+
# Validate arguments.
|
8
|
+
unless ARGV.length == 2 && File.exist?(html_file)
|
9
|
+
abort <<-EOF
|
10
|
+
Usage: #{$0} [input HTML file path] [output HTML file path]
|
11
|
+
|
12
|
+
Those can be the same if you want to override the original file.
|
13
|
+
That can be useful for deployment, so you keep the original file
|
14
|
+
in your project, using it for development while for production
|
15
|
+
it is overriden for faster load times.
|
16
|
+
EOF
|
17
|
+
end
|
18
|
+
|
19
|
+
document = Nokogiri::HTML(File.read(html_file))
|
20
|
+
|
21
|
+
# Change CWD.
|
22
|
+
Dir.chdir(File.dirname(html_file))
|
23
|
+
|
24
|
+
puts "~ Assuming #{Dir.pwd} as the root directory."
|
25
|
+
|
26
|
+
# Helper methods.
|
27
|
+
def list(document, selector, attribute)
|
28
|
+
values = document.css(selector).map do |element|
|
29
|
+
value = element.attr(attribute)
|
30
|
+
value.start_with?('/') ? value[1..-1] : value
|
31
|
+
end
|
32
|
+
|
33
|
+
document.search(selector).remove
|
34
|
+
|
35
|
+
values
|
36
|
+
end
|
37
|
+
|
38
|
+
def run(command)
|
39
|
+
puts "~ $ #{command}"
|
40
|
+
%x{#{command}}.split("\n").each do |line|
|
41
|
+
puts " #{line}"
|
42
|
+
end; puts
|
43
|
+
end
|
44
|
+
|
45
|
+
# Main.
|
46
|
+
scripts = list(document, 'html > head > script[src]', 'src')
|
47
|
+
stylesheets = list(document, 'html > head > link[rel="stylesheet"]', 'href')
|
48
|
+
|
49
|
+
Dir.mkdir('build') unless Dir.exist?('build')
|
50
|
+
|
51
|
+
# Uglify
|
52
|
+
run "uglifyjs -o build/build.min.js --source-map build/build.min.js.map #{scripts.join(' ')}"
|
53
|
+
run "uglifycss #{stylesheets.join(' ')} > build/build.min.css"
|
54
|
+
|
55
|
+
script = document.create_element('script', src: '/build/build.min.js', defer: true)
|
56
|
+
document.at_css('head').children.after(script)
|
57
|
+
|
58
|
+
stylesheet = document.create_element('link', rel: 'stylesheet', href: '/build/build.min.css')
|
59
|
+
document.at_css('head').children.after(stylesheet)
|
60
|
+
|
61
|
+
|
62
|
+
# reformatter_path = File.expand_path('../../assets/reformat-html.xsl', __FILE__)
|
63
|
+
# reformatter_path = "/webs/ppt/assets-squasher/assets/reformat-html.xsl"
|
64
|
+
|
65
|
+
xsl = Nokogiri::XSLT(DATA)
|
66
|
+
lines = xsl.apply_to(document).split("\n")
|
67
|
+
lines[0] = "<!DOCTYPE html>"
|
68
|
+
|
69
|
+
File.open(ARGV[1], 'w') do |file|
|
70
|
+
file.puts(lines.join("\n"))
|
71
|
+
end
|
72
|
+
|
73
|
+
__END__
|
74
|
+
<!-- http://emmanueloga.wordpress.com/2009/09/29/pretty-printing-xhtml-with-nokogiri-and-xslt/ -->
|
75
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
76
|
+
<!-- It slightly missindents with method="html", at least on the file I tried. -->
|
77
|
+
<xsl:output method="xml" encoding="utf-8"/>
|
78
|
+
|
79
|
+
<!--
|
80
|
+
Producting HTML 5 doctype is a PITA, as per
|
81
|
+
http://stackoverflow.com/questions/3387127/set-html5-doctype-with-xslt
|
82
|
+
|
83
|
+
Let's just do it from Ruby.
|
84
|
+
-->
|
85
|
+
<!-- <xsl:output method="html" encoding="utf-8" indent="yes" /> -->
|
86
|
+
<!-- <xsl:output method="html" version="5.0" encoding="UTF-8" indent="yes" /> -->
|
87
|
+
|
88
|
+
<!-- <xsl:text disable-output-escaping="yes"><!DOCTYPE html></xsl:text> -->
|
89
|
+
|
90
|
+
<!-- <xsl:template match="/">
|
91
|
+
<xsl:text disable-output-escaping='yes'><!DOCTYPE html></xsl:text>
|
92
|
+
</xsl:template> -->
|
93
|
+
|
94
|
+
<xsl:param name="indent-increment" select="' '"/>
|
95
|
+
|
96
|
+
<xsl:template name="newline">
|
97
|
+
<xsl:text disable-output-escaping="yes">
|
98
|
+
</xsl:text>
|
99
|
+
</xsl:template>
|
100
|
+
|
101
|
+
<xsl:template match="comment() | processing-instruction()">
|
102
|
+
<xsl:param name="indent" select="''"/>
|
103
|
+
<xsl:call-template name="newline"/>
|
104
|
+
<xsl:value-of select="$indent"/>
|
105
|
+
<xsl:copy />
|
106
|
+
</xsl:template>
|
107
|
+
|
108
|
+
<xsl:template match="text()">
|
109
|
+
<xsl:param name="indent" select="''"/>
|
110
|
+
<xsl:call-template name="newline"/>
|
111
|
+
<xsl:value-of select="$indent"/>
|
112
|
+
<xsl:value-of select="normalize-space(.)"/>
|
113
|
+
</xsl:template>
|
114
|
+
|
115
|
+
<xsl:template match="text()[normalize-space(.)='']"/>
|
116
|
+
|
117
|
+
<xsl:template match="*">
|
118
|
+
<xsl:param name="indent" select="''"/>
|
119
|
+
<xsl:call-template name="newline"/>
|
120
|
+
<xsl:value-of select="$indent"/>
|
121
|
+
<xsl:choose>
|
122
|
+
<xsl:when test="count(child::*) > 0">
|
123
|
+
<xsl:copy>
|
124
|
+
<xsl:copy-of select="@*"/>
|
125
|
+
<xsl:apply-templates select="*|text()">
|
126
|
+
<xsl:with-param name="indent" select="concat ($indent, $indent-increment)"/>
|
127
|
+
</xsl:apply-templates>
|
128
|
+
<xsl:call-template name="newline"/>
|
129
|
+
<xsl:value-of select="$indent"/>
|
130
|
+
</xsl:copy>
|
131
|
+
</xsl:when>
|
132
|
+
<xsl:otherwise>
|
133
|
+
<xsl:copy-of select="."/>
|
134
|
+
</xsl:otherwise>
|
135
|
+
</xsl:choose>
|
136
|
+
</xsl:template>
|
137
|
+
</xsl:stylesheet>
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: assets-squasher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- https://github.com/botanicus
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: It takes an HTML file, traverses over its scripts and stylesheets and
|
28
|
+
minify them all into one file using UglifyJS2 and UglifyCSS. Meant primarily for
|
29
|
+
single page apps.
|
30
|
+
email: james@101ideas.cz
|
31
|
+
executables:
|
32
|
+
- assets-squasher
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- README.md
|
37
|
+
- bin/assets-squasher
|
38
|
+
homepage: https://github.com/botanicus/assets-squasher
|
39
|
+
licenses:
|
40
|
+
- MIT
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project: assets-squasher
|
58
|
+
rubygems_version: 2.2.2
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: Assets squasher for single page apps.
|
62
|
+
test_files: []
|