pakyow-assets 0.1.2 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +3 -19
- data/lib/pakyow/assets.rb +19 -0
- data/lib/pakyow/assets/actions/process.rb +63 -0
- data/lib/pakyow/assets/actions/public.rb +75 -0
- data/lib/pakyow/assets/asset.rb +238 -0
- data/lib/pakyow/assets/babel.rb +34 -0
- data/lib/pakyow/assets/behavior/assets.rb +45 -0
- data/lib/pakyow/assets/behavior/config.rb +137 -0
- data/lib/pakyow/assets/behavior/externals.rb +58 -0
- data/lib/pakyow/assets/behavior/packs.rb +162 -0
- data/lib/pakyow/assets/behavior/prelaunching.rb +19 -0
- data/lib/pakyow/assets/behavior/processing.rb +27 -0
- data/lib/pakyow/assets/behavior/rendering/install_assets.rb +39 -0
- data/lib/pakyow/assets/behavior/silencing.rb +35 -0
- data/lib/pakyow/assets/behavior/watching.rb +25 -0
- data/lib/pakyow/assets/errors.rb +16 -0
- data/lib/pakyow/assets/external.rb +103 -0
- data/lib/pakyow/assets/framework.rb +52 -0
- data/lib/pakyow/assets/pack.rb +171 -0
- data/lib/pakyow/assets/precompiler.rb +63 -0
- data/lib/pakyow/assets/source_map.rb +99 -0
- data/lib/pakyow/assets/tasks/precompile.rake +9 -0
- data/lib/pakyow/assets/tasks/update.rake +20 -0
- data/lib/pakyow/assets/types/css.rb +45 -0
- data/lib/pakyow/assets/types/js.rb +98 -0
- data/lib/pakyow/assets/types/sass.rb +69 -0
- data/lib/pakyow/assets/types/scss.rb +14 -0
- data/src/@babel/standalone@7.3.1/babel.min.js +165 -0
- data/src/@babel/standalone@7.4.5/babel.min.js +92359 -0
- metadata +146 -46
- data/CHANGELOG.md +0 -18
- data/README.md +0 -58
- data/lib/assets.rb +0 -221
- data/lib/config.rb +0 -37
- data/lib/middleware.rb +0 -42
- data/lib/pakyow-assets.rb +0 -31
- data/lib/preprocessors/css-preprocessor.rb +0 -16
- data/lib/preprocessors/image-preprocessor.rb +0 -1
- data/lib/preprocessors/javascript-preprocessor.rb +0 -16
- data/lib/preprocessors/sass-preprocessor.rb +0 -23
- data/lib/version.rb +0 -5
- data/pakyow-assets.gemspec +0 -21
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/extension"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Assets
|
7
|
+
module Behavior
|
8
|
+
module Rendering
|
9
|
+
module InstallAssets
|
10
|
+
extend Support::Extension
|
11
|
+
|
12
|
+
apply_extension do
|
13
|
+
build do |view, app:|
|
14
|
+
if head = view.head
|
15
|
+
packs = app.packs(view)
|
16
|
+
|
17
|
+
if app.is_a?(Plugin)
|
18
|
+
packs = app.parent.packs(view).concat(packs)
|
19
|
+
end
|
20
|
+
|
21
|
+
packs.uniq { |pack|
|
22
|
+
pack.public_path
|
23
|
+
}.each do |pack|
|
24
|
+
if pack.javascripts?
|
25
|
+
head.object.append_html("<script src=\"#{pack.public_path}.js\"></script>\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
if pack.stylesheets?
|
29
|
+
head.object.append_html("<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"#{pack.public_path}.css\">\n")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/extension"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Assets
|
7
|
+
module Behavior
|
8
|
+
# Silences asset requests from being logged.
|
9
|
+
#
|
10
|
+
module Silencing
|
11
|
+
extend Support::Extension
|
12
|
+
|
13
|
+
apply_extension do
|
14
|
+
on "load" do
|
15
|
+
if config.assets.silent
|
16
|
+
# silence asset requests
|
17
|
+
Pakyow.silence do |connection|
|
18
|
+
# TODO: do we need the second check?
|
19
|
+
connection.path.start_with?(config.assets.prefix) || self.class.asset.instances.any? { |asset|
|
20
|
+
asset.logical_path == connection.path
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
# silence requests to public files
|
25
|
+
Pakyow.silence do |connection|
|
26
|
+
# TODO: really need an in-memory directory for these files
|
27
|
+
File.file?(File.join(config.assets.public_path, connection.path))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/extension"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Assets
|
7
|
+
module Behavior
|
8
|
+
module Watching
|
9
|
+
extend Support::Extension
|
10
|
+
|
11
|
+
apply_extension do
|
12
|
+
after "configure" do
|
13
|
+
config.assets.extensions.each do |extension|
|
14
|
+
config.process.watched_paths << File.join(config.presenter.path, "**/*#{extension}")
|
15
|
+
|
16
|
+
# Exclude vendored assets.
|
17
|
+
#
|
18
|
+
config.process.excluded_paths << File.join(config.assets.externals.path, "*#{extension}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/error"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Assets
|
7
|
+
class Error < Pakyow::Error
|
8
|
+
end
|
9
|
+
|
10
|
+
class UnknownExternalAsset < Error
|
11
|
+
class_state :messages, default: {
|
12
|
+
default: "`{asset}' is not a known external asset"
|
13
|
+
}.freeze
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "http"
|
4
|
+
|
5
|
+
require "pakyow/support/cli/runner"
|
6
|
+
|
7
|
+
module Pakyow
|
8
|
+
module Assets
|
9
|
+
# @api private
|
10
|
+
class External
|
11
|
+
attr_reader :name, :version, :package
|
12
|
+
|
13
|
+
def initialize(name, version:, package:, files:, config:)
|
14
|
+
@name, @version, @config = name, version, config
|
15
|
+
@package = package || name
|
16
|
+
@files = files || []
|
17
|
+
end
|
18
|
+
|
19
|
+
def exist?
|
20
|
+
if @files.empty?
|
21
|
+
Dir.glob(File.join(@config.externals.path, "#{@name}*.js")).any?
|
22
|
+
else
|
23
|
+
!@files.any? { |file|
|
24
|
+
if File.basename(file, File.extname(file)) == @name.to_s
|
25
|
+
Dir.glob(File.join(@config.externals.path, "#{@name}*.js")).empty?
|
26
|
+
else
|
27
|
+
Dir.glob(File.join(@config.externals.path, "#{@name}*__#{File.basename(file, File.extname(file))}.js")).empty?
|
28
|
+
end
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch!
|
34
|
+
if @files.empty?
|
35
|
+
fetch_file!(nil)
|
36
|
+
else
|
37
|
+
@files.each do |file|
|
38
|
+
fetch_file!(file)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def fetch_file!(file)
|
46
|
+
name_with_version = if @version
|
47
|
+
"#{name}@#{@version}"
|
48
|
+
else
|
49
|
+
name.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
file_with_version = File.join(name_with_version, file.to_s).chomp("/")
|
53
|
+
|
54
|
+
package_with_version = if @version
|
55
|
+
"#{@package}@#{@version}"
|
56
|
+
else
|
57
|
+
@package.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
Support::CLI::Runner.new(message: "Fetching #{file_with_version}").run do |runner|
|
61
|
+
begin
|
62
|
+
response = HTTP.follow(true).get(
|
63
|
+
File.join(
|
64
|
+
@config.externals.provider,
|
65
|
+
package_with_version,
|
66
|
+
file.to_s
|
67
|
+
)
|
68
|
+
)
|
69
|
+
|
70
|
+
if response.code == 200
|
71
|
+
FileUtils.mkdir_p(@config.externals.path)
|
72
|
+
|
73
|
+
fetched_version = response.uri.to_s.split(@package.to_s, 2)[1].split("/", 2)[0].split("@", 2)[1]
|
74
|
+
file_basename = File.basename(file.to_s, File.extname(file.to_s))
|
75
|
+
|
76
|
+
local_path = if file && file_basename != name.to_s
|
77
|
+
File.join(
|
78
|
+
@config.externals.path,
|
79
|
+
"#{name}@#{fetched_version}__#{file_basename}.js"
|
80
|
+
)
|
81
|
+
else
|
82
|
+
File.join(
|
83
|
+
@config.externals.path,
|
84
|
+
"#{name}@#{fetched_version}.js"
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
File.open(local_path, "w") do |fp|
|
89
|
+
fp.write(response.body.to_s)
|
90
|
+
end
|
91
|
+
|
92
|
+
runner.succeeded
|
93
|
+
else
|
94
|
+
runner.failed(response.to_s)
|
95
|
+
end
|
96
|
+
rescue HTTP::ConnectionError => error
|
97
|
+
runner.failed(error.to_s)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/framework"
|
4
|
+
|
5
|
+
require "pakyow/assets/asset"
|
6
|
+
require "pakyow/assets/pack"
|
7
|
+
|
8
|
+
require "pakyow/assets/behavior/config"
|
9
|
+
require "pakyow/assets/behavior/assets"
|
10
|
+
require "pakyow/assets/behavior/packs"
|
11
|
+
require "pakyow/assets/behavior/silencing"
|
12
|
+
require "pakyow/assets/behavior/externals"
|
13
|
+
require "pakyow/assets/behavior/watching"
|
14
|
+
require "pakyow/assets/behavior/prelaunching"
|
15
|
+
require "pakyow/assets/behavior/processing"
|
16
|
+
|
17
|
+
require "pakyow/assets/behavior/rendering/install_assets"
|
18
|
+
|
19
|
+
module Pakyow
|
20
|
+
module Assets
|
21
|
+
class Framework < Pakyow::Framework(:assets)
|
22
|
+
def boot
|
23
|
+
object.class_eval do
|
24
|
+
# Let other frameworks load their own assets.
|
25
|
+
#
|
26
|
+
stateful :asset, Asset
|
27
|
+
|
28
|
+
# Let other frameworks load their own asset packs.
|
29
|
+
#
|
30
|
+
stateful :pack, Pack
|
31
|
+
|
32
|
+
include Behavior::Config
|
33
|
+
include Behavior::Assets
|
34
|
+
include Behavior::Packs
|
35
|
+
include Behavior::Silencing
|
36
|
+
include Behavior::Externals
|
37
|
+
include Behavior::Watching
|
38
|
+
include Behavior::Prelaunching
|
39
|
+
include Behavior::Processing
|
40
|
+
|
41
|
+
after "load" do
|
42
|
+
isolated(:Renderer) do
|
43
|
+
# Load this one later, in case other actions define components that will load assets.
|
44
|
+
#
|
45
|
+
include Assets::Behavior::Rendering::InstallAssets
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/md5"
|
4
|
+
require "forwardable"
|
5
|
+
|
6
|
+
require "pakyow/support/core_refinements/string/normalization"
|
7
|
+
|
8
|
+
require "pakyow/assets/asset"
|
9
|
+
require "pakyow/assets/source_map"
|
10
|
+
|
11
|
+
module Pakyow
|
12
|
+
module Assets
|
13
|
+
class Pack
|
14
|
+
using Support::Refinements::String::Normalization
|
15
|
+
|
16
|
+
attr_reader :name, :public_path
|
17
|
+
|
18
|
+
def initialize(name, config, prefix: "/")
|
19
|
+
@name, @config = name, config
|
20
|
+
@assets = []
|
21
|
+
@packed = { js: [], css: [] }
|
22
|
+
@public_path = String.normalize_path(
|
23
|
+
File.join(config.prefix, prefix, "packs", name.to_s)
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def finalize
|
28
|
+
tap do
|
29
|
+
if @config.fingerprint
|
30
|
+
extension = File.extname(@public_path)
|
31
|
+
@public_path = File.join(
|
32
|
+
File.dirname(@public_path),
|
33
|
+
File.basename(@public_path, extension) + "__" + fingerprint + extension
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
pack_assets!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def <<(asset)
|
42
|
+
@assets << asset.disable_source_map
|
43
|
+
end
|
44
|
+
|
45
|
+
def packed(path)
|
46
|
+
if path.start_with?(@public_path + ".")
|
47
|
+
@packed[File.extname(path)[1..-1].to_sym]
|
48
|
+
else
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def javascripts
|
54
|
+
@packed[:js]
|
55
|
+
end
|
56
|
+
|
57
|
+
def stylesheets
|
58
|
+
@packed[:css]
|
59
|
+
end
|
60
|
+
|
61
|
+
def javascripts?
|
62
|
+
javascripts.any?
|
63
|
+
end
|
64
|
+
|
65
|
+
def stylesheets?
|
66
|
+
stylesheets.any?
|
67
|
+
end
|
68
|
+
|
69
|
+
def fingerprint
|
70
|
+
@assets.flat_map(&:fingerprint).sort.each_with_object(Digest::MD5.new) { |fingerprint, digest|
|
71
|
+
digest.update(fingerprint)
|
72
|
+
}.hexdigest
|
73
|
+
end
|
74
|
+
|
75
|
+
def public_js_path
|
76
|
+
@public_path + ".js"
|
77
|
+
end
|
78
|
+
|
79
|
+
def public_css_path
|
80
|
+
@public_path + ".css"
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def pack_assets!
|
86
|
+
@packed[:js] = PackedAssets.new(@assets.select { |asset|
|
87
|
+
asset.mime_suffix == "javascript"
|
88
|
+
}, public_js_path, @config, @name)
|
89
|
+
|
90
|
+
@packed[:css] = PackedAssets.new(@assets.select { |asset|
|
91
|
+
asset.mime_suffix == "css"
|
92
|
+
}, public_css_path, @config, @name)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class PackedAssets
|
97
|
+
extend Forwardable
|
98
|
+
def_delegators :@assets, :any?
|
99
|
+
|
100
|
+
attr_reader :public_path, :assets
|
101
|
+
|
102
|
+
def initialize(assets, public_path, config, name)
|
103
|
+
@assets, @public_path, @config, @name = assets, public_path, config, name
|
104
|
+
end
|
105
|
+
|
106
|
+
def initialize_copy(_)
|
107
|
+
super
|
108
|
+
|
109
|
+
@assets = @assets.map(&:dup)
|
110
|
+
end
|
111
|
+
|
112
|
+
def mime_type
|
113
|
+
@assets.first&.mime_type
|
114
|
+
end
|
115
|
+
|
116
|
+
def mime_suffix
|
117
|
+
@assets.first&.mime_suffix
|
118
|
+
end
|
119
|
+
|
120
|
+
def each(&block)
|
121
|
+
@assets.each do |asset|
|
122
|
+
asset.each(&block)
|
123
|
+
end
|
124
|
+
|
125
|
+
if @config.source_maps && source_map?
|
126
|
+
yield source_mapping_url
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def read
|
131
|
+
String.new.tap do |packed_asset|
|
132
|
+
@assets.each do |asset|
|
133
|
+
packed_asset << asset.read
|
134
|
+
end
|
135
|
+
|
136
|
+
if @config.source_maps && source_map?
|
137
|
+
packed_asset << source_mapping_url
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def bytesize
|
143
|
+
bytes = @assets.map(&:bytesize).inject(&:+)
|
144
|
+
|
145
|
+
if @config.source_maps && source_map?
|
146
|
+
bytes += source_mapping_url.bytesize
|
147
|
+
end
|
148
|
+
|
149
|
+
bytes
|
150
|
+
end
|
151
|
+
|
152
|
+
def source_map
|
153
|
+
@assets.select(&:source_map?).inject(
|
154
|
+
SourceMap.new(
|
155
|
+
file: File.basename(@public_path)
|
156
|
+
)
|
157
|
+
) { |merged, asset|
|
158
|
+
merged.merge(asset.source_map)
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
def source_map?
|
163
|
+
@assets.any?(&:source_map?)
|
164
|
+
end
|
165
|
+
|
166
|
+
def source_mapping_url
|
167
|
+
SourceMap.mapping_url(path: @public_path, type: @assets.first.mime_suffix)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|