klenod-build 0.0.7 → 0.0.8
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 +4 -4
- data/lib/klenod/build/context.rb +1 -0
- data/lib/klenod/build/graph.rb +6 -3
- data/lib/klenod/build/plugins/asset_javascript_metadata.rb +2 -1
- data/lib/klenod/build/plugins/haml_plugin/transformer/ruby_builder.rb +24 -6
- data/lib/klenod/build/plugins/haml_plugin/transformer.rb +42 -13
- data/lib/klenod/build/plugins/haml_plugin.rb +3 -0
- data/lib/klenod/build/plugins/image_plugin.rb +47 -11
- data/lib/klenod/build/plugins/static_asset_plugin.rb +56 -0
- data/lib/klenod/build/plugins.rb +1 -0
- data/lib/klenod/build/version.rb +1 -1
- metadata +18 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a357752604a0766c4448f82142e21ae3a9d51863839c538aa3fe04d30719a21b
|
|
4
|
+
data.tar.gz: ab3ffc5a88004014fe159b6ae3690c6e3f61ed0a0ba73cdac1f34499cc474262
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 28bcd4ee5726533dffa7ed0dac3b57e0a677fb050e067bc230a14e74895c164bd6caceec598c3847823cd421f8b7b18d6f4e30a0d62eef07883b30fc5615b95b
|
|
7
|
+
data.tar.gz: bd7a69a04c303d7719f44ca3eba9f00e6296e435b1970748781095427a525632d141e2506d06e19d2c6a1d0a6c9a340b1cc310beb18fa052db7491f1bc275f9e
|
data/lib/klenod/build/context.rb
CHANGED
data/lib/klenod/build/graph.rb
CHANGED
|
@@ -56,7 +56,7 @@ module Klenod
|
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
attr_reader :records, :mods, :asset_generation_queue, :mode, :profiler, :base
|
|
59
|
+
attr_reader :records, :mods, :asset_generation_queue, :mode, :profiler, :base, :namespace
|
|
60
60
|
attr_reader :plugins
|
|
61
61
|
|
|
62
62
|
def initialize(
|
|
@@ -80,6 +80,7 @@ module Klenod
|
|
|
80
80
|
)
|
|
81
81
|
@records = {}
|
|
82
82
|
@mods = {}
|
|
83
|
+
@namespace = Module.new
|
|
83
84
|
@virtual_sources = {}
|
|
84
85
|
@virtual_metadata = {}
|
|
85
86
|
@virtual_owners = {}
|
|
@@ -358,7 +359,8 @@ module Klenod
|
|
|
358
359
|
imports: imports_for(record.resolved_dependencies, dependency_records),
|
|
359
360
|
source_map: record.source_map,
|
|
360
361
|
version: record.version,
|
|
361
|
-
eval_path: eval_path_for(module_id)
|
|
362
|
+
eval_path: eval_path_for(module_id),
|
|
363
|
+
namespace: namespace
|
|
362
364
|
)
|
|
363
365
|
|
|
364
366
|
@mods[module_id] = mod
|
|
@@ -540,7 +542,8 @@ module Klenod
|
|
|
540
542
|
imports: imports_for(resolved_dependencies, dependency_records),
|
|
541
543
|
source_map: transform.source_map,
|
|
542
544
|
version: cached ? cached.version + 1 : 0,
|
|
543
|
-
eval_path: eval_path_for(module_id)
|
|
545
|
+
eval_path: eval_path_for(module_id),
|
|
546
|
+
namespace: namespace
|
|
544
547
|
)
|
|
545
548
|
end
|
|
546
549
|
|
|
@@ -33,9 +33,10 @@ module Klenod
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export default class ImageMetadata extends ImageBase {
|
|
36
|
-
constructor({ src, width, height, contentType, aspectRatio, variants = [] }) {
|
|
36
|
+
constructor({ src, width, height, contentType, aspectRatio, variants = [], placeholder = null }) {
|
|
37
37
|
super({ src, width, height, contentType, aspectRatio });
|
|
38
38
|
this.variants = Object.freeze([...variants]);
|
|
39
|
+
this.placeholder = placeholder;
|
|
39
40
|
Object.freeze(this);
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -442,6 +442,15 @@ module Klenod
|
|
|
442
442
|
ast_silent_script(source) || raise(ArgumentError, "Could not build Ruby begin block from Haml script: #{source.inspect}")
|
|
443
443
|
end
|
|
444
444
|
|
|
445
|
+
def silent_script_with_children(source, body)
|
|
446
|
+
source = rewrite_ruby_source(source, nil)
|
|
447
|
+
statements = parse_statements(source)
|
|
448
|
+
return raise(ArgumentError, "Could not parse Haml silent script: #{source.inspect}") unless statements
|
|
449
|
+
|
|
450
|
+
node = ast_begin([*statement_body_for(statements), *statement_body_for(body)])
|
|
451
|
+
Fragment.new(["begin", indent(source, 2), indent(to_source(body), 2), "end"].join("\n"), node)
|
|
452
|
+
end
|
|
453
|
+
|
|
445
454
|
def branches(branches)
|
|
446
455
|
ast_branches(branches) || raise(ArgumentError, "Could not build Ruby branch from Haml scripts: #{branches.map(&:first).inspect}")
|
|
447
456
|
end
|
|
@@ -550,11 +559,12 @@ module Klenod
|
|
|
550
559
|
.filter_map do |(line, column), type, token, _state|
|
|
551
560
|
kind, prefix, pattern = VARIABLE_TOKEN_KINDS[type]
|
|
552
561
|
receiver = @variables[kind]
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
562
|
+
if type == :on_gvar && token == "$*" && receiver
|
|
563
|
+
[offset_for(line_offsets, line, column), token.length, receiver]
|
|
564
|
+
elsif receiver && token.match?(pattern)
|
|
565
|
+
name = token.delete_prefix(prefix)
|
|
566
|
+
[offset_for(line_offsets, line, column), token.length, "(#{receiver})[#{symbol_source(name)}]"]
|
|
567
|
+
end
|
|
558
568
|
end
|
|
559
569
|
.reverse_each
|
|
560
570
|
.each_with_object(source.dup) do |(offset, length, replacement), rewritten|
|
|
@@ -562,6 +572,10 @@ module Klenod
|
|
|
562
572
|
end
|
|
563
573
|
end
|
|
564
574
|
|
|
575
|
+
def offset_for(line_offsets, line, column)
|
|
576
|
+
line_offsets.fetch(line - 1) + column
|
|
577
|
+
end
|
|
578
|
+
|
|
565
579
|
def source_expressions(expressions)
|
|
566
580
|
case expressions.length
|
|
567
581
|
when 0
|
|
@@ -579,11 +593,14 @@ module Klenod
|
|
|
579
593
|
factory = expression_fragment(factory)
|
|
580
594
|
tag = expression_fragment(tag)
|
|
581
595
|
children = children.map { |child| expression_fragment(child) }
|
|
596
|
+
props = props.dup
|
|
597
|
+
attribute_splats = props.delete(:__klenod_attribute_splats__) || []
|
|
582
598
|
|
|
583
599
|
source_parts = [
|
|
584
600
|
to_source(tag),
|
|
585
601
|
*children.map { |child| argument_source(child) },
|
|
586
|
-
*keyword_props_source(props, mark: mark)
|
|
602
|
+
*keyword_props_source(props, mark: mark),
|
|
603
|
+
*attribute_splats.map { |value| "**#{argument_source(value)}" }
|
|
587
604
|
].compact
|
|
588
605
|
Fragment.new("#{to_source(factory)}[#{source_parts.join(", ")}]", nil)
|
|
589
606
|
end
|
|
@@ -712,6 +729,7 @@ module Klenod
|
|
|
712
729
|
case source
|
|
713
730
|
when /\Aif\s+(.+)\z/ then $1
|
|
714
731
|
when /\Aelsif\s+(.+)\z/ then $1
|
|
732
|
+
when /\Aunless\s+(.+)\z/ then "!(#{$1})"
|
|
715
733
|
else return nil
|
|
716
734
|
end
|
|
717
735
|
predicate = parse_expression(predicate_source, context: :branch_predicate)
|
|
@@ -12,6 +12,8 @@ module Klenod
|
|
|
12
12
|
module Plugins
|
|
13
13
|
module HamlPlugin
|
|
14
14
|
class Transformer
|
|
15
|
+
ATTRIBUTE_SPLATS_KEY = :__klenod_attribute_splats__
|
|
16
|
+
|
|
15
17
|
VALID_CONST_PATH = /\A[A-Z]\w*(?:::[A-Z]\w*)*\z/
|
|
16
18
|
|
|
17
19
|
ConstPath = Data.define(:value) do
|
|
@@ -43,11 +45,13 @@ module Klenod
|
|
|
43
45
|
import_rewriter: nil,
|
|
44
46
|
markdown_components_source: "{}",
|
|
45
47
|
variables: nil,
|
|
48
|
+
event_handler: nil,
|
|
46
49
|
haml_helper_source: nil,
|
|
47
50
|
cache_static_subtrees: false
|
|
48
51
|
)
|
|
49
52
|
component_base_class = ConstPath.parse(component_base_class, name: "component_base_class")
|
|
50
53
|
factory = ConstPath.parse(factory, name: "factory")
|
|
54
|
+
event_handler = ConstPath.parse(event_handler, name: "event_handler") if event_handler
|
|
51
55
|
validate_component_children(component_children)
|
|
52
56
|
builder = RubyBuilder.new(profiler: profiler, variables: variables)
|
|
53
57
|
haml_helper_source ||= builder.constant_assignment("HamlHelper", "Object") if styleable || cache_static_subtrees
|
|
@@ -56,11 +60,13 @@ module Klenod
|
|
|
56
60
|
previous_static_constants = @static_constants
|
|
57
61
|
previous_cache_static_subtrees = @cache_static_subtrees
|
|
58
62
|
previous_component_children = @component_children
|
|
63
|
+
previous_event_handler = @event_handler
|
|
59
64
|
@profiler = profiler
|
|
60
65
|
@module_id = module_id
|
|
61
66
|
@static_constants = []
|
|
62
67
|
@cache_static_subtrees = cache_static_subtrees
|
|
63
68
|
@component_children = component_children
|
|
69
|
+
@event_handler = event_handler
|
|
64
70
|
template =
|
|
65
71
|
if profiler
|
|
66
72
|
profiler.measure(:haml_compile_template, module_id: module_id.to_s) do
|
|
@@ -136,6 +142,7 @@ module Klenod
|
|
|
136
142
|
@static_constants = previous_static_constants
|
|
137
143
|
@cache_static_subtrees = previous_cache_static_subtrees
|
|
138
144
|
@component_children = previous_component_children
|
|
145
|
+
@event_handler = previous_event_handler
|
|
139
146
|
end
|
|
140
147
|
|
|
141
148
|
private
|
|
@@ -369,6 +376,13 @@ module Klenod
|
|
|
369
376
|
)
|
|
370
377
|
end
|
|
371
378
|
|
|
379
|
+
unless source.start_with?("if ", "unless ", "case ")
|
|
380
|
+
return builder.silent_script_with_children(
|
|
381
|
+
source,
|
|
382
|
+
compile_nodes(node.children, factory: factory, styleable: styleable, builder: builder, markdown_compiler: markdown_compiler)
|
|
383
|
+
)
|
|
384
|
+
end
|
|
385
|
+
|
|
372
386
|
compile_silent_branches(
|
|
373
387
|
split_silent_script_branches(node, builder: builder),
|
|
374
388
|
factory: factory,
|
|
@@ -507,7 +521,7 @@ module Klenod
|
|
|
507
521
|
end
|
|
508
522
|
|
|
509
523
|
def compile_ruby_filter(node, builder:, source: "", import_rewriter: nil)
|
|
510
|
-
text = node.value.fetch(:text)
|
|
524
|
+
text = node.value.fetch(:text) || ""
|
|
511
525
|
if import_rewriter && text.include?("import")
|
|
512
526
|
source_column_offset = source.lines.fetch(node.line, "").match(/\A\s*/).to_s.length
|
|
513
527
|
text = import_rewriter.call(text, source_line_offset: node.line, source_column_offset: source_column_offset)
|
|
@@ -552,8 +566,9 @@ module Klenod
|
|
|
552
566
|
def compile_filter_node(node, builder:, markdown_compiler:)
|
|
553
567
|
return builder.render_ruby_filter(compile_ruby_filter(node, builder: builder)) if ruby_filter?(node)
|
|
554
568
|
return builder.expression(markdown_compiler.compile(node.value.fetch(:text), interpolate: true)) if markdown_filter?(node)
|
|
569
|
+
return builder.literal(node.value.fetch(:text).to_s) if plain_filter?(node)
|
|
555
570
|
|
|
556
|
-
raise ArgumentError, "Only :ruby and :
|
|
571
|
+
raise ArgumentError, "Only :ruby, :markdown, and :plain Haml filters are supported"
|
|
557
572
|
end
|
|
558
573
|
|
|
559
574
|
def ruby_filter?(node)
|
|
@@ -564,6 +579,10 @@ module Klenod
|
|
|
564
579
|
node.type == :filter && node.value.fetch(:name) == "markdown"
|
|
565
580
|
end
|
|
566
581
|
|
|
582
|
+
def plain_filter?(node)
|
|
583
|
+
node.type == :filter && node.value.fetch(:name) == "plain"
|
|
584
|
+
end
|
|
585
|
+
|
|
567
586
|
def css_filter?(node)
|
|
568
587
|
node.type == :filter && node.value.fetch(:name) == "css"
|
|
569
588
|
end
|
|
@@ -588,7 +607,7 @@ module Klenod
|
|
|
588
607
|
|
|
589
608
|
measure_compile(:haml_compile_dynamic_attributes) do
|
|
590
609
|
source = builder.line_rewritten_source(source, node.line)
|
|
591
|
-
simple = simple_dynamic_attributes(source, builder: builder)
|
|
610
|
+
simple = simple_dynamic_attributes(source, builder: builder) unless @event_handler
|
|
592
611
|
if simple
|
|
593
612
|
simple.each { |key, value| props[key] = value }
|
|
594
613
|
return simple
|
|
@@ -601,8 +620,15 @@ module Klenod
|
|
|
601
620
|
|
|
602
621
|
dynamic = {}
|
|
603
622
|
hash.node.assocs.each do |assoc|
|
|
623
|
+
if assoc.is_a?(SyntaxTree::AssocSplat)
|
|
624
|
+
splat_source = hash.source[assoc.value.location.start_char...assoc.value.location.end_char]
|
|
625
|
+
props[ATTRIBUTE_SPLATS_KEY] ||= []
|
|
626
|
+
props[ATTRIBUTE_SPLATS_KEY] << builder.expression(splat_source)
|
|
627
|
+
next
|
|
628
|
+
end
|
|
629
|
+
|
|
604
630
|
key = attribute_key(assoc.key, builder: builder)
|
|
605
|
-
value =
|
|
631
|
+
value = event_handler_value(key, assoc.value, builder: builder) || attribute_value(assoc, builder: builder)
|
|
606
632
|
dynamic[key] = value
|
|
607
633
|
props[key] = value
|
|
608
634
|
end
|
|
@@ -722,16 +748,9 @@ module Klenod
|
|
|
722
748
|
end
|
|
723
749
|
end
|
|
724
750
|
|
|
725
|
-
def
|
|
726
|
-
location = node.location
|
|
727
|
-
return source unless location
|
|
728
|
-
|
|
729
|
-
source[location.start_char...location.end_char]
|
|
730
|
-
end
|
|
731
|
-
|
|
732
|
-
def attribute_value(assoc, source, builder:)
|
|
751
|
+
def attribute_value(assoc, builder:)
|
|
733
752
|
value = assoc.value
|
|
734
|
-
return builder.
|
|
753
|
+
return builder.fragment(value) if value
|
|
735
754
|
|
|
736
755
|
key = omitted_attribute_value_name(assoc.key)
|
|
737
756
|
return builder.expression(key) if key
|
|
@@ -739,6 +758,16 @@ module Klenod
|
|
|
739
758
|
builder.ruby_parse_error(source, line_no: assoc.key.location&.start_line, context: "Could not parse Haml dynamic attributes")
|
|
740
759
|
end
|
|
741
760
|
|
|
761
|
+
def event_handler_value(key, value, builder:)
|
|
762
|
+
return unless @event_handler && key.to_s.match?(/\Aon[a-z]/)
|
|
763
|
+
return unless value
|
|
764
|
+
|
|
765
|
+
method_name = builder.fragment(value).source
|
|
766
|
+
return unless method_name.match?(/\A[a-zA-Z_]\w*[!?=]?\z/)
|
|
767
|
+
|
|
768
|
+
builder.expression("#{@event_handler}.callback(self, :#{method_name})")
|
|
769
|
+
end
|
|
770
|
+
|
|
742
771
|
def omitted_attribute_value_name(node)
|
|
743
772
|
case node
|
|
744
773
|
when SyntaxTree::Label
|
|
@@ -66,6 +66,7 @@ module Klenod
|
|
|
66
66
|
factory: DEFAULT_FACTORY,
|
|
67
67
|
component_children: DEFAULT_COMPONENT_CHILDREN,
|
|
68
68
|
variables: nil,
|
|
69
|
+
event_handler: nil,
|
|
69
70
|
i18n: nil,
|
|
70
71
|
cache_static_subtrees: false
|
|
71
72
|
)
|
|
@@ -73,6 +74,7 @@ module Klenod
|
|
|
73
74
|
@factory = factory
|
|
74
75
|
@component_children = validate_component_children(component_children)
|
|
75
76
|
@variables = validate_variables(variables)
|
|
77
|
+
@event_handler = event_handler
|
|
76
78
|
@i18n_class, @i18n_constant = validate_i18n_options(i18n)
|
|
77
79
|
@cache_static_subtrees = cache_static_subtrees
|
|
78
80
|
@transformer = Transformer.new
|
|
@@ -208,6 +210,7 @@ module Klenod
|
|
|
208
210
|
import_rewriter: import_rewriter,
|
|
209
211
|
markdown_components_source: markdown_components_dependency ? "__klenod_import__(#{markdown_components_dependency.id.inspect})::Default" : "{}",
|
|
210
212
|
variables: @variables,
|
|
213
|
+
event_handler: @event_handler,
|
|
211
214
|
cache_static_subtrees: @cache_static_subtrees
|
|
212
215
|
)
|
|
213
216
|
import_rewrite =
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "image_size"
|
|
4
4
|
require "rmagick"
|
|
5
5
|
require "uri"
|
|
6
|
+
require "base64"
|
|
6
7
|
|
|
7
8
|
require_relative "../asset"
|
|
8
9
|
require_relative "../dependency"
|
|
@@ -27,12 +28,15 @@ module Klenod
|
|
|
27
28
|
|
|
28
29
|
ImageDefaultKey = Data.define(:source_path, :source_hash, :format, :quality)
|
|
29
30
|
ImageVariantKey = Data.define(:source_path, :source_hash, :width, :format, :quality)
|
|
31
|
+
ImagePlaceholderKey = Data.define(:source_path, :source_hash, :width, :format, :quality)
|
|
30
32
|
|
|
31
|
-
def initialize(widths: [], formats: nil)
|
|
33
|
+
def initialize(widths: [], formats: nil, placeholder: nil)
|
|
32
34
|
@widths = widths
|
|
33
35
|
@formats = formats
|
|
36
|
+
@placeholder = normalize_placeholder(placeholder)
|
|
34
37
|
@default_asset_cache = {}
|
|
35
38
|
@variant_cache = {}
|
|
39
|
+
@placeholder_cache = {}
|
|
36
40
|
end
|
|
37
41
|
|
|
38
42
|
def resolve(dependency, _context)
|
|
@@ -51,8 +55,9 @@ module Klenod
|
|
|
51
55
|
image_options = image_options_for(module_id)
|
|
52
56
|
asset = default_image_asset(module_id, source_path, source_hash, dimensions, image_options, context.asset_generation_queue)
|
|
53
57
|
variant_assets = generate_variant_assets(module_id, source_path, source_hash, dimensions, image_options, context.asset_generation_queue)
|
|
58
|
+
placeholder = image_placeholder(source_path, source_hash)
|
|
54
59
|
[asset, *variant_assets].each { |image_asset| image_asset.url = context.asset_url(image_asset.output_path) }
|
|
55
|
-
javascript_asset = javascript_image_asset(module_id, asset, variant_assets, context)
|
|
60
|
+
javascript_asset = javascript_image_asset(module_id, asset, variant_assets, context, placeholder:)
|
|
56
61
|
javascript_asset.url = context.asset_url(javascript_asset.output_path)
|
|
57
62
|
assets = [asset, *variant_assets]
|
|
58
63
|
image_runtime_dependency =
|
|
@@ -66,7 +71,7 @@ module Klenod
|
|
|
66
71
|
|
|
67
72
|
transform =
|
|
68
73
|
TransformResult.new(
|
|
69
|
-
image_module_source(module_id, assets, image_runtime_dependency, context),
|
|
74
|
+
image_module_source(module_id, assets, image_runtime_dependency, context, placeholder:),
|
|
70
75
|
[image_runtime_dependency],
|
|
71
76
|
nil,
|
|
72
77
|
assets,
|
|
@@ -184,13 +189,14 @@ module Klenod
|
|
|
184
189
|
end
|
|
185
190
|
|
|
186
191
|
ImageOptions = Data.define(:widths, :formats, :explicit_formats, :quality)
|
|
192
|
+
PlaceholderOptions = Data.define(:width, :format, :quality)
|
|
187
193
|
|
|
188
194
|
def image_runtime_source
|
|
189
195
|
<<~RUBY
|
|
190
196
|
ImageMetadata =
|
|
191
|
-
Data.define(:src, :width, :height, :content_type, :aspect_ratio, :variants) do
|
|
192
|
-
def initialize(src:, width:, height:, content_type:, aspect_ratio:, variants:)
|
|
193
|
-
super(src:, width:, height:, content_type:, aspect_ratio:, variants: variants.dup.freeze)
|
|
197
|
+
Data.define(:src, :width, :height, :content_type, :aspect_ratio, :variants, :placeholder) do
|
|
198
|
+
def initialize(src:, width:, height:, content_type:, aspect_ratio:, variants:, placeholder: nil)
|
|
199
|
+
super(src:, width:, height:, content_type:, aspect_ratio:, variants: variants.dup.freeze, placeholder:)
|
|
194
200
|
end
|
|
195
201
|
|
|
196
202
|
alias to_s src
|
|
@@ -219,7 +225,7 @@ module Klenod
|
|
|
219
225
|
"# image asset: #{module_id}\n"
|
|
220
226
|
end
|
|
221
227
|
|
|
222
|
-
def image_module_source(module_id, assets, image_runtime_dependency, context)
|
|
228
|
+
def image_module_source(module_id, assets, image_runtime_dependency, context, placeholder:)
|
|
223
229
|
asset = image_asset(assets)
|
|
224
230
|
variants = image_variant_assets(assets).map { |variant_asset| image_variant_source(variant_asset, context) }
|
|
225
231
|
|
|
@@ -232,6 +238,7 @@ module Klenod
|
|
|
232
238
|
height: #{asset.metadata[:height].inspect},
|
|
233
239
|
content_type: #{asset.content_type.inspect},
|
|
234
240
|
aspect_ratio: #{AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height]).inspect},
|
|
241
|
+
placeholder: #{placeholder.inspect},
|
|
235
242
|
variants: [
|
|
236
243
|
#{variants.join(",\n ")}
|
|
237
244
|
]
|
|
@@ -255,8 +262,36 @@ module Klenod
|
|
|
255
262
|
RUBY
|
|
256
263
|
end
|
|
257
264
|
|
|
258
|
-
def
|
|
259
|
-
|
|
265
|
+
def image_placeholder(source_path, source_hash)
|
|
266
|
+
return nil unless @placeholder
|
|
267
|
+
|
|
268
|
+
key = ImagePlaceholderKey.new(source_path.to_s, source_hash, @placeholder.width, @placeholder.format, @placeholder.quality)
|
|
269
|
+
@placeholder_cache[key] ||= begin
|
|
270
|
+
bytes = generate_image_bytes(source_path, @placeholder.format, width: @placeholder.width, quality: @placeholder.quality)
|
|
271
|
+
"data:image/#{@placeholder.format};base64,#{Base64.strict_encode64(bytes)}"
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def normalize_placeholder(value)
|
|
276
|
+
return nil if value.nil? || value == false
|
|
277
|
+
|
|
278
|
+
value = {width: value} if value.is_a?(Integer)
|
|
279
|
+
unless value.is_a?(Hash)
|
|
280
|
+
raise ArgumentError, "placeholder must be nil, false, an Integer width, or a Hash"
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
width = Integer(value.fetch(:width, 16))
|
|
284
|
+
raise ArgumentError, "placeholder width must be positive" unless width.positive?
|
|
285
|
+
|
|
286
|
+
format = value.fetch(:format, "webp").to_s.downcase
|
|
287
|
+
quality = Integer(value.fetch(:quality, 80))
|
|
288
|
+
raise ArgumentError, "placeholder quality must be between 0 and 100" unless (0..100).cover?(quality)
|
|
289
|
+
|
|
290
|
+
PlaceholderOptions.new(width, format, quality)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def javascript_image_asset(module_id, asset, variant_assets, context, placeholder:)
|
|
294
|
+
code = javascript_image_module_source(asset, variant_assets, context, placeholder:)
|
|
260
295
|
hash = Hashing.short(code)
|
|
261
296
|
Asset.new(
|
|
262
297
|
module_id.path,
|
|
@@ -269,14 +304,15 @@ module Klenod
|
|
|
269
304
|
)
|
|
270
305
|
end
|
|
271
306
|
|
|
272
|
-
def javascript_image_module_source(asset, variant_assets, context)
|
|
307
|
+
def javascript_image_module_source(asset, variant_assets, context, placeholder:)
|
|
273
308
|
variants = variant_assets.map { "new ImageVariant(#{AssetJavaScriptMetadata.object_literal(javascript_image_variant(it, context))})" }
|
|
274
309
|
properties = {
|
|
275
310
|
src: asset.url,
|
|
276
311
|
width: asset.metadata[:width],
|
|
277
312
|
height: asset.metadata[:height],
|
|
278
313
|
contentType: asset.content_type,
|
|
279
|
-
aspectRatio: AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height])
|
|
314
|
+
aspectRatio: AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height]),
|
|
315
|
+
placeholder: placeholder
|
|
280
316
|
}.map { |key, value| AssetJavaScriptMetadata.property(key, value) }
|
|
281
317
|
properties << %(variants:[#{variants.join(",")}])
|
|
282
318
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../asset"
|
|
4
|
+
require_relative "../hashing"
|
|
5
|
+
require_relative "../plugin"
|
|
6
|
+
require_relative "../transform_result"
|
|
7
|
+
|
|
8
|
+
module Klenod
|
|
9
|
+
module Build
|
|
10
|
+
module Plugins
|
|
11
|
+
module StaticAssetPlugin
|
|
12
|
+
def self.new(...)
|
|
13
|
+
Plugin.new(...)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Plugin < Klenod::Build::Plugin
|
|
17
|
+
CONTENT_TYPES = {
|
|
18
|
+
".otf" => "font/otf",
|
|
19
|
+
".ttf" => "font/ttf",
|
|
20
|
+
".woff" => "font/woff",
|
|
21
|
+
".woff2" => "font/woff2"
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
def transform(module_id, code, context)
|
|
25
|
+
return super unless CONTENT_TYPES.key?(module_id.extname)
|
|
26
|
+
|
|
27
|
+
hash = Hashing.short(code)
|
|
28
|
+
output_path = "/#{asset_name(module_id)}.#{hash}#{module_id.extname}"
|
|
29
|
+
asset = Asset.new(module_id.path, hash, output_path, nil, code, CONTENT_TYPES.fetch(module_id.extname), {type: :static_asset})
|
|
30
|
+
asset.url = context.asset_url(output_path)
|
|
31
|
+
|
|
32
|
+
TransformResult.new("Default = #{asset.url.inspect}\n", [], nil, [asset], [], {})
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def import_value(_resolved_dependency, record, context)
|
|
36
|
+
return nil unless CONTENT_TYPES.key?(record.id.extname)
|
|
37
|
+
|
|
38
|
+
context.mods.fetch(record.id).const_get(:Exports)::Default
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def runtime_import_value(_resolved_dependency, record, _context)
|
|
42
|
+
return nil unless CONTENT_TYPES.key?(record.id.extname)
|
|
43
|
+
|
|
44
|
+
Runtime::DefaultImport.new(:Default)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def asset_name(module_id)
|
|
50
|
+
File.basename(module_id.path, module_id.extname).gsub(/[^A-Za-z0-9]+/, "_")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/klenod/build/plugins.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Klenod
|
|
|
11
11
|
autoload :GoogleFontsPlugin, File.expand_path("plugins/google_fonts_plugin", __dir__)
|
|
12
12
|
autoload :SvgPlugin, File.expand_path("plugins/svg_plugin", __dir__)
|
|
13
13
|
autoload :ImagePlugin, File.expand_path("plugins/image_plugin", __dir__)
|
|
14
|
+
autoload :StaticAssetPlugin, File.expand_path("plugins/static_asset_plugin", __dir__)
|
|
14
15
|
autoload :DataPlugin, File.expand_path("plugins/data_plugin", __dir__)
|
|
15
16
|
autoload :JsonPlugin, File.expand_path("plugins/data_plugin", __dir__)
|
|
16
17
|
autoload :YamlPlugin, File.expand_path("plugins/data_plugin", __dir__)
|
data/lib/klenod/build/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: klenod-build
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrés Alin
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.0.
|
|
18
|
+
version: 0.0.8
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.0.
|
|
25
|
+
version: 0.0.8
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: async
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -57,6 +57,20 @@ dependencies:
|
|
|
57
57
|
- - "<"
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
59
|
version: 0.104.0
|
|
60
|
+
- !ruby/object:Gem::Dependency
|
|
61
|
+
name: base64
|
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - "~>"
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '0.3'
|
|
67
|
+
type: :runtime
|
|
68
|
+
prerelease: false
|
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - "~>"
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '0.3'
|
|
60
74
|
- !ruby/object:Gem::Dependency
|
|
61
75
|
name: brotli
|
|
62
76
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -277,6 +291,7 @@ files:
|
|
|
277
291
|
- lib/klenod/build/plugins/markdown_plugin.rb
|
|
278
292
|
- lib/klenod/build/plugins/router_plugin.rb
|
|
279
293
|
- lib/klenod/build/plugins/ruby_plugin.rb
|
|
294
|
+
- lib/klenod/build/plugins/static_asset_plugin.rb
|
|
280
295
|
- lib/klenod/build/plugins/svg_plugin.rb
|
|
281
296
|
- lib/klenod/build/profiler.rb
|
|
282
297
|
- lib/klenod/build/resolution_error_formatter.rb
|