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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +3 -19
  3. data/lib/pakyow/assets.rb +19 -0
  4. data/lib/pakyow/assets/actions/process.rb +63 -0
  5. data/lib/pakyow/assets/actions/public.rb +75 -0
  6. data/lib/pakyow/assets/asset.rb +238 -0
  7. data/lib/pakyow/assets/babel.rb +34 -0
  8. data/lib/pakyow/assets/behavior/assets.rb +45 -0
  9. data/lib/pakyow/assets/behavior/config.rb +137 -0
  10. data/lib/pakyow/assets/behavior/externals.rb +58 -0
  11. data/lib/pakyow/assets/behavior/packs.rb +162 -0
  12. data/lib/pakyow/assets/behavior/prelaunching.rb +19 -0
  13. data/lib/pakyow/assets/behavior/processing.rb +27 -0
  14. data/lib/pakyow/assets/behavior/rendering/install_assets.rb +39 -0
  15. data/lib/pakyow/assets/behavior/silencing.rb +35 -0
  16. data/lib/pakyow/assets/behavior/watching.rb +25 -0
  17. data/lib/pakyow/assets/errors.rb +16 -0
  18. data/lib/pakyow/assets/external.rb +103 -0
  19. data/lib/pakyow/assets/framework.rb +52 -0
  20. data/lib/pakyow/assets/pack.rb +171 -0
  21. data/lib/pakyow/assets/precompiler.rb +63 -0
  22. data/lib/pakyow/assets/source_map.rb +99 -0
  23. data/lib/pakyow/assets/tasks/precompile.rake +9 -0
  24. data/lib/pakyow/assets/tasks/update.rake +20 -0
  25. data/lib/pakyow/assets/types/css.rb +45 -0
  26. data/lib/pakyow/assets/types/js.rb +98 -0
  27. data/lib/pakyow/assets/types/sass.rb +69 -0
  28. data/lib/pakyow/assets/types/scss.rb +14 -0
  29. data/src/@babel/standalone@7.3.1/babel.min.js +165 -0
  30. data/src/@babel/standalone@7.4.5/babel.min.js +92359 -0
  31. metadata +146 -46
  32. data/CHANGELOG.md +0 -18
  33. data/README.md +0 -58
  34. data/lib/assets.rb +0 -221
  35. data/lib/config.rb +0 -37
  36. data/lib/middleware.rb +0 -42
  37. data/lib/pakyow-assets.rb +0 -31
  38. data/lib/preprocessors/css-preprocessor.rb +0 -16
  39. data/lib/preprocessors/image-preprocessor.rb +0 -1
  40. data/lib/preprocessors/javascript-preprocessor.rb +0 -16
  41. data/lib/preprocessors/sass-preprocessor.rb +0 -23
  42. data/lib/version.rb +0 -5
  43. 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