spark_engine 1.0.0
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/.gitignore +12 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +34 -0
- data/Rakefile +2 -0
- data/bin/spark +99 -0
- data/lib/spark_engine/assets.rb +8 -0
- data/lib/spark_engine/command/help.rb +86 -0
- data/lib/spark_engine/command/npm.rb +62 -0
- data/lib/spark_engine/command.rb +156 -0
- data/lib/spark_engine/config_data.rb +29 -0
- data/lib/spark_engine/helpers/asset_helpers.rb +66 -0
- data/lib/spark_engine/helpers/layout_helpers.rb +21 -0
- data/lib/spark_engine/middleware.rb +72 -0
- data/lib/spark_engine/plugin/assets/asset.rb +163 -0
- data/lib/spark_engine/plugin/assets/javascripts.rb +83 -0
- data/lib/spark_engine/plugin/assets/stylesheets.rb +88 -0
- data/lib/spark_engine/plugin/assets/svgs.rb +79 -0
- data/lib/spark_engine/plugin.rb +191 -0
- data/lib/spark_engine/sass/engine.rb +21 -0
- data/lib/spark_engine/sass/importer.rb +103 -0
- data/lib/spark_engine/scaffold/gem/.gitignore +18 -0
- data/lib/spark_engine/scaffold/gem/app/assets/images/namespace/.keep +0 -0
- data/lib/spark_engine/scaffold/gem/app/assets/javascripts/namespace/engine.js +3 -0
- data/lib/spark_engine/scaffold/gem/app/assets/stylesheets/namespace/_index.scss +1 -0
- data/lib/spark_engine/scaffold/gem/app/assets/svgs/namespace/.keep +0 -0
- data/lib/spark_engine/scaffold/gem/app/helpers/namespace/application_helper.rb +4 -0
- data/lib/spark_engine/scaffold/gem/app/views/layouts/namespace/default.html.erb +18 -0
- data/lib/spark_engine/scaffold/gem/gem.gemspec +24 -0
- data/lib/spark_engine/scaffold/gem/lib/gem.rb +12 -0
- data/lib/spark_engine/scaffold/gem/site/app/assets/javascripts/application.js +1 -0
- data/lib/spark_engine/scaffold/gem/site/app/assets/stylesheets/application.scss +2 -0
- data/lib/spark_engine/scaffold/gem/site/app/controllers/docs_controller.rb +19 -0
- data/lib/spark_engine/scaffold/gem/site/app/views/docs/index.html.erb +1 -0
- data/lib/spark_engine/scaffold/gem/site/app/views/layouts/application.html.erb +4 -0
- data/lib/spark_engine/scaffold/gem/site/config/application.rb +18 -0
- data/lib/spark_engine/scaffold/gem/site/config/environments/development.rb +13 -0
- data/lib/spark_engine/scaffold/gem/site/config/routes.rb +3 -0
- data/lib/spark_engine/scaffold.rb +191 -0
- data/lib/spark_engine/version.rb +3 -0
- data/lib/spark_engine.rb +106 -0
- data/spark_engine.gemspec +31 -0
- metadata +234 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'action_dispatch/middleware/static'
|
2
|
+
|
3
|
+
module SparkEngine
|
4
|
+
class Application < Rails::Application
|
5
|
+
initializer "static assets" do |app|
|
6
|
+
app.middleware.insert_before(::ActionDispatch::Static, ::ActionDispatch::Static, "#{root}/public")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class StaticAssets
|
11
|
+
|
12
|
+
# Rails 5 middleware patch
|
13
|
+
if SparkEngine.rails5?
|
14
|
+
|
15
|
+
def initialize(app, path, index: 'index', headers: {}, engine_name: nil)
|
16
|
+
@app = app
|
17
|
+
@engine_name = engine_name
|
18
|
+
@file_handler = ActionDispatch::FileHandler.new(path, index: index, headers: headers)
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
req = Rack::Request.new env
|
23
|
+
prefix = File.join Application.config.assets.prefix, @engine_name
|
24
|
+
|
25
|
+
if req.get? || req.head?
|
26
|
+
path = req.path_info.chomp('/'.freeze)
|
27
|
+
|
28
|
+
if path.start_with? prefix
|
29
|
+
path = path.remove /\A#{prefix}\//
|
30
|
+
|
31
|
+
if match = @file_handler.match?(path)
|
32
|
+
req.path_info = match
|
33
|
+
return @file_handler.serve(req)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
@app.call(req.env)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Rails 4 middleware patch
|
42
|
+
else
|
43
|
+
|
44
|
+
def initialize(app, path, cache_control=nil, engine_name: nil)
|
45
|
+
@app = app
|
46
|
+
@engine_name = engine_name
|
47
|
+
@file_handler = ::ActionDispatch::FileHandler.new(path, cache_control)
|
48
|
+
end
|
49
|
+
|
50
|
+
def call(env)
|
51
|
+
prefix = File.join Application.config.assets.prefix, @engine_name
|
52
|
+
|
53
|
+
case env['REQUEST_METHOD']
|
54
|
+
when 'GET', 'HEAD'
|
55
|
+
path = env['PATH_INFO'].chomp('/')
|
56
|
+
|
57
|
+
if path.start_with? prefix
|
58
|
+
path = path.remove /\A#{prefix}\//
|
59
|
+
|
60
|
+
if match = @file_handler.match?(path)
|
61
|
+
env["PATH_INFO"] = match
|
62
|
+
return @file_handler.call(env)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
@app.call(env)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module SparkEngine
|
2
|
+
module Assets
|
3
|
+
class AssetType
|
4
|
+
attr_reader :plugin, :base
|
5
|
+
|
6
|
+
def initialize(plugin, base)
|
7
|
+
@base = base
|
8
|
+
@plugin = plugin
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_files
|
12
|
+
if @files
|
13
|
+
@files
|
14
|
+
else
|
15
|
+
files = Dir[File.join(base, "*.#{ext}")].reject do |f|
|
16
|
+
# Filter out partials
|
17
|
+
File.basename(f).start_with?('_')
|
18
|
+
end
|
19
|
+
|
20
|
+
@files = files if SparkEngine.production?
|
21
|
+
files
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def filter_files(names)
|
26
|
+
|
27
|
+
# Filter names based on asset file locations
|
28
|
+
find_files.select do |f|
|
29
|
+
names.include? File.basename(f).sub(/(\..+)$/,'')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def versioned(path)
|
34
|
+
File.basename(path).sub(/(\.\w+)$/, '-'+plugin.version+'\1')
|
35
|
+
end
|
36
|
+
|
37
|
+
def local_path(file)
|
38
|
+
destination(file).sub(plugin.root+'/','')
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_success(file)
|
42
|
+
log_success "Built: #{local_path(file)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_failure(file)
|
46
|
+
msg = "\nFAILED TO BUILD"
|
47
|
+
msg += ": #{local_path(file)}" if file
|
48
|
+
log_error msg
|
49
|
+
end
|
50
|
+
|
51
|
+
def log_success( msg )
|
52
|
+
STDOUT.puts msg.to_s.colorize(:green)
|
53
|
+
end
|
54
|
+
|
55
|
+
def log_error( msg )
|
56
|
+
STDERR.puts msg.to_s.colorize(:red)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Determine if an NPM module is installed by checking paths with `npm bin`
|
60
|
+
# Returns path to binary if installed
|
61
|
+
def find_node_module(cmd)
|
62
|
+
require 'open3'
|
63
|
+
(@modules ||= {})[cmd] ||= begin
|
64
|
+
|
65
|
+
local = "$(npm bin)/#{cmd}"
|
66
|
+
global = "$(npm -g bin)/#{cmd}"
|
67
|
+
|
68
|
+
if Open3.capture3(local)[2].success?
|
69
|
+
local
|
70
|
+
elsif Open3.capture3(global)[2].success?
|
71
|
+
global
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def npm_command(cmd)
|
78
|
+
cmd = cmd.split(' ')
|
79
|
+
if path = find_node_module(cmd.shift)
|
80
|
+
system "#{path} #{cmd.join(' ')}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def destination(path)
|
85
|
+
plugin.asset_path(versioned(path))
|
86
|
+
end
|
87
|
+
|
88
|
+
def url(path)
|
89
|
+
plugin.asset_url(versioned(path))
|
90
|
+
end
|
91
|
+
|
92
|
+
def urls(names=nil)
|
93
|
+
# If names are passed, look at the basename minus
|
94
|
+
# the extension as build files may have
|
95
|
+
# different extensions than sources
|
96
|
+
names = [names].flatten.compact.map do |n|
|
97
|
+
File.basename(n).sub(/(\..+)$/,'')
|
98
|
+
end
|
99
|
+
|
100
|
+
# Return all asset urls if none were specifically chosen
|
101
|
+
if names.empty?
|
102
|
+
find_files.map{ |file| url(file) }
|
103
|
+
|
104
|
+
# Filter files based on name
|
105
|
+
else
|
106
|
+
filter_files(names).map{ |file| url(file) }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def watch
|
111
|
+
|
112
|
+
@throttle = 4
|
113
|
+
@last_build = 0
|
114
|
+
|
115
|
+
puts "Watching for changes to #{base.sub(plugin.root+'/', '')}...".colorize(:light_yellow)
|
116
|
+
|
117
|
+
Thread.new {
|
118
|
+
listener = Listen.to(base) do |modified, added, removed|
|
119
|
+
change(modified, added, removed)
|
120
|
+
end
|
121
|
+
|
122
|
+
listener.start # not blocking
|
123
|
+
sleep
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
def change(modified, added, removed)
|
128
|
+
return if (Time.now.to_i - @last_build) < @throttle
|
129
|
+
|
130
|
+
puts "Added: #{file_event(added)}".colorize(:light_green) unless added.empty?
|
131
|
+
puts "Removed: #{file_event(removed)}".colorize(:light_red) unless removed.empty?
|
132
|
+
puts "Modified: #{file_event(modified)}".colorize(:light_yellow) unless modified.empty?
|
133
|
+
|
134
|
+
build
|
135
|
+
@last_build = Time.now.to_i
|
136
|
+
end
|
137
|
+
|
138
|
+
def file_event(files)
|
139
|
+
list = files.flat_map { |f| f.sub(base+'/', '') }.join(" \n")
|
140
|
+
list = " \n#{files}" if 1 < files.size
|
141
|
+
|
142
|
+
list
|
143
|
+
end
|
144
|
+
|
145
|
+
def compress(file)
|
146
|
+
return unless SparkEngine.production?
|
147
|
+
|
148
|
+
mtime = File.mtime(file)
|
149
|
+
gz_file = "#{file}.gz"
|
150
|
+
return if File.exist?(gz_file) && File.mtime(gz_file) >= mtime
|
151
|
+
|
152
|
+
File.open(gz_file, "wb") do |dest|
|
153
|
+
gz = Zlib::GzipWriter.new(dest, Zlib::BEST_COMPRESSION)
|
154
|
+
gz.mtime = mtime.to_i
|
155
|
+
IO.copy_stream(open(file), gz)
|
156
|
+
gz.close
|
157
|
+
end
|
158
|
+
|
159
|
+
File.utime(mtime, mtime, gz_file)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module SparkEngine
|
2
|
+
module Assets
|
3
|
+
class Javascripts < AssetType
|
4
|
+
def ext
|
5
|
+
"js"
|
6
|
+
end
|
7
|
+
|
8
|
+
def asset_tag(*args)
|
9
|
+
javascript_include_tag(args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def cache_file(name=nil)
|
13
|
+
SparkEngine.rails_path("tmp/cache/assets/.browserify-cache-#{name}.json")
|
14
|
+
end
|
15
|
+
|
16
|
+
# Find all asset files matching array of names
|
17
|
+
def filter_files(names)
|
18
|
+
[find_files, plugin.svgs.build_paths].flatten.select do |f|
|
19
|
+
names.include? File.basename(f).sub(/(\..+)$/,'')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def build
|
24
|
+
files = find_files
|
25
|
+
FileUtils.mkdir_p(File.dirname(cache_file)) if !files.empty?
|
26
|
+
|
27
|
+
if Open3.capture3("npm ls browserify-incremental")[1].empty?
|
28
|
+
files.each do |file|
|
29
|
+
|
30
|
+
dest = destination(file)
|
31
|
+
|
32
|
+
FileUtils.rm(dest) if File.exists?(dest)
|
33
|
+
|
34
|
+
response = Open3.capture3(build_command(file))
|
35
|
+
|
36
|
+
# If the file exists and is not empty (a failed build is empty)
|
37
|
+
if File.exist?(dest) && !File.read(dest).strip.empty?
|
38
|
+
compress(dest) if SparkEngine.production?
|
39
|
+
build_success file
|
40
|
+
else
|
41
|
+
build_failure file
|
42
|
+
|
43
|
+
response = response.map { |l| l.to_s.split("\n") }.flatten
|
44
|
+
|
45
|
+
response.each do |line|
|
46
|
+
if !line.empty? && # Don't print empty lines
|
47
|
+
!line.match(/node_modules/i) && # Ignore stack traces from installed modules
|
48
|
+
!line.match(/pid (\d+?) exit/i) && # Ignore pid exit stack line
|
49
|
+
!line.match(/\[BABEL\] Note:/i) # Notices from Bable are noisy
|
50
|
+
log_error line.gsub(plugin.root+'/','')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
puts ""
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
log_error "JS BUILD FAILED: browserifyinc NPM module not found.\n" << "Please add browserifyinc to your package.json and run `npm install`"
|
59
|
+
abort
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def npm_path( cmd )
|
64
|
+
File.join SparkEngine.gem_path, "node_modules/.bin", cmd
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_command(file)
|
68
|
+
dest = destination(file).sub(/\.js$/,'')
|
69
|
+
options = "--standalone #{plugin.name} -o #{dest}.js -d"
|
70
|
+
|
71
|
+
cmd = if SparkEngine.production?
|
72
|
+
npm_path "browserify #{file} #{options} -t"
|
73
|
+
else
|
74
|
+
npm_path "browserifyinc --cachefile #{cache_file(File.basename(dest))} #{file} #{options}"
|
75
|
+
end
|
76
|
+
puts "Running: #{cmd}"
|
77
|
+
|
78
|
+
cmd
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'sass'
|
2
|
+
require "autoprefixer-rails"
|
3
|
+
|
4
|
+
module SparkEngine
|
5
|
+
module Assets
|
6
|
+
class Stylesheets < AssetType
|
7
|
+
|
8
|
+
def ext
|
9
|
+
"*[ca]ss"
|
10
|
+
end
|
11
|
+
|
12
|
+
def asset_tag(*args)
|
13
|
+
stylesheet_link_tag(args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def build(ext=nil)
|
17
|
+
files = find_files
|
18
|
+
files = files.reject {|f| !f.match(/\.#{ext}/) } if ext
|
19
|
+
|
20
|
+
files.each do |file|
|
21
|
+
|
22
|
+
begin
|
23
|
+
if File.extname(file).match(/\.css/)
|
24
|
+
build_css(file)
|
25
|
+
elsif File.extname(file).match(/\.s[ca]ss/)
|
26
|
+
build_sass(file)
|
27
|
+
end
|
28
|
+
|
29
|
+
puts build_success(file)
|
30
|
+
|
31
|
+
rescue Exception => e
|
32
|
+
build_failure file
|
33
|
+
|
34
|
+
if e.backtrace.is_a? Array
|
35
|
+
log_error "Error in file: #{local_path(e.backtrace[0])}"
|
36
|
+
end
|
37
|
+
|
38
|
+
log_error " #{e.message}\n" if e.message
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_css(file)
|
44
|
+
css = AutoprefixerRails.process(File.read(file)).css
|
45
|
+
File.open(destination(file), 'w') { |io| io.write(css) }
|
46
|
+
|
47
|
+
compress(destination(file))
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_sass(file)
|
51
|
+
style = SparkEngine.production? ? "compressed" : 'nested'
|
52
|
+
dest = destination(file)
|
53
|
+
|
54
|
+
Sass.logger.log_level = :error if SparkEngine.production?
|
55
|
+
|
56
|
+
css = Sass.compile_file(file, style: style)
|
57
|
+
css = AutoprefixerRails.process(css).css
|
58
|
+
|
59
|
+
File.open(dest, 'w') { |io| io.write(css) }
|
60
|
+
|
61
|
+
compress(dest)
|
62
|
+
end
|
63
|
+
|
64
|
+
def data
|
65
|
+
if @data
|
66
|
+
@data
|
67
|
+
else
|
68
|
+
data = {}
|
69
|
+
|
70
|
+
Dir[File.join(base, "**/*.yml")].each do |file|
|
71
|
+
key = file.sub(base+"/", '').sub(/^_/,'').sub('.yml','')
|
72
|
+
|
73
|
+
data[key] = SassParser.parse(file)
|
74
|
+
end
|
75
|
+
|
76
|
+
@data = data if SparkEngine.production?
|
77
|
+
data
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Convert extension
|
82
|
+
def versioned(file)
|
83
|
+
super(file.sub(/(\.css)?\.s[ca]ss$/i,'.css'))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module SparkEngine
|
2
|
+
module Assets
|
3
|
+
class Svgs < AssetType
|
4
|
+
|
5
|
+
def initialize(plugin, path)
|
6
|
+
|
7
|
+
require 'esvg'
|
8
|
+
|
9
|
+
@plugin = plugin
|
10
|
+
@base = path
|
11
|
+
@svg = esvg
|
12
|
+
end
|
13
|
+
|
14
|
+
def esvg
|
15
|
+
@svg || Esvg.new({
|
16
|
+
config_file: File.join(plugin.root, 'config', 'esvg.yml'),
|
17
|
+
source: @base,
|
18
|
+
assets: plugin.paths[:javascripts],
|
19
|
+
version: plugin.version,
|
20
|
+
build: plugin.destination,
|
21
|
+
temp: SparkEngine.rails_path('tmp/cache/assets'),
|
22
|
+
filename: '_icons.js',
|
23
|
+
compress: SparkEngine.production?,
|
24
|
+
optimize: true,
|
25
|
+
print: false
|
26
|
+
})
|
27
|
+
end
|
28
|
+
|
29
|
+
def ext
|
30
|
+
"svg"
|
31
|
+
end
|
32
|
+
|
33
|
+
def local_path(path)
|
34
|
+
path = File.expand_path(path)
|
35
|
+
|
36
|
+
# Strip all irrelevant sections of the path
|
37
|
+
path.sub(plugin.paths[:javascripts]+'/', '') # written to assets dir
|
38
|
+
.sub(plugin.root+'/','') # writtent to public dir
|
39
|
+
end
|
40
|
+
|
41
|
+
def use(*args)
|
42
|
+
esvg.use(*args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_paths
|
46
|
+
esvg.build_paths.map { |file| file.sub("-#{plugin.version}",'') }
|
47
|
+
end
|
48
|
+
|
49
|
+
def build
|
50
|
+
begin
|
51
|
+
esvg.load_files
|
52
|
+
|
53
|
+
return if esvg.symbols.empty?
|
54
|
+
|
55
|
+
if files = esvg.build
|
56
|
+
files.each do |file|
|
57
|
+
puts build_success(file)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
log_error "FAILED TO BUILD SVGs"
|
61
|
+
end
|
62
|
+
rescue Exception => e
|
63
|
+
log_error "\nFAILED TO BUILD SVGs"
|
64
|
+
|
65
|
+
if e.backtrace && e.backtrace.is_a?(Array)
|
66
|
+
log_error "Error in file: #{local_path(e.backtrace.shift)}"
|
67
|
+
|
68
|
+
e.backtrace.each do |line|
|
69
|
+
log_error local_path(line)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
log_error(" #{e.message}\n") if e.message
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
module SparkEngine
|
2
|
+
class Plugin
|
3
|
+
attr_reader :name, :gem, :engine,
|
4
|
+
:stylesheets, :javascripts, :svgs, :destination
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@name = options.delete(:engine).downcase
|
8
|
+
@gem = Gem.loaded_specs[options.delete(:gem)]
|
9
|
+
config(options)
|
10
|
+
expand_asset_paths
|
11
|
+
|
12
|
+
# Store the gem path for access later when overriding root
|
13
|
+
parent_module.instance_variable_set(:@gem_path, root)
|
14
|
+
parent_module.instance_variable_set(:@spark_plugin_name, name)
|
15
|
+
add_assets
|
16
|
+
end
|
17
|
+
|
18
|
+
def engine_name
|
19
|
+
@engine.name.sub(/::Engine/,'')
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_engine(&block)
|
23
|
+
# Create a new Rails::Engine
|
24
|
+
@engine = parent_module.const_set('Engine', Class.new(Rails::Engine) do
|
25
|
+
|
26
|
+
def spark_plugin_path
|
27
|
+
parent = Object.const_get(self.class.name.sub(/::Engine/,''))
|
28
|
+
Pathname.new parent.instance_variable_get("@gem_path")
|
29
|
+
end
|
30
|
+
|
31
|
+
def config
|
32
|
+
@config ||= Rails::Engine::Configuration.new(spark_plugin_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
engine_name SparkEngine.plugin.name
|
36
|
+
|
37
|
+
require 'spark_engine/middleware'
|
38
|
+
|
39
|
+
initializer "#{name}.static_assets" do |app|
|
40
|
+
if !SparkEngine.rails5? || app.config.public_file_server.enabled
|
41
|
+
app.middleware.insert_after ::ActionDispatch::Static, SparkEngine::StaticAssets, "#{root}/public", engine_name: SparkEngine.plugin.name
|
42
|
+
app.middleware.insert_before ::ActionDispatch::Static, Rack::Deflater
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end)
|
47
|
+
|
48
|
+
@engine.instance_eval(&block) if block_given?
|
49
|
+
end
|
50
|
+
|
51
|
+
def parent_module
|
52
|
+
mods = self.class.to_s.split('::')
|
53
|
+
mods.pop
|
54
|
+
Object.const_get(mods.join('::'))
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_assets
|
58
|
+
@javascripts = Assets::Javascripts.new(self, paths[:javascripts])
|
59
|
+
@stylesheets = Assets::Stylesheets.new(self, paths[:stylesheets])
|
60
|
+
@svgs = Assets::Svgs.new(self, paths[:svgs])
|
61
|
+
end
|
62
|
+
|
63
|
+
def assets(options={})
|
64
|
+
assets = []
|
65
|
+
if options[:select_assets]
|
66
|
+
assets.push @svgs if options[:svg]
|
67
|
+
assets.push @stylesheets if options[:css]
|
68
|
+
assets.push @javascripts if options[:js]
|
69
|
+
else
|
70
|
+
assets = [@svgs, @stylesheets, @javascripts]
|
71
|
+
end
|
72
|
+
|
73
|
+
assets
|
74
|
+
end
|
75
|
+
|
76
|
+
def svgs?
|
77
|
+
@svgs.icons.nil?
|
78
|
+
end
|
79
|
+
|
80
|
+
def build(options={})
|
81
|
+
FileUtils.mkdir_p(asset_path)
|
82
|
+
assets(options).each do |asset|
|
83
|
+
asset.build
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
def watch(options)
|
89
|
+
assets(options).map(&:watch)
|
90
|
+
end
|
91
|
+
|
92
|
+
def asset_root
|
93
|
+
asset_prefix = Rails.application.config.assets.prefix || '/assets'
|
94
|
+
File.join asset_prefix, name
|
95
|
+
end
|
96
|
+
|
97
|
+
def production_root
|
98
|
+
@production_asset_root ||= asset_root
|
99
|
+
end
|
100
|
+
|
101
|
+
def config(options)
|
102
|
+
|
103
|
+
options = {
|
104
|
+
production_asset_root: nil,
|
105
|
+
destination: "public/",
|
106
|
+
root: @gem.full_gem_path,
|
107
|
+
version: @gem.version.to_s,
|
108
|
+
gem_name: @gem.name,
|
109
|
+
paths: {
|
110
|
+
stylesheets: "app/assets/stylesheets/#{name}",
|
111
|
+
javascripts: "app/assets/javascripts/#{name}",
|
112
|
+
images: "app/assets/images/#{name}",
|
113
|
+
svgs: "app/assets/svgs/#{name}",
|
114
|
+
}
|
115
|
+
}.merge(options)
|
116
|
+
|
117
|
+
options.each do |k,v|
|
118
|
+
set_instance(k.to_s,v)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def expand_asset_paths
|
123
|
+
@paths.each do |type, path|
|
124
|
+
@paths[type] = File.join(root, path)
|
125
|
+
end
|
126
|
+
@destination = File.join(root, @destination)
|
127
|
+
end
|
128
|
+
|
129
|
+
def asset_path(file=nil)
|
130
|
+
dest = destination
|
131
|
+
dest = File.join(dest, file) if file
|
132
|
+
dest
|
133
|
+
end
|
134
|
+
|
135
|
+
def asset_url(file=nil)
|
136
|
+
|
137
|
+
path = if SparkEngine.production? && !ENV[name.upcase + '_FORCE_LOCAL_ASSETS']
|
138
|
+
production_root
|
139
|
+
else
|
140
|
+
asset_root
|
141
|
+
end
|
142
|
+
|
143
|
+
path = File.join(path, file) if file
|
144
|
+
path
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def asset_ext(klass)
|
150
|
+
klass.name.split('::').last.downcase
|
151
|
+
end
|
152
|
+
|
153
|
+
# Find files based on class type and
|
154
|
+
# return an array of Classes for each file
|
155
|
+
def add_files(klass)
|
156
|
+
ext = asset_ext klass
|
157
|
+
find_files(ext).map do |path|
|
158
|
+
klass.new(self, path)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Find files by class type and extension
|
163
|
+
def find_files(ext)
|
164
|
+
files = Dir[File.join(paths[ext.to_sym], asset_glob(ext))]
|
165
|
+
|
166
|
+
# Filter out partials
|
167
|
+
files.reject { |f| File.basename(f).start_with?('_') }
|
168
|
+
end
|
169
|
+
|
170
|
+
def asset_glob(type)
|
171
|
+
case type
|
172
|
+
when "sass"
|
173
|
+
"*.s[ca]ss"
|
174
|
+
else
|
175
|
+
"*.#{type}"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Convert configuration into instance variables
|
180
|
+
def set_instance(name, value)
|
181
|
+
instance_variable_set("@#{name}", value)
|
182
|
+
|
183
|
+
instance_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
184
|
+
def #{name}
|
185
|
+
@#{name}
|
186
|
+
end
|
187
|
+
EOS
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spark_engine/sass/importer'
|
2
|
+
|
3
|
+
# Taken from https://github.com/chriseppstein/sass-css-importer/blob/master/lib/sass/css_importer/monkey_patches.rb
|
4
|
+
# TODO: This feels wrong, surely there must be a better way to handle this
|
5
|
+
|
6
|
+
class Sass::Engine
|
7
|
+
alias initialize_without_yaml_importer initialize
|
8
|
+
|
9
|
+
def initialize(template, options={})
|
10
|
+
initialize_without_yaml_importer(template, options)
|
11
|
+
|
12
|
+
yaml_importer = self.options[:load_paths].find {|lp| lp.is_a?(SparkEngine::Importer) }
|
13
|
+
|
14
|
+
unless yaml_importer
|
15
|
+
root = File.dirname(options[:filename] || ".")
|
16
|
+
plugin_root = SparkEngine.plugin.stylesheets.base
|
17
|
+
self.options[:load_paths] << SparkEngine::Importer.new(root)
|
18
|
+
self.options[:load_paths] << SparkEngine::Importer.new(plugin_root)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|