gluey 0.2.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2fde00ea1efaad06ddc4780ae8cd89ba0608d2c3
4
+ data.tar.gz: d51d6124fbecf62a1bab250a7e8f62e0f9fda44d
5
+ SHA512:
6
+ metadata.gz: 8be79aa84654f1e3b1ce3f6e220cb8bd767eef34593503809c06d92ed01c7f024ce1ef2f9878cffc35bff50983557b562e8dcebd1f93822b808297a4a27c083b
7
+ data.tar.gz: 177013b823b9a1bd66aaa8773e5fc501df265ceef0550afb15547b3962288598a53a5feb1f0cd336e3419f38c5bd1c11045660c3e20e31655131b428c1f8bbba
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gluey.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 doooby
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # Gluey
2
+
3
+ This is my custom alternative for processing assets in ruby web apps. Firt, there was just dislike in sprockets
4
+ (and their integration into rails), but then i realized it's not that big a deal to write my own caching and processing system.
5
+ This has unlimited abilities, because it's very easy to write custom directives (that headers in assets that you know from
6
+ sprockets). For example, you can precompile handlebars a nd insert them into page's js file as an object (it cannot be easier).
7
+ You can append, prepend, insert (...) other files, merge them into one asset, that you wanth to hit on
8
+ particular http path. There is no docs nor test for now, and probably never will be, but the code should not be hard
9
+ to read, so if you're interested, just digg into the code itself.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'gluey'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install gluey
26
+
27
+ ## Usage
28
+
29
+ look at my nesselsburg2 integration (a repository just next door)
30
+
31
+ ## Contributing
32
+
33
+ 1. Fork it ( https://github.com/[my-github-username]/gluey/fork )
34
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
35
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
36
+ 4. Push to the branch (`git push origin my-new-feature`)
37
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/gluey.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'gluey/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'gluey'
7
+ spec.version = Gluey::VERSION
8
+ spec.authors = ['doooby']
9
+ spec.email = ['zelazk.o@email.cz']
10
+ spec.summary = 'Rails\' asset pipelane replacement'
11
+ spec.description = %q{Concatenating and processing asset files with possibly complicated dependencies.}
12
+ # spec.homepage = ""
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ # spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ # spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.7'
21
+ spec.add_development_dependency 'rake', '~> 10.0'
22
+ end
@@ -0,0 +1,29 @@
1
+ require_relative 'single_file'
2
+
3
+ module Gluey::Dependencies
4
+ class Directory < SingleFile
5
+
6
+ def initialize(dir, dir_pattern=nil)
7
+ @dir_pattern = "#{dir}/#{ dir_pattern || '**/*' }"
8
+ super dir
9
+ end
10
+
11
+ def actualize
12
+ @files_list = files_list
13
+ super
14
+ end
15
+
16
+ def changed?
17
+ @files_list != files_list
18
+ end
19
+
20
+ def exists?
21
+ Dir.exists? @file
22
+ end
23
+
24
+ def files_list
25
+ Dir[@dir_pattern]
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,62 @@
1
+ require 'handlebars'
2
+ require_relative 'directory'
3
+
4
+ module Gluey::Dependencies
5
+ class Handlebars_bundle < SingleFile
6
+
7
+ def initialize(dir, logical_path, context)
8
+ tmp_dir = "#{context.tmp_path}/.texts_bundle"
9
+ Dir.mkdir tmp_dir unless Dir.exists? tmp_dir
10
+ @cache_path = "#{tmp_dir}/#{logical_path.gsub '/', '-'}"
11
+ Dir.mkdir @cache_path unless Dir.exists? @cache_path
12
+
13
+ @dir_dep = ::Gluey::Dependencies::Directory.new(dir, '**/*.hb')
14
+ @dependencies = []
15
+ super "#{@cache_path}.hb_bundle"
16
+ end
17
+
18
+ def changed?
19
+ @dependencies.any?{|d| d.changed?} || @dir_dep.changed? || (File.mtime(@file).to_i != @mtime rescue true)
20
+ end
21
+
22
+ def actualize
23
+ # remove deleted files
24
+ @dependencies.delete_if{|dep| !dep.exists? }
25
+ # add new files
26
+ new_files = (@dir_dep.files_list - @dependencies.map(&:file)).map do |f|
27
+ template = f[/#{@dir_dep.file}\/(.+)\.hb$/, 1]
28
+ ::Gluey::Dependencies::SingleFile.new f, template: template,
29
+ hb_precompiled: "#{@cache_path}/#{template.gsub '/', '-'}"
30
+ end
31
+ @dependencies.concat new_files
32
+ @dir_dep.actualize
33
+
34
+ # re-precompile changed
35
+ handlebars_context = ::Handlebars::Context.new
36
+ @dependencies.each do |dep|
37
+ next if !dep.changed? && File.exists?(dep.data[:hb_precompiled])
38
+ dep.actualize
39
+ precompile_output = handlebars_context.precompile File.read(dep.file)
40
+ File.write dep.data[:hb_precompiled], precompile_output
41
+ end
42
+
43
+ write_bundle
44
+ @mtime = File.mtime(@file).to_i
45
+ self
46
+ end
47
+
48
+ private
49
+
50
+ def write_bundle
51
+ File.open @file, 'w' do |f|
52
+ f.write '{'
53
+ @dependencies.each_with_index do |dep, i|
54
+ f.write "#{', ' if i!=0}\"#{dep.data[:template]}\": "
55
+ f.write File.read(dep.data[:hb_precompiled])
56
+ end
57
+ f.write '}'
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,29 @@
1
+ module Gluey::Dependencies
2
+ class SingleFile
3
+
4
+ attr_reader :file, :data
5
+
6
+ def initialize(file, **data)
7
+ @file = file
8
+ @data = data
9
+ end
10
+
11
+ def actualize
12
+ @mtime = File.mtime(@file).to_i
13
+ self
14
+ end
15
+
16
+ def changed?
17
+ File.mtime(@file).to_i != @mtime rescue true
18
+ end
19
+
20
+ def exists?
21
+ File.exists? @file
22
+ end
23
+
24
+ def ==(other)
25
+ @file == other.file
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,62 @@
1
+ require_relative 'directory'
2
+
3
+ module Gluey::Dependencies
4
+ class TextsBundle < SingleFile
5
+ JS_ESCAPE_MAP = {
6
+ '\\' => '\\\\',
7
+ "\r\n" => '\n',
8
+ "\n" => '\n',
9
+ "\r" => '\n',
10
+ '"' => '\\"',
11
+ "'" => "\\'"
12
+ }
13
+
14
+ def initialize(dir, logical_path, context)
15
+ tmp_dir = "#{context.tmp_path}/.texts_bundle"
16
+ Dir.mkdir tmp_dir unless Dir.exists? tmp_dir
17
+ @cache_path = "#{tmp_dir}/#{logical_path.gsub '/', '-'}"
18
+ Dir.mkdir @cache_path unless Dir.exists? @cache_path
19
+
20
+ @dir_dep = ::Gluey::Dependencies::Directory.new(dir, '**/*')
21
+ @dependencies = []
22
+ super "#{@cache_path}.texts_bundle"
23
+ end
24
+
25
+ def changed?
26
+ @dependencies.any?{|d| d.changed?} || @dir_dep.changed? || (File.mtime(@file).to_i != @mtime rescue true)
27
+ end
28
+
29
+ def actualize
30
+ # remove deleted files
31
+ @dependencies.delete_if{|dep| !dep.exists? }
32
+ # add new files
33
+ new_files = (@dir_dep.files_list - @dependencies.map(&:file)).map do |f|
34
+ text_name = f[/#{@dir_dep.file}\/(.+)$/, 1]
35
+ ::Gluey::Dependencies::SingleFile.new f, text_name: text_name
36
+ end
37
+ @dependencies.concat new_files
38
+ @dir_dep.actualize
39
+ @dependencies.each{|dep| dep.actualize if dep.changed? }
40
+
41
+ write_bundle
42
+ @mtime = File.mtime(@file).to_i
43
+ self
44
+ end
45
+
46
+ private
47
+
48
+ def write_bundle
49
+ File.open @file, 'w' do |f|
50
+ f.write '{'
51
+ @dependencies.each_with_index do |dep, i|
52
+ f.write "#{', ' if i!=0}\"#{dep.data[:text_name]}\": "
53
+ text = File.read dep.file
54
+ text.gsub!(/(\\|\r\n|[\n\r"'])/u){|match| JS_ESCAPE_MAP[match] }
55
+ f.write "\"#{text}\""
56
+ end
57
+ f.write '}'
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,4 @@
1
+ module Gluey
2
+ class FileNotFound < StandardError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Gluey
2
+ class ItemNotListed < StandardError
3
+ end
4
+ end
@@ -0,0 +1,25 @@
1
+ module Gluey::Glues
2
+ class Base
3
+
4
+ def initialize(context, material)
5
+ @context = context
6
+ @material = material
7
+ end
8
+
9
+ def process(base_file, dependecies)
10
+ read_base_file base_file
11
+ end
12
+
13
+ def read_base_file(file)
14
+ raw_content = File.read(file)
15
+ file[-4..-1]=='.erb' ? ERB.new(raw_content).result : raw_content
16
+ end
17
+
18
+ end
19
+
20
+ def self.load(name, *addons_names)
21
+ require_relative name
22
+ addons_names.flatten.each{|an| require_relative "#{name}/#{an}_addons" }
23
+ end
24
+
25
+ end
@@ -0,0 +1,24 @@
1
+ require_relative '../../dependencies/handlebars_bundle'
2
+
3
+ module Gluey::Glues
4
+ class JsScript < Script
5
+
6
+ def pre_replace_with_handlebars(args)
7
+ dir = File.expand_path("../#{args[1]}", @base_file)
8
+ raise "cannot find dir containing handlebars templates for script=#{@base_file}" unless dir && Dir.exists?(dir)
9
+
10
+ logical_path = dir[/(?:^#{@context.root_path}\/)?(.+)$/, 1]
11
+ key = "dep:hb_bundle:#{logical_path}:#{@material.name}"
12
+ hb_dep = @context.cache[key]
13
+ unless hb_dep
14
+ hb_dep = ::Gluey::Dependencies::Handlebars_bundle.new dir, logical_path, @context
15
+ @context.cache[key] = hb_dep
16
+ end
17
+
18
+ hb_dep.actualize if hb_dep.changed?
19
+ @dependencies << hb_dep
20
+ @script.gsub! /"%#{args[0]}%"/, File.read(hb_dep.file)
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,53 @@
1
+ require_relative 'script'
2
+ require_relative '../dependencies/texts_bundle'
3
+
4
+ module Gluey::Glues
5
+ class JsScript < Script
6
+
7
+ def post_strict(_)
8
+ @output = "'use strict';\n#{@output}"
9
+ end
10
+
11
+ def post_enclose(_)
12
+ @output = "(function(){\n#{@output}\n}());"
13
+ end
14
+
15
+ def post_strict_mode(_)
16
+ @output = "'use strict';\n#{@output}"
17
+ end
18
+
19
+ def pre_replace(args)
20
+ file = find_nested_file(args[1])
21
+ cached_file, deps = get_nested_piece file
22
+ @dependencies.concat deps
23
+ @script.gsub! /"%#{args[0]}%"/, File.read(cached_file)
24
+ end
25
+
26
+ def pre_return(args)
27
+ @script = "#{@script}\nreturn #{args.first};"
28
+ end
29
+
30
+ def post_return(_)
31
+ @output = "(function(){\n#{@output}\n}())"
32
+ end
33
+
34
+ end
35
+
36
+ def pre_replace_with_texts_bundle(args)
37
+ dir = File.expand_path("../#{args[1]}", @base_file)
38
+ raise "cannot find relative path #{args[1]} for script=#{@base_file}" unless dir && Dir.exists?(dir)
39
+
40
+ logical_path = dir[/(?:^#{@context.root_path}\/)?(.+)$/, 1]
41
+ key = "dep:txt_bundle:#{logical_path}:#{@material.name}"
42
+ hb_dep = @context.cache[key]
43
+ unless hb_dep
44
+ hb_dep = ::Gluey::Dependencies::TextsBundle.new dir, logical_path, @context
45
+ @context.cache[key] = hb_dep
46
+ end
47
+
48
+ hb_dep.actualize if hb_dep.changed?
49
+ @dependencies << hb_dep
50
+ @script.gsub! /"%#{args[0]}%"/, File.read(hb_dep.file)
51
+ end
52
+
53
+ end
@@ -0,0 +1,26 @@
1
+ require 'sass'
2
+ require_relative '../dependencies/single_file'
3
+
4
+ module Gluey::Glues
5
+ class Sass < Base
6
+
7
+ def process(base_file, deps)
8
+ opts = {
9
+ syntax: @material.file_extension.to_sym,
10
+ load_paths: [File.expand_path('..', base_file)],
11
+ cache_store: ::Sass::CacheStores::Filesystem.new("#{@context.tmp_path}/.sass"),
12
+ filename: base_file,
13
+ line_comments: true
14
+ }
15
+ engine = ::Sass::Engine.new(read_base_file(base_file), opts)
16
+ output = engine.render
17
+
18
+ engine.dependencies.each do |dependency|
19
+ deps << ::Gluey::Dependencies::SingleFile.new(dependency.options[:filename]).actualize
20
+ end
21
+
22
+ output
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,84 @@
1
+ require_relative '../dependencies/single_file'
2
+
3
+ module Gluey::Glues
4
+ class Script < Base
5
+
6
+ PREFIXES = ['//'].map{|p| Regexp.escape(p)}
7
+ DIRECTIVES_REGEXP = Regexp.compile "\\A(?:\\s*#{PREFIXES.map{|p| "(?:#{p}=.*\\n?)+"}.join '|'})+"
8
+
9
+ def process(base_file, deps)
10
+ @script, @directives = strip_directives read_base_file(base_file)
11
+ return @script unless @directives
12
+ @dependencies = deps
13
+ @output = ''
14
+ @base_file = base_file
15
+ @marks = {append_self: ->{ @output += @script }}
16
+ @directives.each{|args| directive args, :pre }
17
+ @marks[:append_self].call if @marks[:append_self]
18
+ @directives.each{|args| directive args, :post }
19
+ @output
20
+ end
21
+
22
+ def pre_prepend(args)
23
+ file = find_nested_file(args.first)
24
+ cached_file, deps = get_nested_piece file
25
+ @dependencies.concat deps
26
+ @script = "#{File.read cached_file}#{@script}"
27
+ end
28
+
29
+ def pre_append(args)
30
+ file = find_nested_file(args.first)
31
+ cached_file, deps = get_nested_piece file
32
+ @dependencies.concat deps
33
+ @script = "#{@script}#{File.read cached_file}"
34
+ end
35
+
36
+ def pre_depend_on(args)
37
+ file = find_nested_file(args[1])
38
+ @dependencies << ::Gluey::Dependencies::SingleFile.new(file).actualize
39
+ end
40
+
41
+ private
42
+
43
+ def strip_directives(data)
44
+ script = data
45
+ directives = data[DIRECTIVES_REGEXP]
46
+ if directives
47
+ script = $'
48
+ directives = directives.split("\n").reject{|dir| dir.empty?}.map do |dir|
49
+ dir.strip[/(?:#{PREFIXES.join '|'}=)\s*(.+)/, 1].split (' ')
50
+ end
51
+ end
52
+ return script, directives
53
+ end
54
+
55
+ def directive(dir_array, run)
56
+ method = "#{run}_#{dir_array.first}"
57
+ send method, dir_array[1..-1] if respond_to? method
58
+ end
59
+
60
+ def find_nested_file(rel_path)
61
+ file = File.expand_path("../#{rel_path}", @base_file)
62
+ File.exists?(file) || raise("cannot find '#{rel_path}' from script=#{@base_file}")
63
+ file
64
+ end
65
+
66
+ def get_nested_piece(file)
67
+ path = file[/(?:^#{@context.root_path}\/)?(.+)$/, 1]
68
+ key = "script_piece:#{@material.name}:#{path}"
69
+ cache_file, dependencies = @context.cache[key]
70
+ return cache_file, dependencies if cache_file && File.exists?(cache_file) && !dependencies.any?{|dep| dep.changed?}
71
+
72
+ glue = self.class.new @context, @material
73
+ cache_dir = "#{@context.tmp_path}/.script"
74
+ Dir.mkdir cache_dir unless Dir.exists? cache_dir
75
+ cache_file = "#{cache_dir}/#{path}.#{@material.name}"
76
+ dependencies = [::Gluey::Dependencies::SingleFile.new(file).actualize]
77
+ FileUtils.mkdir_p cache_file[0..(cache_file.rindex('/')-1)]
78
+ File.write cache_file, glue.process(file, dependencies)
79
+ @context.cache[key] = [cache_file, dependencies]
80
+ return cache_file, dependencies
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,74 @@
1
+ require_relative 'exceptions/file_not_found'
2
+
3
+ class Gluey::Material
4
+
5
+ attr_reader :name, :glue
6
+ attr_accessor :asset, :file_extension, :public_dir
7
+
8
+ def initialize(name, glue, context)
9
+ @name = name.to_sym
10
+ @glue = glue
11
+ @context = context
12
+ @asset = name.to_s
13
+ @paths = []
14
+ @items = []
15
+ yield self if block_given?
16
+ @file_extension ||= @asset.dup
17
+ end
18
+
19
+ def add_path(path)
20
+ @paths << path
21
+ end
22
+
23
+ def add_item(declaration)
24
+ @items << declaration
25
+ end
26
+
27
+ def is_listed?(path, file=nil)
28
+ @items.any? do |items_declaration|
29
+ case items_declaration
30
+ when String
31
+ path == items_declaration
32
+ when Regexp
33
+ path =~ items_declaration
34
+ when Proc
35
+ items_declaration[path, file]
36
+ end
37
+ end
38
+ end
39
+
40
+ def to_s
41
+ "Material #{@name}"
42
+ end
43
+
44
+ def find_base_file(path)
45
+ paths.each do |base_path|
46
+ p = "#{base_path}/#{path}.#{@file_extension}"; return p if File.exists? p
47
+ p = "#{p}.erb"; return p if File.exists? p
48
+ p = "#{base_path}/#{path}/index.#{@file_extension}"; return p if File.exists? p
49
+ p = "#{p}.erb"; return p if File.exists? p
50
+ end
51
+ raise(::Gluey::FileNotFound.new "#{to_s} cannot find base file for #{path}")
52
+ end
53
+
54
+ def list_all_items
55
+ list = []
56
+ paths.map do |base_path|
57
+ glob_path = "#{base_path}/**/*.#{@file_extension}"
58
+ files = Dir[glob_path] + Dir["#{glob_path}.erb"]
59
+ files.select do |file|
60
+ path = file[/^#{base_path}\/(.+)\.#{@file_extension}(?:\.erb)?$/, 1]
61
+ path.gsub! /\/index$/, ''
62
+ list << path if is_listed? path, file
63
+ end
64
+ end
65
+ list.uniq
66
+ end
67
+
68
+ private
69
+
70
+ def paths
71
+ @paths.map{|p| "#{@context.root_path}/#{p}"}
72
+ end
73
+
74
+ end
@@ -0,0 +1,86 @@
1
+ require_relative 'tools'
2
+
3
+ module Gluey::Tools
4
+
5
+ def self.build_into_public_dir(workshop, warehouse, public_dir='public/assets', **builders)
6
+ public_dirs = workshop.materials.values.inject({}) do |h, m|
7
+ h[m.name] = "#{workshop.root_path}/#{m.public_dir || public_dir}"
8
+ h
9
+ end
10
+
11
+ built = []
12
+ move_it = -> (cache_file, file) { FileUtils.mv cache_file, file }
13
+ self.each_asset_file workshop, warehouse do |cache_file, type, path|
14
+ file = "#{public_dirs[type]}/#{path}"
15
+ next if File.exists? file
16
+ FileUtils.mkdir_p file[0..(file.rindex('/')-1)]
17
+ (builders[type] || move_it)[cache_file, file]
18
+ built << file
19
+ puts "created #{file}"
20
+ end
21
+ return built
22
+ end
23
+
24
+ def self.clear_public_dir(workshop, warehouse, versions=2, public_dir='public/assets')
25
+ public_dirs = workshop.materials.values.inject({}) do |h, m|
26
+ h[m.name] = "#{workshop.root_path}/#{m.public_dir || public_dir}"
27
+ h
28
+ end
29
+
30
+ # process existing files into assets
31
+ eas_regexp = /^#{workshop.root_path}\/(.+)$/
32
+ assets = public_dirs.values.uniq.map{|dir| Dir["#{dir}/**/*.*.*"]}.flatten.
33
+ map{|f| Asset.try_create f[eas_regexp, 1]}.compact
34
+ assets = assets.inject({}){|h, asset| (h[asset.path] ||= []) << asset; h }
35
+
36
+ # items not on list
37
+ on_list = []
38
+ warehouse.assets.each do |type, mater_assets|
39
+ mater_assets.each do |_, real_path|
40
+ file = "#{public_dirs[type]}/#{real_path}"
41
+ asset = Asset.try_create file[eas_regexp, 1]
42
+ on_list << asset
43
+ end
44
+ end
45
+ on_list.map! &:path
46
+ assets.delete_if do |path, asseets_arr|
47
+ unless on_list.include? path
48
+ asseets_arr.each do |some_asset|
49
+ file = "#{workshop.root_path}/#{some_asset.orig_path}"
50
+ File.delete file
51
+ puts "deleted unknown #{file}"
52
+ end
53
+ true
54
+ end
55
+ false
56
+ end
57
+
58
+ # older versions
59
+ assets.values.select{|arr| arr.length > versions}.
60
+ map{|arr| arr.sort.slice 0..(-versions-1) }.compact.flatten.each do |old_asset|
61
+ file = "#{workshop.root_path}/#{old_asset.orig_path}"
62
+ File.delete file
63
+ puts "deleted old #{file}"
64
+ end
65
+ end
66
+
67
+ class Asset < Struct.new(:path, :time_stamp)
68
+
69
+ def self.try_create(file)
70
+ file.match /^([^\.]+)\.(\d+)\.(\w+)$/ do |m|
71
+ new "#{m[1]}.#{m[3]}", m[2]
72
+ end
73
+ end
74
+
75
+ def <=>(other)
76
+ time_stamp <=> other.time_stamp
77
+ end
78
+
79
+ def orig_path
80
+ ret = path.dup
81
+ ret.insert ret.rindex('.'), ".#{time_stamp}"
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,19 @@
1
+ require 'gluey/warehouse'
2
+
3
+ module Gluey::Tools
4
+
5
+ def self.each_asset_file(workshop, warehouse)
6
+ warehouse.assets.each do |type, assets|
7
+ assets.each do |path, real_path|
8
+ cache_file = workshop.fetch_file type, path
9
+ yield cache_file, type, real_path
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.create_uglifier_builder(**opts)
15
+ require 'uglifier'
16
+ ->(a, b){File.write b, ::Uglifier.new(opts.merge! copyright: :none).compile(File.read a)}
17
+ end
18
+
19
+ end
@@ -0,0 +1,3 @@
1
+ module Gluey
2
+ VERSION = '0.2.2'
3
+ end
@@ -0,0 +1,50 @@
1
+ require_relative '../gluey'
2
+ require_relative 'exceptions/item_not_listed'
3
+ require 'json'
4
+
5
+ class Gluey::Warehouse
6
+
7
+ attr_reader :assets
8
+
9
+ def initialize(root, listing_file='assets/gluey_listing.json')
10
+ @listing_file = "#{root}/#{listing_file}"
11
+ read_listing
12
+ end
13
+
14
+ def real_path(asset_type, path)
15
+ listing = @assets[asset_type]
16
+ unless listing
17
+ raise ::Gluey::ItemNotListed.new("Asset type #{asset_type} is not defined! (listing file problem?)")
18
+ end
19
+
20
+ real_path = listing[path]
21
+ unless real_path
22
+ raise ::Gluey::ItemNotListed.new("Unknown asset: #{path}, type=#{asset_type}! (listing file problem?)")
23
+ end
24
+
25
+ real_path
26
+ end
27
+
28
+ def read_listing
29
+ assets = if File.exists? @listing_file
30
+ JSON.parse File.read(@listing_file) rescue {}
31
+ else
32
+ {}
33
+ end
34
+ raise "corrupted listing file at #{@listing_file}" unless assets.is_a? Hash
35
+ @assets = assets.keys.inject({}){|h, asset_type| h[asset_type.to_sym] = assets[asset_type]; h }
36
+ end
37
+
38
+ def write_listing(workshop)
39
+ @assets = workshop.materials.values.inject({}) do |listing, material|
40
+ list = material.list_all_items.inject({}) do |h, path|
41
+ h[path] = workshop.real_path material.name, path
42
+ h
43
+ end
44
+ listing[material.name.to_sym] = list
45
+ listing
46
+ end
47
+ File.write @listing_file, JSON.pretty_generate(@assets)
48
+ end
49
+
50
+ end
@@ -0,0 +1,64 @@
1
+ require_relative '../gluey'
2
+
3
+ require_relative 'exceptions/item_not_listed'
4
+
5
+ require_relative 'material'
6
+ require_relative 'glues/base'
7
+
8
+ class Gluey::Workshop
9
+
10
+ attr_reader :root_path, :tmp_path, :materials, :cache
11
+
12
+ def initialize(root, tmp_dir='tmp/gluey')
13
+ @root_path = root
14
+ @tmp_path = "#{root}/#{tmp_dir}"
15
+ Dir.mkdir @tmp_path unless Dir.exists? @tmp_path
16
+ @materials = {}
17
+ @cache = {}
18
+ end
19
+
20
+ def register_material(name, glue=::Gluey::Glues::Base, &block)
21
+ name = name.to_sym
22
+ material = ::Gluey::Material.new name, glue, self, &block
23
+ @materials[name] = material
24
+ end
25
+
26
+ def fetch_file(material, path)
27
+ # check cache
28
+ cache_key = "lump:#{material}:#{path}"
29
+ file, dependencies = @cache[cache_key]
30
+ if file && File.exists?(file) && !dependencies.any?{|d| d.changed?}
31
+ return file
32
+ end
33
+
34
+ # prepare for processing
35
+ material = @materials[material.to_sym]
36
+ base_file = material.find_base_file path
37
+ file = "#{@tmp_path}/#{path}.#{material.asset}"
38
+ dependencies = [::Gluey::Dependencies::SingleFile.new(base_file).actualize]
39
+ # process
40
+ glue = material.glue.new self, material
41
+ FileUtils.mkdir_p file[0..(file.rindex('/')-1)]
42
+ File.write file, glue.process(base_file, dependencies)
43
+
44
+ # save and return
45
+ @cache[cache_key] = [file, dependencies]
46
+ file
47
+ end
48
+
49
+ def real_path(material, path)
50
+ material = @materials[material.to_sym]
51
+ file = material.find_base_file path
52
+ unless material.is_listed? path, file
53
+ raise ::Gluey::ItemNotListed.new("#{material.to_s} doesn't have enlisted item #{path} (file=#{file}).")
54
+ end
55
+ "#{path}.#{File.mtime(file).to_i}.#{material.asset}"
56
+ end
57
+
58
+ def try_real_path(path)
59
+ path.match /^(.+)\.\d+\.(\w+)$/ do |m|
60
+ yield m[1], m[2]
61
+ end
62
+ end
63
+
64
+ end
data/lib/gluey.rb ADDED
@@ -0,0 +1,2 @@
1
+
2
+ require_relative 'gluey/version'
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gluey
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - doooby
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Concatenating and processing asset files with possibly complicated dependencies.
42
+ email:
43
+ - zelazk.o@email.cz
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - gluey.gemspec
54
+ - lib/gluey.rb
55
+ - lib/gluey/dependencies/directory.rb
56
+ - lib/gluey/dependencies/handlebars_bundle.rb
57
+ - lib/gluey/dependencies/single_file.rb
58
+ - lib/gluey/dependencies/texts_bundle.rb
59
+ - lib/gluey/exceptions/file_not_found.rb
60
+ - lib/gluey/exceptions/item_not_listed.rb
61
+ - lib/gluey/glues/base.rb
62
+ - lib/gluey/glues/js_script.rb
63
+ - lib/gluey/glues/js_script/handlebars_addons.rb
64
+ - lib/gluey/glues/sass.rb
65
+ - lib/gluey/glues/script.rb
66
+ - lib/gluey/material.rb
67
+ - lib/gluey/tools/local_build.rb
68
+ - lib/gluey/tools/tools.rb
69
+ - lib/gluey/version.rb
70
+ - lib/gluey/warehouse.rb
71
+ - lib/gluey/workshop.rb
72
+ homepage:
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.2.2
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Rails' asset pipelane replacement
96
+ test_files: []