blix-assets 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.
@@ -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
@@ -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: []