pakyow-assets 0.1.2 → 1.0.0.rc1

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.
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