hanami-assets 1.3.5 → 2.1.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +92 -314
- data/hanami-assets.gemspec +26 -33
- data/lib/hanami/assets/asset.rb +83 -0
- data/lib/hanami/assets/base_url.rb +64 -0
- data/lib/hanami/assets/config.rb +106 -0
- data/lib/hanami/assets/errors.rb +46 -0
- data/lib/hanami/assets/version.rb +2 -2
- data/lib/hanami/assets.rb +61 -143
- data/lib/hanami-assets.rb +3 -0
- metadata +33 -115
- data/lib/hanami/assets/bundler/asset.rb +0 -100
- data/lib/hanami/assets/bundler/compressor.rb +0 -63
- data/lib/hanami/assets/bundler/manifest_entry.rb +0 -64
- data/lib/hanami/assets/bundler.rb +0 -154
- data/lib/hanami/assets/cache.rb +0 -102
- data/lib/hanami/assets/compiler.rb +0 -287
- data/lib/hanami/assets/compilers/less.rb +0 -31
- data/lib/hanami/assets/compilers/sass.rb +0 -61
- data/lib/hanami/assets/compressors/abstract.rb +0 -119
- data/lib/hanami/assets/compressors/builtin_javascript.rb +0 -36
- data/lib/hanami/assets/compressors/builtin_stylesheet.rb +0 -57
- data/lib/hanami/assets/compressors/closure_javascript.rb +0 -25
- data/lib/hanami/assets/compressors/javascript.rb +0 -77
- data/lib/hanami/assets/compressors/jsmin.rb +0 -284
- data/lib/hanami/assets/compressors/null_compressor.rb +0 -19
- data/lib/hanami/assets/compressors/sass_stylesheet.rb +0 -36
- data/lib/hanami/assets/compressors/stylesheet.rb +0 -77
- data/lib/hanami/assets/compressors/uglifier_javascript.rb +0 -25
- data/lib/hanami/assets/compressors/yui_javascript.rb +0 -25
- data/lib/hanami/assets/compressors/yui_stylesheet.rb +0 -25
- data/lib/hanami/assets/config/global_sources.rb +0 -52
- data/lib/hanami/assets/config/manifest.rb +0 -142
- data/lib/hanami/assets/config/sources.rb +0 -80
- data/lib/hanami/assets/configuration.rb +0 -657
- data/lib/hanami/assets/helpers.rb +0 -945
- data/lib/hanami/assets/precompiler.rb +0 -97
data/lib/hanami/assets/cache.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "pathname"
|
4
|
-
|
5
|
-
module Hanami
|
6
|
-
module Assets
|
7
|
-
# Store assets references when compile mode is on.
|
8
|
-
#
|
9
|
-
# This is especially useful in development mode, where we want to compile
|
10
|
-
# only the assets that were changed from last browser refresh.
|
11
|
-
#
|
12
|
-
# @since 0.1.0
|
13
|
-
# @api private
|
14
|
-
class Cache
|
15
|
-
# File cache entry
|
16
|
-
#
|
17
|
-
# @since 0.3.0
|
18
|
-
# @api private
|
19
|
-
class File
|
20
|
-
# @since 0.3.0
|
21
|
-
# @api private
|
22
|
-
def initialize(file, mtime: nil, dependencies: nil)
|
23
|
-
@file = file.is_a?(String) ? Pathname.new(file) : file
|
24
|
-
@mtime = mtime || @file.mtime.utc.to_i
|
25
|
-
|
26
|
-
@dependencies = (dependencies || []).map { |d| self.class.new(d) }
|
27
|
-
end
|
28
|
-
|
29
|
-
# @since 0.3.0
|
30
|
-
# @api private
|
31
|
-
def modified?(other)
|
32
|
-
file = other.is_a?(self.class) ? other : self.class.new(other)
|
33
|
-
|
34
|
-
if dependencies?
|
35
|
-
modified_dependencies?(file) ||
|
36
|
-
mtime <= file.mtime
|
37
|
-
else
|
38
|
-
mtime < file.mtime
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
protected
|
43
|
-
|
44
|
-
# @since 0.3.0
|
45
|
-
# @api private
|
46
|
-
attr_reader :mtime
|
47
|
-
|
48
|
-
# @since 0.3.0
|
49
|
-
# @api private
|
50
|
-
attr_reader :dependencies
|
51
|
-
|
52
|
-
# @since 0.3.0
|
53
|
-
# @api private
|
54
|
-
def modified_dependencies?(other)
|
55
|
-
dependencies.all? { |dep| dep.mtime > other.mtime }
|
56
|
-
end
|
57
|
-
|
58
|
-
# @since 0.3.0
|
59
|
-
# @api private
|
60
|
-
def dependencies?
|
61
|
-
dependencies.any?
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Return a new instance
|
66
|
-
#
|
67
|
-
# @return [Hanami::Assets::Cache] a new instance
|
68
|
-
def initialize
|
69
|
-
@data = Hash.new { |h, k| h[k] = File.new(k, mtime: 0) }
|
70
|
-
@mutex = Mutex.new
|
71
|
-
end
|
72
|
-
|
73
|
-
# Check if the given file was modified
|
74
|
-
#
|
75
|
-
# @param file [String,Pathname] the file path
|
76
|
-
#
|
77
|
-
# @return [TrueClass,FalseClass] the result of the check
|
78
|
-
#
|
79
|
-
# @since 0.3.0
|
80
|
-
# @api private
|
81
|
-
def modified?(file)
|
82
|
-
@mutex.synchronize do
|
83
|
-
@data[file.to_s].modified?(file)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Store the given file reference
|
88
|
-
#
|
89
|
-
# @param file [String,Pathname] the file path
|
90
|
-
#
|
91
|
-
# @return [TrueClass,FalseClass] the result of the check
|
92
|
-
#
|
93
|
-
# @since 0.1.0
|
94
|
-
# @api private
|
95
|
-
def store(file, dependencies = nil)
|
96
|
-
@mutex.synchronize do
|
97
|
-
@data[file.to_s] = File.new(file, dependencies: dependencies)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
@@ -1,287 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "set"
|
4
|
-
require "find"
|
5
|
-
require "hanami/utils/class_attribute"
|
6
|
-
|
7
|
-
module Hanami
|
8
|
-
module Assets
|
9
|
-
# Missing Asset error
|
10
|
-
class MissingAsset < Error
|
11
|
-
def initialize(name, sources)
|
12
|
-
sources = sources.map(&:to_s).join(", ")
|
13
|
-
super("Missing asset: `#{name}' (sources: #{sources})")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# Unknown Asset Engine error
|
18
|
-
class UnknownAssetEngine < Error
|
19
|
-
def initialize(source)
|
20
|
-
super("No asset engine registered for `#{::File.basename(source)}'")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Assets compiler
|
25
|
-
#
|
26
|
-
# It compiles assets that needs to be preprocessed (eg. Sass or ES6) into
|
27
|
-
# the destination directory.
|
28
|
-
#
|
29
|
-
# Vanilla javascripts or stylesheets are just copied over.
|
30
|
-
#
|
31
|
-
# @since 0.1.0
|
32
|
-
# @api private
|
33
|
-
class Compiler
|
34
|
-
# @since 0.1.0
|
35
|
-
# @api private
|
36
|
-
DEFAULT_PERMISSIONS = 0o644
|
37
|
-
|
38
|
-
# @since 0.1.0
|
39
|
-
# @api private
|
40
|
-
COMPILE_PATTERN = "*.*.*" # Example hello.js.es6
|
41
|
-
|
42
|
-
# @since 0.1.0
|
43
|
-
# @api private
|
44
|
-
EXTENSIONS = {".js" => true, ".css" => true, ".map" => true}.freeze
|
45
|
-
|
46
|
-
include Utils::ClassAttribute
|
47
|
-
|
48
|
-
# @since 0.3.0
|
49
|
-
# @api private
|
50
|
-
class_attribute :subclasses
|
51
|
-
self.subclasses = Set.new
|
52
|
-
|
53
|
-
# @since 0.3.0
|
54
|
-
# @api private
|
55
|
-
def self.inherited(subclass)
|
56
|
-
super
|
57
|
-
subclasses.add(subclass)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Compile the given asset
|
61
|
-
#
|
62
|
-
# @param configuration [Hanami::Assets::Configuration] the application
|
63
|
-
# configuration associated with the given asset
|
64
|
-
#
|
65
|
-
# @param name [String] the asset path
|
66
|
-
#
|
67
|
-
# @since 0.1.0
|
68
|
-
# @api private
|
69
|
-
def self.compile(configuration, name)
|
70
|
-
return unless configuration.compile
|
71
|
-
|
72
|
-
require "tilt"
|
73
|
-
require "hanami/assets/cache"
|
74
|
-
require "hanami/assets/compilers/sass"
|
75
|
-
require "hanami/assets/compilers/less"
|
76
|
-
fabricate(configuration, name).compile
|
77
|
-
end
|
78
|
-
|
79
|
-
# @since 0.3.0
|
80
|
-
# @api private
|
81
|
-
def self.fabricate(configuration, name)
|
82
|
-
source = configuration.source(name)
|
83
|
-
engine = (subclasses + [self]).find do |klass|
|
84
|
-
klass.eligible?(source)
|
85
|
-
end
|
86
|
-
|
87
|
-
engine.new(configuration, name)
|
88
|
-
end
|
89
|
-
|
90
|
-
# @since 0.3.0
|
91
|
-
# @api private
|
92
|
-
def self.eligible?(_name)
|
93
|
-
true
|
94
|
-
end
|
95
|
-
|
96
|
-
# Assets cache
|
97
|
-
#
|
98
|
-
# @since 0.1.0
|
99
|
-
# @api private
|
100
|
-
#
|
101
|
-
# @see Hanami::Assets::Cache
|
102
|
-
def self.cache
|
103
|
-
@@cache ||= Assets::Cache.new # rubocop:disable Style/ClassVars
|
104
|
-
end
|
105
|
-
|
106
|
-
# Return a new instance
|
107
|
-
#
|
108
|
-
# @param configuration [Hanami::Assets::Configuration] the application
|
109
|
-
# configuration associated with the given asset
|
110
|
-
#
|
111
|
-
# @param name [String] the asset path
|
112
|
-
#
|
113
|
-
# @return [Hanami::Assets::Compiler] a new instance
|
114
|
-
#
|
115
|
-
# @since 0.1.0
|
116
|
-
# @api private
|
117
|
-
def initialize(configuration, name)
|
118
|
-
@configuration = configuration
|
119
|
-
@name = Pathname.new(name)
|
120
|
-
end
|
121
|
-
|
122
|
-
# Compile the asset
|
123
|
-
#
|
124
|
-
# @raise [Hanami::Assets::MissingAsset] if the asset can't be found in
|
125
|
-
# sources
|
126
|
-
#
|
127
|
-
# @since 0.1.0
|
128
|
-
# @api private
|
129
|
-
def compile
|
130
|
-
raise MissingAsset.new(@name, @configuration.sources) unless exist?
|
131
|
-
return unless modified?
|
132
|
-
|
133
|
-
if compile?
|
134
|
-
compile!
|
135
|
-
else
|
136
|
-
copy!
|
137
|
-
end
|
138
|
-
|
139
|
-
cache!
|
140
|
-
end
|
141
|
-
|
142
|
-
private
|
143
|
-
|
144
|
-
# @since 0.1.0
|
145
|
-
# @api private
|
146
|
-
def source
|
147
|
-
@source ||= @configuration.source(@name)
|
148
|
-
end
|
149
|
-
|
150
|
-
# @since 0.1.0
|
151
|
-
# @api private
|
152
|
-
def destination
|
153
|
-
@destination ||= @configuration.destination_directory.join(destination_name)
|
154
|
-
end
|
155
|
-
|
156
|
-
# @since 1.3.0
|
157
|
-
# @api private
|
158
|
-
def relative_destination_name(name: @name, add_prefix: true)
|
159
|
-
result = name.to_s
|
160
|
-
base_dir = @configuration.base_directories.detect { |dir| result.start_with?(dir) }
|
161
|
-
if base_dir
|
162
|
-
prefix = @configuration.prefix
|
163
|
-
base_dir = prefix.join(base_dir) if add_prefix
|
164
|
-
result = name.relative_path_from(Pathname.new(base_dir))
|
165
|
-
end
|
166
|
-
result
|
167
|
-
end
|
168
|
-
|
169
|
-
# @since 1.3.0
|
170
|
-
# @api private
|
171
|
-
def absolute_destination_name
|
172
|
-
result = ::File.basename(@name)
|
173
|
-
@configuration.sources.each do |source|
|
174
|
-
if @name.to_s.start_with?(source.to_s)
|
175
|
-
result = @name.relative_path_from(source)
|
176
|
-
break
|
177
|
-
end
|
178
|
-
end
|
179
|
-
relative_destination_name(name: Pathname.new(result), add_prefix: false)
|
180
|
-
end
|
181
|
-
|
182
|
-
# @since 1.3.0
|
183
|
-
# @api private
|
184
|
-
def destination_name
|
185
|
-
result = destination_path
|
186
|
-
|
187
|
-
if compile?
|
188
|
-
result.scan(/\A[[[:alnum:]][\-\_]]*\.[[\w]]*/).first || result
|
189
|
-
else
|
190
|
-
result
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
# @since 1.3.1
|
195
|
-
# @api private
|
196
|
-
def destination_path
|
197
|
-
if @configuration.nested
|
198
|
-
@name.relative? ? relative_destination_name : absolute_destination_name
|
199
|
-
else
|
200
|
-
::File.basename(@name)
|
201
|
-
end.to_s
|
202
|
-
end
|
203
|
-
|
204
|
-
# @since 0.1.0
|
205
|
-
# @api private
|
206
|
-
def exist?
|
207
|
-
!source.nil? &&
|
208
|
-
source.exist?
|
209
|
-
end
|
210
|
-
|
211
|
-
# @since 0.3.0
|
212
|
-
# @api private
|
213
|
-
def modified?
|
214
|
-
!destination.exist? ||
|
215
|
-
cache.modified?(source)
|
216
|
-
end
|
217
|
-
|
218
|
-
# @since 0.1.0
|
219
|
-
# @api private
|
220
|
-
def compile?
|
221
|
-
@compile ||= ::File.fnmatch(COMPILE_PATTERN, ::File.basename(source.to_s)) &&
|
222
|
-
!EXTENSIONS[::File.extname(source.to_s)]
|
223
|
-
end
|
224
|
-
|
225
|
-
# @since 0.1.0
|
226
|
-
# @api private
|
227
|
-
def compile!
|
228
|
-
write { renderer.render }
|
229
|
-
rescue RuntimeError
|
230
|
-
raise UnknownAssetEngine.new(source)
|
231
|
-
end
|
232
|
-
|
233
|
-
# @since 0.1.0
|
234
|
-
# @api private
|
235
|
-
def copy!
|
236
|
-
write { source.binread }
|
237
|
-
end
|
238
|
-
|
239
|
-
# @since 0.1.0
|
240
|
-
# @api private
|
241
|
-
def cache!
|
242
|
-
cache.store(source, dependencies)
|
243
|
-
end
|
244
|
-
|
245
|
-
# @since 0.1.0
|
246
|
-
# @api private
|
247
|
-
def write
|
248
|
-
destination.dirname.mkpath
|
249
|
-
destination.open(File::WRONLY | File::TRUNC | File::CREAT | File::BINARY, DEFAULT_PERMISSIONS) do |file|
|
250
|
-
file.write(yield)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
# @since 0.1.0
|
255
|
-
# @api private
|
256
|
-
def cache
|
257
|
-
self.class.cache
|
258
|
-
end
|
259
|
-
|
260
|
-
# @since 0.3.0
|
261
|
-
# @api private
|
262
|
-
def renderer
|
263
|
-
Tilt.new(source)
|
264
|
-
end
|
265
|
-
|
266
|
-
# @since 0.3.0
|
267
|
-
# @api private
|
268
|
-
def dependencies
|
269
|
-
nil
|
270
|
-
end
|
271
|
-
|
272
|
-
# @since 0.3.0
|
273
|
-
# @api private
|
274
|
-
def load_paths
|
275
|
-
result = []
|
276
|
-
|
277
|
-
@configuration.sources.each do |source|
|
278
|
-
Find.find(source) do |path|
|
279
|
-
result << path if File.directory?(path)
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
result
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Hanami
|
4
|
-
module Assets
|
5
|
-
module Compilers
|
6
|
-
# LESS compiler
|
7
|
-
#
|
8
|
-
# @since 0.3.0
|
9
|
-
# @api private
|
10
|
-
class Less < Compiler
|
11
|
-
# @since 0.3.0
|
12
|
-
# @api private
|
13
|
-
EXTENSIONS = /\.(less)\z/.freeze
|
14
|
-
|
15
|
-
# @since 0.3.0
|
16
|
-
# @api private
|
17
|
-
def self.eligible?(name)
|
18
|
-
name.to_s =~ EXTENSIONS
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
# @since 0.3.0
|
24
|
-
# @api private
|
25
|
-
def renderer
|
26
|
-
Tilt.new(source, nil, paths: load_paths)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Hanami
|
4
|
-
module Assets
|
5
|
-
module Compilers
|
6
|
-
# Sass/SCSS Compiler
|
7
|
-
#
|
8
|
-
# @since 0.3.0
|
9
|
-
# @api private
|
10
|
-
class Sass < Compiler
|
11
|
-
# @since 0.3.0
|
12
|
-
# @api private
|
13
|
-
EXTENSIONS = /\.(sass|scss)\z/.freeze
|
14
|
-
|
15
|
-
# @since 0.3.0
|
16
|
-
# @api private
|
17
|
-
def self.eligible?(name)
|
18
|
-
name.to_s =~ EXTENSIONS
|
19
|
-
end
|
20
|
-
|
21
|
-
# @since 1.3.3
|
22
|
-
# @api private
|
23
|
-
def initialize(*)
|
24
|
-
super
|
25
|
-
require "sassc"
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
# @since 0.3.0
|
31
|
-
# @api private
|
32
|
-
def renderer
|
33
|
-
@renderer ||=
|
34
|
-
::SassC::Engine.new(
|
35
|
-
source.read,
|
36
|
-
syntax: target_syntax,
|
37
|
-
load_paths: load_paths
|
38
|
-
)
|
39
|
-
end
|
40
|
-
|
41
|
-
# @since 0.3.0
|
42
|
-
# @api private
|
43
|
-
def dependencies
|
44
|
-
renderer.dependencies.map(&:filename)
|
45
|
-
rescue source::NotRenderedError
|
46
|
-
[]
|
47
|
-
end
|
48
|
-
|
49
|
-
# @since 1.3.2
|
50
|
-
# @api private
|
51
|
-
def target_syntax
|
52
|
-
if source.extname =~ /sass\z/.freeze
|
53
|
-
:sass
|
54
|
-
else
|
55
|
-
:scss
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,119 +0,0 @@
|
|
1
|
-
require 'hanami/utils/string'
|
2
|
-
require 'hanami/utils/class'
|
3
|
-
|
4
|
-
module Hanami
|
5
|
-
module Assets
|
6
|
-
module Compressors
|
7
|
-
# Unknown compressor error
|
8
|
-
#
|
9
|
-
# It's raised when trying to load an unknown compressor.
|
10
|
-
#
|
11
|
-
# @since 0.1.0
|
12
|
-
# @api private
|
13
|
-
#
|
14
|
-
# @see Hanami::Assets::Configuration#javascript_compressor
|
15
|
-
# @see Hanami::Assets::Configuration#stylesheet_compressor
|
16
|
-
# @see Hanami::Assets::Compressors::Abstract#for
|
17
|
-
class UnknownCompressorError < Error
|
18
|
-
# @since 0.1.0
|
19
|
-
# @api private
|
20
|
-
def initialize(type, engine_name)
|
21
|
-
super("Unknown #{ type } compressor: :#{ engine_name }")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Abstract base class for compressors.
|
26
|
-
#
|
27
|
-
# Don't use this class directly, but please use subclasses instead.
|
28
|
-
#
|
29
|
-
# @since 0.1.0
|
30
|
-
# @api private
|
31
|
-
class Abstract
|
32
|
-
# Compress the given asset
|
33
|
-
#
|
34
|
-
# @param filename [String, Pathname] the absolute path to the asset
|
35
|
-
#
|
36
|
-
# @return [String] the compressed asset
|
37
|
-
#
|
38
|
-
# @since 0.1.0
|
39
|
-
# @api private
|
40
|
-
def compress(filename)
|
41
|
-
compressor.compress(
|
42
|
-
read(filename)
|
43
|
-
)
|
44
|
-
end
|
45
|
-
|
46
|
-
protected
|
47
|
-
# @since 0.1.0
|
48
|
-
# @api private
|
49
|
-
attr_reader :compressor
|
50
|
-
|
51
|
-
# Read the contents of given filename
|
52
|
-
#
|
53
|
-
# @param filename [String, Pathname] the absolute path to the asset
|
54
|
-
#
|
55
|
-
# @return [String] the contents of asset
|
56
|
-
#
|
57
|
-
# @since 0.1.0
|
58
|
-
# @api private
|
59
|
-
def read(filename)
|
60
|
-
::File.read(filename)
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
# Factory for compressors.
|
66
|
-
#
|
67
|
-
# It loads a compressor for the given name.
|
68
|
-
#
|
69
|
-
# @abstract Please use this method from the subclasses
|
70
|
-
#
|
71
|
-
# @param engine_name [Symbol,String,NilClass,#compress] the name of the
|
72
|
-
# engine to load or an instance of an engine
|
73
|
-
#
|
74
|
-
# @return [Hanami::Assets::Compressors::Abstract] returns a concrete
|
75
|
-
# implementation of a compressor
|
76
|
-
#
|
77
|
-
# @raise [Hanami::Assets::Compressors::UnknownCompressorError] when the
|
78
|
-
# given name refers to an unknown compressor engine
|
79
|
-
#
|
80
|
-
# @since 0.1.0
|
81
|
-
# @api private
|
82
|
-
def self.for(engine_name)
|
83
|
-
case engine_name
|
84
|
-
when Symbol, String
|
85
|
-
load_engine(name, engine_name)
|
86
|
-
when nil
|
87
|
-
require 'hanami/assets/compressors/null_compressor'
|
88
|
-
NullCompressor.new
|
89
|
-
else
|
90
|
-
engine_name
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# Load the compressor for the given type and engine name.
|
95
|
-
#
|
96
|
-
# @param type [String] asset type (eg. "Javascript" or "Stylesheet")
|
97
|
-
# @param engine_name [Symbol,String] the name of the engine to load (eg. `:yui`)
|
98
|
-
#
|
99
|
-
# @return [Hanami::Assets::Compress::Abstract] returns a concrete
|
100
|
-
# implementation of a compressor
|
101
|
-
#
|
102
|
-
# @since 0.1.0
|
103
|
-
# @api private
|
104
|
-
def self.load_engine(type, engine_name)
|
105
|
-
type = Utils::String.demodulize(type)
|
106
|
-
|
107
|
-
require "hanami/assets/compressors/#{ engine_name }_#{ Utils::String.underscore(type) }"
|
108
|
-
Utils::Class.load!("#{ Utils::String.classify(engine_name) }#{ type }", Hanami::Assets::Compressors).new
|
109
|
-
rescue LoadError
|
110
|
-
raise UnknownCompressorError.new(type, engine_name)
|
111
|
-
end
|
112
|
-
|
113
|
-
class << self
|
114
|
-
private :for, :load_engine
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'hanami/assets/compressors/javascript'
|
2
|
-
require_relative './jsmin'
|
3
|
-
|
4
|
-
module Hanami
|
5
|
-
module Assets
|
6
|
-
module Compressors
|
7
|
-
# Builtin compressor for stylesheet
|
8
|
-
#
|
9
|
-
# This is a port of jsmin
|
10
|
-
# Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
11
|
-
#
|
12
|
-
# This Ruby port was implemented by Ryan Grove (@rgrove) as work for
|
13
|
-
# <tt>jsmin</tt> gem.
|
14
|
-
#
|
15
|
-
# Copyright (c) 2008-2012 Ryan Grove
|
16
|
-
#
|
17
|
-
# @since 0.1.0
|
18
|
-
# @api private
|
19
|
-
#
|
20
|
-
# @see https://github.com/sbecker/asset_packager
|
21
|
-
class BuiltinJavascript < Javascript
|
22
|
-
def initialize
|
23
|
-
@compressor = JSMin
|
24
|
-
end
|
25
|
-
|
26
|
-
# @since 0.1.0
|
27
|
-
# @api private
|
28
|
-
def compress(filename)
|
29
|
-
compressor.minify(
|
30
|
-
read(filename)
|
31
|
-
)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'hanami/assets/compressors/stylesheet'
|
2
|
-
|
3
|
-
module Hanami
|
4
|
-
module Assets
|
5
|
-
module Compressors
|
6
|
-
# Builtin compressor for stylesheet
|
7
|
-
#
|
8
|
-
# This is a basic algorithm based on Scott Becker (@sbecker) work on
|
9
|
-
# <tt>asset_packager</tt> gem.
|
10
|
-
#
|
11
|
-
# Copyright (c) 2006-2008 Scott Becker
|
12
|
-
#
|
13
|
-
# @since 0.1.0
|
14
|
-
# @api private
|
15
|
-
#
|
16
|
-
# @see https://github.com/sbecker/asset_packager
|
17
|
-
class BuiltinStylesheet < Stylesheet
|
18
|
-
# @since 0.1.0
|
19
|
-
# @api private
|
20
|
-
SPACE_REPLACEMENT = " ".freeze
|
21
|
-
|
22
|
-
# @since 0.1.0
|
23
|
-
# @api private
|
24
|
-
COMMENTS_REPLACEMENT = "".freeze
|
25
|
-
|
26
|
-
# @since 0.1.0
|
27
|
-
# @api private
|
28
|
-
LINE_BREAKS_REPLACEMENT = "}\n".freeze
|
29
|
-
|
30
|
-
# @since 0.1.0
|
31
|
-
# @api private
|
32
|
-
LAST_BREAK_REPLACEMENT = "".freeze
|
33
|
-
|
34
|
-
# @since 0.1.0
|
35
|
-
# @api private
|
36
|
-
INSIDE_LEFT_BRACKET_REPLACEMENT = " {".freeze
|
37
|
-
|
38
|
-
# @since 0.1.0
|
39
|
-
# @api private
|
40
|
-
INSIDE_RIGHT_BRACKET_REPLACEMENT = "}".freeze
|
41
|
-
|
42
|
-
# @since 0.1.0
|
43
|
-
# @api private
|
44
|
-
def compress(filename)
|
45
|
-
result = read(filename)
|
46
|
-
result.gsub!(/\s+/, SPACE_REPLACEMENT) # collapse space
|
47
|
-
result.gsub!(/\/\*(.*?)\*\/ /, COMMENTS_REPLACEMENT) # remove comments - caution, might want to remove this if using css hacks
|
48
|
-
result.gsub!(/\} /, LINE_BREAKS_REPLACEMENT) # add line breaks
|
49
|
-
result.gsub!(/\n$/, LAST_BREAK_REPLACEMENT) # remove last break
|
50
|
-
result.gsub!(/ \{ /, INSIDE_LEFT_BRACKET_REPLACEMENT) # trim inside brackets
|
51
|
-
result.gsub!(/; \}/, INSIDE_RIGHT_BRACKET_REPLACEMENT) # trim inside brackets
|
52
|
-
result
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|