blix-assets 0.1.5
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/LICENSE +25 -0
- data/README.md +127 -0
- data/lib/blix/assets.rb +20 -0
- data/lib/blix/assets/asset_manager.rb +265 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5ae57089bbdbcfd6502c2d9971c8426586255a4741ea496203b583450ba8e9ae
|
4
|
+
data.tar.gz: e8a0acfb4dcc36a8f19825ddf1076ac205359e3e6e29e6b89f4836500f6a4761
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a31cfcb6ae272fea115afdffc9799b226633c123edd8b7e24d03048742f8691789649fd2635e75336c0c9fdb2ddeb33f5c4be46d3b8b1131bf32ec920f58fa77
|
7
|
+
data.tar.gz: 4e68d177b42d011ab740d23e7dd5068cc045f37a1f4cdd61846aae6fb36b1db909c6d0cfffac89c42092610df1b028d9cd542925e84a7d8cb09425a9ba67f0ab
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Clive Andrews
|
4
|
+
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person
|
7
|
+
obtaining a copy of this software and associated documentation
|
8
|
+
files (the "Software"), to deal in the Software without
|
9
|
+
restriction, including without limitation the rights to use,
|
10
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
copies of the Software, and to permit persons to whom the
|
12
|
+
Software is furnished to do so, subject to the following
|
13
|
+
conditions:
|
14
|
+
|
15
|
+
The above copyright notice and this permission notice shall be
|
16
|
+
included in all copies or substantial portions of the Software.
|
17
|
+
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
20
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
22
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
23
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
24
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
25
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
## INSTALLATION
|
2
|
+
|
3
|
+
gem install blix-assets
|
4
|
+
|
5
|
+
|
6
|
+
## Manage Asset Files
|
7
|
+
|
8
|
+
#### using the asset pipeline
|
9
|
+
|
10
|
+
the assets are served by your asset pipeline ( sprockets) and the link to the asset in your html
|
11
|
+
is the asset name pure and simple.
|
12
|
+
|
13
|
+
eg:
|
14
|
+
|
15
|
+
<script src="/assets/application.js" type="text/javascript"></script>
|
16
|
+
|
17
|
+
#### using compiled assets
|
18
|
+
|
19
|
+
a hash is added to the asset name to ensure that it is unique. This allows the asset to be cached indefinitely on the
|
20
|
+
browser.
|
21
|
+
|
22
|
+
eg:
|
23
|
+
|
24
|
+
<script src="/assets/application-59D3331242D65ECC.js" type="text/javascript"></script>
|
25
|
+
|
26
|
+
#### template helper
|
27
|
+
|
28
|
+
in order to use the relevant version user the *asset_path* helper in you template. The PRODUCTION flag should indicate
|
29
|
+
if you are in development mode (false) or in production mode/compiled assets mode (true).
|
30
|
+
|
31
|
+
eg:
|
32
|
+
|
33
|
+
<script src="<%= Blix::AssetManager.asset_path('/assets/application.js',PRODUCTION) %>" type="text/javascript"></script>
|
34
|
+
|
35
|
+
<%= Blix::AssetManager.asset_tag('/assets/application.js',PRODUCTION) %>
|
36
|
+
|
37
|
+
<%= Blix::AssetManager.asset_tag('/assets/main.css',PRODUCTION, :media=>'screen') %>
|
38
|
+
|
39
|
+
if you are using blix_rest then there is a helper defined ..
|
40
|
+
|
41
|
+
<script src="<%= asset_path('/assets/application.js') %>" type="text/javascript"></script>
|
42
|
+
|
43
|
+
or the complete tag ..
|
44
|
+
|
45
|
+
<%= asset_tag('/assets/application.js') %>
|
46
|
+
|
47
|
+
<%= asset_tag('/static/man.css', :media=>'screen') %>
|
48
|
+
|
49
|
+
to enable this helper you have to `require 'blix/rest'` first and then `require 'blix/assets'`
|
50
|
+
|
51
|
+
##### inline assets
|
52
|
+
|
53
|
+
assets can also be inlined which results in the contents of the compiled
|
54
|
+
assets to be inlined in *production* mode only.
|
55
|
+
|
56
|
+
In development mode a link to the asset is used.
|
57
|
+
|
58
|
+
<%= asset_tag('/assets/application.js', :inline=>true ) %>
|
59
|
+
|
60
|
+
<%= asset_tag('/static/main.css', :media=>'screen', :inline=>true) %>
|
61
|
+
|
62
|
+
## Mount points in templates
|
63
|
+
|
64
|
+
use the following helpers to expand any filenames to include a mount point
|
65
|
+
in your templates.
|
66
|
+
|
67
|
+
Blix::AssetManager.set_path_root( '/myapp')
|
68
|
+
|
69
|
+
Blix::AssetManager.full_path('/images/icon.png') ==> '/myapp/images/icon.png'
|
70
|
+
|
71
|
+
## Compiling Assets
|
72
|
+
|
73
|
+
ensure that the destination dictory exists and that the config directory
|
74
|
+
'config/assets' also exists !!
|
75
|
+
|
76
|
+
For the destination directory use a path relative to your applications working directory.
|
77
|
+
|
78
|
+
This will ensure that the file can be found in your production environment as well as in your
|
79
|
+
development environment.
|
80
|
+
|
81
|
+
require 'blix/assets'
|
82
|
+
|
83
|
+
DEST = File.join("www","assets") # where the asset is to be written
|
84
|
+
|
85
|
+
data = environment[name].to_s # the compiled asset data
|
86
|
+
|
87
|
+
Blix::AssetManager.write_asset(DEST,"application.js",data)
|
88
|
+
|
89
|
+
it is also possible to force a version number on the asset instead of a generated stamp
|
90
|
+
|
91
|
+
Blix::AssetManager.write_asset(DEST,"application.js",data, :version=>"1.2.3")
|
92
|
+
|
93
|
+
|
94
|
+
## Generate a static index.html
|
95
|
+
|
96
|
+
it is possible to generate a static index.html with the correct assets within your asset compile script.
|
97
|
+
|
98
|
+
you will need an index.html.erb file with the <%= Blix::AssetManager.asset_tag .. %> code
|
99
|
+
|
100
|
+
and set your PRODUCTION variable to true in the compile script. In your config.ru set PRODUCTION to false in
|
101
|
+
development mode.
|
102
|
+
|
103
|
+
eg ...
|
104
|
+
|
105
|
+
index.html.erb
|
106
|
+
|
107
|
+
....
|
108
|
+
....
|
109
|
+
<head>
|
110
|
+
<%= Blix::AssetManager.asset_tag('/assets/application.js',PRODUCTION) %>
|
111
|
+
<%= Blix::AssetManager.asset_tag('/assets/main.css',PRODUCTION, :media=>'screen') %>
|
112
|
+
|
113
|
+
</head>
|
114
|
+
|
115
|
+
compile_assets.rb ..
|
116
|
+
|
117
|
+
ROOT = Dir.pwd
|
118
|
+
PRODUCTION = true
|
119
|
+
DEST = File.join("www","assets")
|
120
|
+
....
|
121
|
+
....
|
122
|
+
Blix::AssetManager.write_asset(DEST,"application.js",environment["application.js"].to_s)
|
123
|
+
Blix::AssetManager.write_asset(DEST,"main.css",environment["main.css"].to_s)
|
124
|
+
....
|
125
|
+
....
|
126
|
+
|
127
|
+
File.write File.join("www","index.html"),environment['index.html'].to_s
|
data/lib/blix/assets.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'blix/assets/asset_manager'
|
2
|
+
|
3
|
+
# add the asset_path method to the Controller if it is being used.
|
4
|
+
if defined? Blix::Rest
|
5
|
+
module Blix
|
6
|
+
module Rest
|
7
|
+
class Controller
|
8
|
+
def asset_path(partial_path)
|
9
|
+
AssetManager.asset_path(full_path(partial_path),mode_production?)
|
10
|
+
end
|
11
|
+
|
12
|
+
# make a complete html tag for an asset
|
13
|
+
def asset_tag(partial_path,opts={})
|
14
|
+
AssetManager.asset_tag(full_path(partial_path),mode_production?,opts)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
|
5
|
+
# manage your asset names
|
6
|
+
#
|
7
|
+
# a config directory contains a file for each managed asset using its generic name. In the file
|
8
|
+
# is the unique stamp that is used to find the name of the latest version of the asset.
|
9
|
+
# config format consists of a filestamp part and md5 hash part
|
10
|
+
#
|
11
|
+
# ensure that your config dir exists (default config/assets)
|
12
|
+
# ensure that you destination dir exists ( eg public/assets )
|
13
|
+
#
|
14
|
+
# then use something like this to compile your assets...
|
15
|
+
#
|
16
|
+
# ASSETS = ['main.js', 'main.css']
|
17
|
+
# ASSETS.each do |name|
|
18
|
+
#
|
19
|
+
# str = environment[name].to_s
|
20
|
+
#
|
21
|
+
# if File.extname(name) == ".css"
|
22
|
+
# engine = Sass::Engine.new(str, :syntax => :scss, :style => :compressed)
|
23
|
+
# str = engine.render
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# AssetManager.if_modified(name,str,:rewrite=>true) do |a|
|
27
|
+
#
|
28
|
+
# filename = File.join(ROOT,"www","assets",a.newname)
|
29
|
+
# puts "writing #{name} to #{filename}"
|
30
|
+
# File.write filename,str
|
31
|
+
#
|
32
|
+
# File.unlink File.join(ROOT,"www","assets",a.oldname) if a.oldname
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
#
|
38
|
+
# then within your erb template or whatever ...
|
39
|
+
#
|
40
|
+
# <script src="<%= AssetManager.asset_path('/assets/main.js',flag) %>" type="text/javascript"></script>
|
41
|
+
#
|
42
|
+
# where flag indicates if the static compiled version should be used ( ie with hash) or the plain name ( served by sprockets pipeline)
|
43
|
+
|
44
|
+
module Blix
|
45
|
+
class AssetManager
|
46
|
+
|
47
|
+
AssetInfo = Struct.new(:newname, :oldname)
|
48
|
+
class << self
|
49
|
+
|
50
|
+
def config_dir
|
51
|
+
@config_dir || 'config/assets'
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_writer :config_dir
|
55
|
+
|
56
|
+
# the name of the file to write to
|
57
|
+
def filename(name)
|
58
|
+
name
|
59
|
+
end
|
60
|
+
|
61
|
+
def asset_root
|
62
|
+
@asset_root || 'assets'
|
63
|
+
end
|
64
|
+
|
65
|
+
attr_writer :asset_root
|
66
|
+
|
67
|
+
# write the compiled asset here
|
68
|
+
def dest_path(name)
|
69
|
+
File.join(asset_dir, filename(name))
|
70
|
+
end
|
71
|
+
|
72
|
+
# write the config info here
|
73
|
+
def config_path(name)
|
74
|
+
File.join(config_dir, filename(name) + '.conf')
|
75
|
+
end
|
76
|
+
|
77
|
+
# yield the old and new name to a block if
|
78
|
+
# the asset has been modified
|
79
|
+
def if_modified(destination, name, data, opts = {})
|
80
|
+
new_hash = Digest::MD5.hexdigest data
|
81
|
+
|
82
|
+
ext = File.extname(name)[1..-1]
|
83
|
+
base = name.split('.')[0]
|
84
|
+
confname = base + '.' + ext
|
85
|
+
config = get_config(confname)
|
86
|
+
|
87
|
+
if !config ||
|
88
|
+
(config[:hash] != new_hash || (config[:destination] != destination)) ||
|
89
|
+
opts[:version] && (opts[:version] != config[:version])
|
90
|
+
|
91
|
+
stamp = get_filestamp
|
92
|
+
info = AssetInfo.new
|
93
|
+
info.newname = "#{base}-#{opts[:version] || stamp}.#{ext}"
|
94
|
+
info.oldname = config && "#{base}-#{config[:version] || config[:stamp]}.#{ext}"
|
95
|
+
set_config(destination, confname, new_hash, stamp, opts[:version])
|
96
|
+
yield(info)
|
97
|
+
|
98
|
+
elsif opts[:rewrite] # rewrite the same data to the same asset as before
|
99
|
+
|
100
|
+
info = AssetInfo.new
|
101
|
+
info.newname = config && "#{base}-#{config[:version] || config[:stamp]}.#{ext}"
|
102
|
+
info.oldname = nil
|
103
|
+
yield(info)
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# generate a unique suffix for the file
|
109
|
+
def get_filestamp
|
110
|
+
now = Time.now
|
111
|
+
str = '%X' % now.to_i
|
112
|
+
str += '%X' % now.usec
|
113
|
+
str += '%X' % rand(9999)
|
114
|
+
str
|
115
|
+
end
|
116
|
+
|
117
|
+
# get config data from file or nil if file does not exist
|
118
|
+
def get_config(name)
|
119
|
+
return nil unless File.exist? config_path(name)
|
120
|
+
|
121
|
+
data = File.read config_path(name)
|
122
|
+
parts = data.split('|')
|
123
|
+
out = { :hash => parts[1], :stamp => parts[0], :destination => parts[3] }
|
124
|
+
out[:version] = parts[2] unless parts[2].empty?
|
125
|
+
out
|
126
|
+
end
|
127
|
+
|
128
|
+
# set the config data
|
129
|
+
def set_config(destination, name, hash, stamp, version = nil)
|
130
|
+
File.write(config_path(name), stamp + '|' + hash + '|' + version.to_s + '|' + destination)
|
131
|
+
true
|
132
|
+
end
|
133
|
+
|
134
|
+
# cache asset name store
|
135
|
+
def cache
|
136
|
+
@cache ||= {}
|
137
|
+
end
|
138
|
+
|
139
|
+
# retrieve and cache the full asset name
|
140
|
+
def get_asset_name(name)
|
141
|
+
cache[name] ||= begin
|
142
|
+
config = get_config(name)
|
143
|
+
raise "ERROR : config file for asset:#{name} not found !!" unless config
|
144
|
+
|
145
|
+
ext = File.extname(name)[1..-1]
|
146
|
+
base = name.split('.')[0]
|
147
|
+
base + '-' + (config[:version] || config[:stamp]) + '.' + ext
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# retrieve and cache the full asset name
|
152
|
+
def get_asset_version_name(name)
|
153
|
+
cache[name] ||= begin
|
154
|
+
config = get_config(name)
|
155
|
+
raise "ERROR : config file for asset:#{name} not found !!" unless config
|
156
|
+
|
157
|
+
ext = File.extname(name)[1..-1]
|
158
|
+
base = name.split('.')[0]
|
159
|
+
base + '-' + config[:version] + '.' + ext
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def set_path_root(root)
|
164
|
+
root = root.to_s
|
165
|
+
root = '/' + root if root[0, 1] != '/'
|
166
|
+
root += '/' if root[-1, 1] != '/'
|
167
|
+
@path_root = root
|
168
|
+
@path_root_length = @path_root.length - 1
|
169
|
+
end
|
170
|
+
|
171
|
+
def path_root
|
172
|
+
@path_root || '/'
|
173
|
+
end
|
174
|
+
|
175
|
+
attr_reader :path_root_length
|
176
|
+
|
177
|
+
# calculate the full path of the asset
|
178
|
+
def full_path(path)
|
179
|
+
path = path[1..-1] if path[0, 1] == '/'
|
180
|
+
path_root + path
|
181
|
+
end
|
182
|
+
|
183
|
+
# caculate the correct asset path depending on the mode of execution
|
184
|
+
def asset_path(path, mode_production = false)
|
185
|
+
partial_path = full_path(path)
|
186
|
+
if mode_production
|
187
|
+
asset_name = File.basename(partial_path)
|
188
|
+
dir_name = File.dirname(partial_path)
|
189
|
+
if dir_name == '.'
|
190
|
+
AssetManager.get_asset_name(asset_name)
|
191
|
+
else
|
192
|
+
File.join(dir_name, AssetManager.get_asset_name(asset_name))
|
193
|
+
end
|
194
|
+
else
|
195
|
+
partial_path
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# return the location of the compiled asset
|
200
|
+
def file_path(path)
|
201
|
+
name = File.basename(path)
|
202
|
+
config = get_config(name)
|
203
|
+
raise "ERROR : config file for asset:#{name} not found !!" unless config
|
204
|
+
|
205
|
+
ext = File.extname(name)[1..-1]
|
206
|
+
base = name.split('.')[0]
|
207
|
+
config[:destination] + '/' + base + '-' + (config[:version] || config[:stamp]) + '.' + ext
|
208
|
+
end
|
209
|
+
|
210
|
+
# write a complete asset tag html string
|
211
|
+
def asset_tag(partial_path, mode_production = false, opts = {})
|
212
|
+
name = File.basename(partial_path)
|
213
|
+
type = File.extname(partial_path)
|
214
|
+
inline = opts.delete(:inline)
|
215
|
+
opts_str = opts.to_a.map { |v| "#{v[0]}=\"#{v[1]}\"" }.join(' ')
|
216
|
+
|
217
|
+
if type == '.css'
|
218
|
+
if mode_production && inline
|
219
|
+
content = cache['///' + name] ||= File.read(file_path(partial_path))
|
220
|
+
%(<style type="text/css" #{opts_str} >\n#{content}</style>)
|
221
|
+
else
|
222
|
+
%(<link rel="stylesheet" href="#{asset_path(partial_path, mode_production)}" type="text/css" #{opts_str} >)
|
223
|
+
end
|
224
|
+
elsif type == '.js'
|
225
|
+
if mode_production && inline
|
226
|
+
# insert js here if in production mode
|
227
|
+
content = cache['///' + name] ||= File.read(file_path(partial_path))
|
228
|
+
%(<script>\n#{content}</script>)
|
229
|
+
else
|
230
|
+
%(<script src="#{asset_path(partial_path, mode_production)}" type="text/javascript"></script>)
|
231
|
+
end
|
232
|
+
else
|
233
|
+
raise "unknown tag for file extension:#{partial_path}"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# write an asset to the destination directory
|
238
|
+
def write_asset(destination, name, str, opts = {})
|
239
|
+
opts = opts.dup
|
240
|
+
opts[:rewrite] = true unless opts.key?(:rewrite)
|
241
|
+
raise "asset destination directory must exist:#{destination}" unless Dir.exist?(destination)
|
242
|
+
|
243
|
+
puts "#{red('WARNING !')} Use a relative path to the destination directory" if destination[0] == '/' # with colour red
|
244
|
+
if_modified(destination, name, str, opts) do |a|
|
245
|
+
outfile = File.join(destination, a.newname)
|
246
|
+
File.write outfile, str
|
247
|
+
if a.oldname && (a.oldname != a.newname)
|
248
|
+
oldfilename = File.join(destination, a.oldname)
|
249
|
+
File.unlink oldfilename if File.exist?(oldfilename)
|
250
|
+
end
|
251
|
+
outfile
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
private
|
256
|
+
|
257
|
+
# escape text for printing in red on console.
|
258
|
+
def red(text)
|
259
|
+
"\e[31m#{text}\e[0m"
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blix-assets
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Clive Andrews
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-08-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Basic Routines for managing Compiled Assets
|
28
|
+
email:
|
29
|
+
- gems@realitybites.eu
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files:
|
33
|
+
- README.md
|
34
|
+
- LICENSE
|
35
|
+
files:
|
36
|
+
- LICENSE
|
37
|
+
- README.md
|
38
|
+
- lib/blix/assets.rb
|
39
|
+
- lib/blix/assets/asset_manager.rb
|
40
|
+
homepage: https://github.com/realbite/blix-rest
|
41
|
+
licenses:
|
42
|
+
- MIT
|
43
|
+
metadata: {}
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubygems_version: 3.1.4
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Basic Asset Management Routines
|
63
|
+
test_files: []
|