hanami-assets 1.1.1 → 1.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/hanami-assets.gemspec +2 -2
- data/lib/hanami/assets/configuration.rb +12 -0
- data/lib/hanami/assets/helpers.rb +109 -29
- data/lib/hanami/assets/version.rb +1 -1
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dee96814cdbdc9c4b0bf4519052da244585da7ce22f1ee9d002ef2bfde88344d
|
4
|
+
data.tar.gz: 7a0607dac9d21de73b5052c5b02efb7e1cf316fb278cc19fee6a197780dfb890
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a984c83ee52c5d75c9175376090b1f00bad151ca63d354d2dd626ae955defeebd685999726be12f5b884bbd6fcb5b3c49304fa8ed2425f9de1cb74708b39270
|
7
|
+
data.tar.gz: 13217797668cc3bba5369fbabd88f69796a16752193f0fbf57f270f990e1e332ec71616dc0c751a25691e1517845dc621ca5a3038032b4b2fac38e929fcf2a4f
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# Hanami::Assets
|
2
2
|
Assets management for Ruby web applications
|
3
3
|
|
4
|
+
## v1.2.0.beta1 - 2018-02-28
|
5
|
+
### Added
|
6
|
+
- [Luca Guidi] Collect assets informations for Early Hints (103)
|
7
|
+
- [Luca Guidi] Send automatically javascripts and stylesheets via Push Promise / Early Hints
|
8
|
+
- [Luca Guidi] Add the ability to send audio, video, and generic assets for Push Promise / Early Hints
|
9
|
+
|
4
10
|
## v1.1.1 - 2018-02-27
|
5
11
|
### Added
|
6
12
|
- [Luca Guidi] Official support for Ruby: MRI 2.5
|
data/hanami-assets.gemspec
CHANGED
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
spec.required_ruby_version = '>= 2.3.0'
|
22
22
|
|
23
|
-
spec.add_runtime_dependency 'hanami-utils', '
|
24
|
-
spec.add_runtime_dependency 'hanami-helpers', '
|
23
|
+
spec.add_runtime_dependency 'hanami-utils', '1.2.0.beta1'
|
24
|
+
spec.add_runtime_dependency 'hanami-helpers', '1.2.0.beta1'
|
25
25
|
spec.add_runtime_dependency 'tilt', '~> 2.0', '>= 2.0.2'
|
26
26
|
|
27
27
|
spec.add_development_dependency 'bundler'
|
@@ -412,6 +412,18 @@ module Hanami
|
|
412
412
|
"#{@base_url}#{compile_path(source)}"
|
413
413
|
end
|
414
414
|
|
415
|
+
# Check if the given source is linked via Cross-Origin policy.
|
416
|
+
# In other words, the given source, doesn't satisfy the Same-Origin policy.
|
417
|
+
#
|
418
|
+
# @see https://en.wikipedia.org/wiki/Same-origin_policy#Origin_determination_rules
|
419
|
+
# @see https://en.wikipedia.org/wiki/Same-origin_policy#document.domain_property
|
420
|
+
#
|
421
|
+
# @since 1.2.0
|
422
|
+
# @api private
|
423
|
+
def crossorigin?(source)
|
424
|
+
!source.start_with?(@base_url)
|
425
|
+
end
|
426
|
+
|
415
427
|
# An array of crypographically secure hashing algorithms to use for
|
416
428
|
# generating asset subresource integrity checks
|
417
429
|
#
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'uri'
|
2
|
-
require 'set'
|
3
2
|
require 'hanami/helpers/html_helper'
|
4
3
|
require 'hanami/utils/escape'
|
5
4
|
|
@@ -97,7 +96,11 @@ module Hanami
|
|
97
96
|
# name of the algorithm, then a hyphen, then the hash value of the file.
|
98
97
|
# If more than one algorithm is used, they'll be separated by a space.
|
99
98
|
#
|
99
|
+
# It makes the script(s) eligible for HTTP/2 Push Promise/Early Hints.
|
100
|
+
# You can opt-out with inline option: `push: false`.
|
101
|
+
#
|
100
102
|
# @param sources [Array<String>] one or more assets by name or absolute URL
|
103
|
+
# @param push [TrueClass, FalseClass] HTTP/2 Push Promise/Early Hints flag
|
101
104
|
#
|
102
105
|
# @return [Hanami::Utils::Escape::SafeString] the markup
|
103
106
|
#
|
@@ -165,12 +168,17 @@ module Hanami
|
|
165
168
|
# <%= javascript 'application' %>
|
166
169
|
#
|
167
170
|
# # <script src="https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js" type="text/javascript"></script>
|
168
|
-
|
171
|
+
#
|
172
|
+
# @example Disable Push Promise/Early Hints
|
173
|
+
#
|
174
|
+
# <%= javascript 'application', push: false %>
|
175
|
+
# <%= javascript 'http://cdn.example.test/jquery.js', 'dashboard', push: false %>
|
176
|
+
def javascript(*sources, push: true, **options) # rubocop:disable Metrics/MethodLength
|
169
177
|
options = options.reject { |k, _| k.to_sym == :src }
|
170
178
|
|
171
179
|
_safe_tags(*sources) do |source|
|
172
180
|
attributes = {
|
173
|
-
src: _typed_asset_path(source, JAVASCRIPT_EXT),
|
181
|
+
src: _typed_asset_path(source, JAVASCRIPT_EXT, push: push, as: :script),
|
174
182
|
type: JAVASCRIPT_MIME_TYPE
|
175
183
|
}
|
176
184
|
attributes.merge!(options)
|
@@ -199,7 +207,12 @@ module Hanami
|
|
199
207
|
# If the "subresource integrity mode" is on, <tt>integriy</tt> is the
|
200
208
|
# name of the algorithm, then a hyphen, then the hashed value of the file.
|
201
209
|
# If more than one algorithm is used, they'll be separated by a space.
|
210
|
+
#
|
211
|
+
# It makes the script(s) eligible for HTTP/2 Push Promise/Early Hints.
|
212
|
+
# You can opt-out with inline option: `push: false`.
|
213
|
+
#
|
202
214
|
# @param sources [Array<String>] one or more assets by name or absolute URL
|
215
|
+
# @param push [TrueClass, FalseClass] HTTP/2 Push Promise/Early Hints flag
|
203
216
|
#
|
204
217
|
# @return [Hanami::Utils::Escape::SafeString] the markup
|
205
218
|
#
|
@@ -256,12 +269,17 @@ module Hanami
|
|
256
269
|
# <%= stylesheet 'application' %>
|
257
270
|
#
|
258
271
|
# # <link href="https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.css" type="text/css" rel="stylesheet">
|
259
|
-
|
272
|
+
#
|
273
|
+
# @example Disable Push Promise/Early Hints
|
274
|
+
#
|
275
|
+
# <%= stylesheet 'application', push: false %>
|
276
|
+
# <%= stylesheet 'http://cdn.example.test/bootstrap.css', 'dashboard', push: false %>
|
277
|
+
def stylesheet(*sources, push: true, **options) # rubocop:disable Metrics/MethodLength
|
260
278
|
options = options.reject { |k, _| k.to_sym == :href }
|
261
279
|
|
262
280
|
_safe_tags(*sources) do |source|
|
263
281
|
attributes = {
|
264
|
-
href: _typed_asset_path(source, STYLESHEET_EXT),
|
282
|
+
href: _typed_asset_path(source, STYLESHEET_EXT, push: push, as: :style),
|
265
283
|
type: STYLESHEET_MIME_TYPE,
|
266
284
|
rel: STYLESHEET_REL
|
267
285
|
}
|
@@ -292,6 +310,8 @@ module Hanami
|
|
292
310
|
# application CDN.
|
293
311
|
#
|
294
312
|
# @param source [String] asset name or absolute URL
|
313
|
+
# @param options [Hash] HTML 5 attributes
|
314
|
+
# @option options [TrueClass, FalseClass] :push HTTP/2 Push Promise/Early Hints flag
|
295
315
|
#
|
296
316
|
# @return [Hanami::Utils::Helpers::HtmlBuilder] the builder
|
297
317
|
#
|
@@ -341,11 +361,14 @@ module Hanami
|
|
341
361
|
# <%= image 'logo.png' %>
|
342
362
|
#
|
343
363
|
# # <img src="https://assets.bookshelf.org/assets/logo-28a6b886de2372ee3922fcaf3f78f2d8.png" alt="Logo">
|
364
|
+
#
|
365
|
+
# @example Enable Push Promise/Early Hints
|
366
|
+
#
|
367
|
+
# <%= image 'logo.png', push: true %>
|
344
368
|
def image(source, options = {})
|
345
369
|
options = options.reject { |k, _| k.to_sym == :src }
|
346
|
-
|
347
370
|
attributes = {
|
348
|
-
src: asset_path(source),
|
371
|
+
src: asset_path(source, push: options.delete(:push) || false, as: :image),
|
349
372
|
alt: Utils::String.titleize(::File.basename(source, WILDCARD_EXT))
|
350
373
|
}
|
351
374
|
attributes.merge!(options)
|
@@ -366,6 +389,8 @@ module Hanami
|
|
366
389
|
# application CDN.
|
367
390
|
#
|
368
391
|
# @param source [String] asset name
|
392
|
+
# @param options [Hash] HTML 5 attributes
|
393
|
+
# @option options [TrueClass, FalseClass] :push HTTP/2 Push Promise/Early Hints flag
|
369
394
|
#
|
370
395
|
# @return [Hanami::Utils::Helpers::HtmlBuilder] the builder
|
371
396
|
#
|
@@ -393,7 +418,7 @@ module Hanami
|
|
393
418
|
#
|
394
419
|
# @example Custom HTML Attributes
|
395
420
|
#
|
396
|
-
# <%= favicon id:
|
421
|
+
# <%= favicon "favicon.ico", id: "fav" %>
|
397
422
|
#
|
398
423
|
# # <link id: "fav" href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon">
|
399
424
|
#
|
@@ -408,11 +433,15 @@ module Hanami
|
|
408
433
|
# <%= favicon %>
|
409
434
|
#
|
410
435
|
# # <link href="https://assets.bookshelf.org/assets/favicon-28a6b886de2372ee3922fcaf3f78f2d8.ico" rel="shortcut icon" type="image/x-icon">
|
436
|
+
#
|
437
|
+
# @example Enable Push Promise/Early Hints
|
438
|
+
#
|
439
|
+
# <%= favicon 'favicon.ico', push: true %>
|
411
440
|
def favicon(source = DEFAULT_FAVICON, options = {})
|
412
441
|
options = options.reject { |k, _| k.to_sym == :href }
|
413
442
|
|
414
443
|
attributes = {
|
415
|
-
href: asset_path(source),
|
444
|
+
href: asset_path(source, push: options.delete(:push) || false, as: :image),
|
416
445
|
rel: FAVICON_REL,
|
417
446
|
type: FAVICON_MIME_TYPE
|
418
447
|
}
|
@@ -437,6 +466,8 @@ module Hanami
|
|
437
466
|
# application CDN.
|
438
467
|
#
|
439
468
|
# @param source [String] asset name or absolute URL
|
469
|
+
# @param options [Hash] HTML 5 attributes
|
470
|
+
# @option options [TrueClass, FalseClass] :push HTTP/2 Push Promise/Early Hints flag
|
440
471
|
#
|
441
472
|
# @return [Hanami::Utils::Helpers::HtmlBuilder] the builder
|
442
473
|
#
|
@@ -535,8 +566,20 @@ module Hanami
|
|
535
566
|
# <%= video 'movie.mp4' %>
|
536
567
|
#
|
537
568
|
# # <video src="https://assets.bookshelf.org/assets/movie-28a6b886de2372ee3922fcaf3f78f2d8.mp4"></video>
|
569
|
+
#
|
570
|
+
# @example Enable Push Promise/Early Hints
|
571
|
+
#
|
572
|
+
# <%= video 'movie.mp4', push: true %>
|
573
|
+
#
|
574
|
+
# <%=
|
575
|
+
# video do
|
576
|
+
# text "Your browser does not support the video tag"
|
577
|
+
# source src: asset_path("movie.mp4", push: :video), type: "video/mp4"
|
578
|
+
# source src: asset_path("movie.ogg"), type: "video/ogg"
|
579
|
+
# end
|
580
|
+
# %>
|
538
581
|
def video(source = nil, options = {}, &blk)
|
539
|
-
options = _source_options(source, options, &blk)
|
582
|
+
options = _source_options(source, options, as: :video, &blk)
|
540
583
|
html.video(blk, options)
|
541
584
|
end
|
542
585
|
|
@@ -556,6 +599,8 @@ module Hanami
|
|
556
599
|
# application CDN.
|
557
600
|
#
|
558
601
|
# @param source [String] asset name or absolute URL
|
602
|
+
# @param options [Hash] HTML 5 attributes
|
603
|
+
# @option options [TrueClass, FalseClass] :push HTTP/2 Push Promise/Early Hints flag
|
559
604
|
#
|
560
605
|
# @return [Hanami::Utils::Helpers::HtmlBuilder] the builder
|
561
606
|
#
|
@@ -654,8 +699,20 @@ module Hanami
|
|
654
699
|
# <%= audio 'song.ogg' %>
|
655
700
|
#
|
656
701
|
# # <audio src="https://assets.bookshelf.org/assets/song-28a6b886de2372ee3922fcaf3f78f2d8.ogg"></audio>
|
702
|
+
#
|
703
|
+
# @example Enable Push Promise/Early Hints
|
704
|
+
#
|
705
|
+
# <%= audio 'movie.mp4', push: true %>
|
706
|
+
#
|
707
|
+
# <%=
|
708
|
+
# audio do
|
709
|
+
# text "Your browser does not support the audio tag"
|
710
|
+
# source src: asset_path("song.ogg", push: :audio), type: "audio/ogg"
|
711
|
+
# source src: asset_path("song.wav"), type: "audio/wav"
|
712
|
+
# end
|
713
|
+
# %>
|
657
714
|
def audio(source = nil, options = {}, &blk)
|
658
|
-
options = _source_options(source, options, &blk)
|
715
|
+
options = _source_options(source, options, as: :audio, &blk)
|
659
716
|
html.audio(blk, options)
|
660
717
|
end
|
661
718
|
|
@@ -671,6 +728,8 @@ module Hanami
|
|
671
728
|
# If CDN mode is on, it returns the absolute URL of the asset.
|
672
729
|
#
|
673
730
|
# @param source [String] the asset name
|
731
|
+
# @param push [TrueClass, FalseClass, Symbol] HTTP/2 Push Promise/Early Hints flag, or type
|
732
|
+
# @param as [Symbol] HTTP/2 Push Promise / Early Hints flag type
|
674
733
|
#
|
675
734
|
# @return [String] the asset path
|
676
735
|
#
|
@@ -703,8 +762,12 @@ module Hanami
|
|
703
762
|
# <%= asset_path 'application.js' %>
|
704
763
|
#
|
705
764
|
# # "https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js"
|
706
|
-
|
707
|
-
|
765
|
+
#
|
766
|
+
# @example Enable Push Promise/Early Hints
|
767
|
+
#
|
768
|
+
# <%= asset_path "application.js", push: :script %>
|
769
|
+
def asset_path(source, push: false, as: nil)
|
770
|
+
_asset_url(source, push: push, as: as) { _relative_url(source) }
|
708
771
|
end
|
709
772
|
|
710
773
|
# It generates the absolute URL for the given source.
|
@@ -719,6 +782,8 @@ module Hanami
|
|
719
782
|
# If CDN mode is on, it returns the absolute URL of the asset.
|
720
783
|
#
|
721
784
|
# @param source [String] the asset name
|
785
|
+
# @param push [TrueClass, FalseClass, Symbol] HTTP/2 Push Promise/Early Hints flag, or type
|
786
|
+
# @param as [Symbol] HTTP/2 Push Promise / Early Hints flag type
|
722
787
|
#
|
723
788
|
# @return [String] the asset URL
|
724
789
|
#
|
@@ -751,8 +816,12 @@ module Hanami
|
|
751
816
|
# <%= asset_url 'application.js' %>
|
752
817
|
#
|
753
818
|
# # "https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js"
|
754
|
-
|
755
|
-
|
819
|
+
#
|
820
|
+
# @example Enable Push Promise/Early Hints
|
821
|
+
#
|
822
|
+
# <%= asset_url "application.js", push: :script %>
|
823
|
+
def asset_url(source, push: false, as: nil)
|
824
|
+
_asset_url(source, push: push, as: as) { _absolute_url(source) }
|
756
825
|
end
|
757
826
|
|
758
827
|
private
|
@@ -769,18 +838,24 @@ module Hanami
|
|
769
838
|
|
770
839
|
# @since 0.1.0
|
771
840
|
# @api private
|
772
|
-
def _asset_url(source)
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
841
|
+
def _asset_url(source, push:, as:)
|
842
|
+
url = _absolute_url?(source) ? source : yield
|
843
|
+
|
844
|
+
case push
|
845
|
+
when Symbol
|
846
|
+
_push_promise(url, as: push)
|
847
|
+
when TrueClass
|
848
|
+
_push_promise(url, as: as)
|
849
|
+
end
|
850
|
+
|
851
|
+
url
|
777
852
|
end
|
778
853
|
|
779
854
|
# @since 0.1.0
|
780
855
|
# @api private
|
781
|
-
def _typed_asset_path(source, ext)
|
856
|
+
def _typed_asset_path(source, ext, push: false, as: nil)
|
782
857
|
source = "#{source}#{ext}" if _append_extension?(source, ext)
|
783
|
-
asset_path(source)
|
858
|
+
asset_path(source, push: push, as: as)
|
784
859
|
end
|
785
860
|
|
786
861
|
# @api private
|
@@ -800,6 +875,13 @@ module Hanami
|
|
800
875
|
ABSOLUTE_URL_MATCHER.match(source)
|
801
876
|
end
|
802
877
|
|
878
|
+
# @since 1.2.0
|
879
|
+
# @api private
|
880
|
+
def _crossorigin?(source)
|
881
|
+
return false unless _absolute_url?(source)
|
882
|
+
self.class.assets_configuration.crossorigin?(source)
|
883
|
+
end
|
884
|
+
|
803
885
|
# @since 0.1.0
|
804
886
|
# @api private
|
805
887
|
def _relative_url(source)
|
@@ -814,13 +896,13 @@ module Hanami
|
|
814
896
|
|
815
897
|
# @since 0.1.0
|
816
898
|
# @api private
|
817
|
-
def _source_options(src, options, &_blk)
|
899
|
+
def _source_options(src, options, as:, &_blk)
|
818
900
|
options ||= {}
|
819
901
|
|
820
902
|
if src.respond_to?(:to_hash)
|
821
903
|
options = src.to_hash
|
822
904
|
elsif src
|
823
|
-
options[:src] = asset_path(src)
|
905
|
+
options[:src] = asset_path(src, push: options.delete(:push) || false, as: as)
|
824
906
|
end
|
825
907
|
|
826
908
|
if !options[:src] && !block_given?
|
@@ -832,11 +914,9 @@ module Hanami
|
|
832
914
|
|
833
915
|
# @since 0.1.0
|
834
916
|
# @api private
|
835
|
-
def _push_promise(url)
|
836
|
-
|
837
|
-
|
838
|
-
Thread.current[:__hanami_assets].add(url.to_s)
|
839
|
-
end
|
917
|
+
def _push_promise(url, as: nil)
|
918
|
+
Thread.current[:__hanami_assets] ||= {}
|
919
|
+
Thread.current[:__hanami_assets][url.to_s] = { as: as, crossorigin: _crossorigin?(url) }
|
840
920
|
|
841
921
|
url
|
842
922
|
end
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hanami-assets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hanami-utils
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.2.0.beta1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.2.0.beta1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: hanami-helpers
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 1.2.0.beta1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 1.2.0.beta1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: tilt
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -240,9 +240,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
240
240
|
version: 2.3.0
|
241
241
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
242
242
|
requirements:
|
243
|
-
- - "
|
243
|
+
- - ">"
|
244
244
|
- !ruby/object:Gem::Version
|
245
|
-
version:
|
245
|
+
version: 1.3.1
|
246
246
|
requirements: []
|
247
247
|
rubyforge_project:
|
248
248
|
rubygems_version: 2.7.5
|