klenod-build 0.0.3 → 0.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3c7b7667bd38de08f8f31ebb2aecf97bcbde81d8e189dae356ac64651dd340b
4
- data.tar.gz: 55d2493b7d0047d97f9fb26766f7f6a1ed07867e1b1024c04d92dac3e04088e7
3
+ metadata.gz: f7515626d279801c2dfb15f6b0ff7d00b358c4dc20549f21b60730f1ef1307cf
4
+ data.tar.gz: ea285ea5d5d59188defafb4eced0c96ff316fbb67bd2d1cf0de7728f41cda927
5
5
  SHA512:
6
- metadata.gz: ce9d72bdc5127d334c72baa154e6d16997081c3e3a7f016074ec41088a16007b4c35c93d4bfb96a220fd950539b0e3496d7b3c9b33439c6777d5760cad2e2715
7
- data.tar.gz: 156d7564ff2e42c7831585790e906598510f5b27c74de16378f06870e792baa91f15101abe932212b6669a7a368d5b852c9f1be2cdeae5cc75ffa2f951eff46f
6
+ metadata.gz: 7480460dfbedd0e793ceed82b3142d6ea5750f9c11e6752193745248643c53ff8a804cd1c855b4ffb171c8cdd1872a7aae9e66f15b417f8bc5f15d3d3baa8da6
7
+ data.tar.gz: 743b1821300848721a9208b1e6f59fc2736dc89d99f6e9ff24bb01346e9701645c2c88dc75daf83424f6a1e6ad758f98db7877fbccac2a0670cbf3630f26b19f
data/README.md CHANGED
@@ -27,3 +27,6 @@ The CLI can also generate a [Graphviz](https://graphviz.org/) DOT-file from a ge
27
27
  ```sh
28
28
  bundle exec klenod graph dist/klenod.bundle > graph.dot
29
29
  ```
30
+
31
+ Klenod's internal virtual modules are hidden by default. Pass
32
+ `--internal-virtual-modules` to include them in the graph.
@@ -68,13 +68,19 @@ module Klenod
68
68
 
69
69
  options do
70
70
  option "--no-assets", "Hide generated asset nodes and edges."
71
+ option "--internal-virtual-modules", "Include Klenod's internal virtual modules."
71
72
  end
72
73
 
73
74
  one :bundle_path, "Path to a Klenod runtime bundle.", required: true
74
75
 
75
76
  def call
76
77
  bundle = Klenod::Runtime.load_bundle(@bundle_path)
77
- dot = Klenod::Build::Graphviz.call(bundle, include_assets: !@options[:no_assets])
78
+ dot =
79
+ Klenod::Build::Graphviz.call(
80
+ bundle,
81
+ include_assets: !@options[:no_assets],
82
+ include_internal_virtual_modules: @options[:internal_virtual_modules]
83
+ )
78
84
  output.write(dot)
79
85
  dot
80
86
  end
@@ -19,13 +19,18 @@ module Klenod
19
19
  ASSET_STYLE = {fillcolor: "#ffe4d6", color: "#e26d39"}.freeze
20
20
  DEFAULT_MODULE_STYLE = {fillcolor: "#f7f7f7", color: "#8a8a8a"}.freeze
21
21
 
22
- def self.call(bundle, include_assets: true)
23
- new(bundle, include_assets: include_assets).to_dot
22
+ def self.call(bundle, include_assets: true, include_internal_virtual_modules: false)
23
+ new(
24
+ bundle,
25
+ include_assets: include_assets,
26
+ include_internal_virtual_modules: include_internal_virtual_modules
27
+ ).to_dot
24
28
  end
25
29
 
26
- def initialize(bundle, include_assets: true)
30
+ def initialize(bundle, include_assets: true, include_internal_virtual_modules: false)
27
31
  @bundle = bundle
28
32
  @include_assets = include_assets
33
+ @include_internal_virtual_modules = include_internal_virtual_modules
29
34
  end
30
35
 
31
36
  def to_dot
@@ -46,8 +51,15 @@ module Klenod
46
51
 
47
52
  private
48
53
 
54
+ def all_module_ids
55
+ @all_module_ids ||= @bundle.modules.keys.sort
56
+ end
57
+
49
58
  def module_ids
50
- @bundle.modules.keys.sort
59
+ @module_ids ||=
60
+ all_module_ids.reject do |id|
61
+ internal_virtual_module?(id) && !entrypoint?(id) && !@include_internal_virtual_modules
62
+ end
51
63
  end
52
64
 
53
65
  def module_node(id)
@@ -75,7 +87,7 @@ module Klenod
75
87
  module_ids.flat_map do |id|
76
88
  @bundle.modules.fetch(id).imports.values.map do |import|
77
89
  import = import_spec(import)
78
- next unless @bundle.modules.key?(import.target_id)
90
+ next unless visible_module?(import.target_id)
79
91
 
80
92
  attributes = {
81
93
  id: svg_edge_id(id, import.target_id),
@@ -91,25 +103,71 @@ module Klenod
91
103
  end
92
104
 
93
105
  def asset_edges
94
- @bundle.assets.values.sort_by(&:output_path).filter_map do |asset|
95
- owner = asset_owner(asset)
96
- next unless owner
97
-
98
- attributes = {
99
- id: svg_edge_id(owner_node_name(owner), asset.output_path),
100
- class: "edge edge-asset",
101
- color: "#e26d39",
102
- style: "dotted",
103
- label: "asset"
104
- }
105
- " #{owner_node_id(owner)} -> #{asset_node_id(asset)} [#{dot_attributes(attributes)}];"
106
+ @bundle.assets.values.sort_by(&:output_path).flat_map do |asset|
107
+ asset_owners(asset).map do |owner|
108
+ attributes = {
109
+ id: svg_edge_id(owner_node_name(owner), asset.output_path),
110
+ class: "edge edge-asset",
111
+ color: "#e26d39",
112
+ style: "dotted",
113
+ label: "asset"
114
+ }
115
+ " #{owner_node_id(owner)} -> #{asset_node_id(asset)} [#{dot_attributes(attributes)}];"
116
+ end
106
117
  end
107
118
  end
108
119
 
109
- def asset_owner(asset)
110
- return [:module, asset.logical_name] if @bundle.modules.key?(asset.logical_name)
120
+ def asset_owners(asset)
121
+ module_id = module_id_for_asset(asset.logical_name)
122
+ return visible_module_owners(module_id) if module_id
111
123
 
112
- google_fonts_css_asset_owner(asset) || query_module_id_for(asset.logical_name)
124
+ [google_fonts_css_asset_owner(asset), *asset_metadata_owners(asset)].compact
125
+ end
126
+
127
+ def visible_module_owners(module_id)
128
+ pending = [module_id]
129
+ seen = Set.new
130
+ owners = []
131
+
132
+ until pending.empty?
133
+ current_id = pending.shift
134
+ next unless seen.add?(current_id)
135
+
136
+ if visible_module?(current_id)
137
+ owners << [:module, current_id]
138
+ else
139
+ pending.concat(module_importers.fetch(current_id, []))
140
+ end
141
+ end
142
+
143
+ owners
144
+ end
145
+
146
+ def module_importers
147
+ @module_importers ||=
148
+ all_module_ids.each_with_object(Hash.new { |index, id| index[id] = [] }) do |id, index|
149
+ @bundle.modules.fetch(id).imports.each_value do |import|
150
+ target_id = import_spec(import).target_id
151
+ index[target_id] << id if @bundle.modules.key?(target_id)
152
+ end
153
+ end
154
+ end
155
+
156
+ def module_id_for_asset(logical_name)
157
+ return logical_name if @bundle.modules.key?(logical_name)
158
+
159
+ module_ids_by_source_path.fetch(logical_name, nil) || query_module_ids_by_path.fetch(logical_name, nil)
160
+ end
161
+
162
+ def module_ids_by_source_path
163
+ @module_ids_by_source_path ||=
164
+ all_module_ids.each_with_object({}) do |id, index|
165
+ source_path = @bundle.modules.fetch(id).source_path
166
+ next unless source_path
167
+
168
+ index[source_path] ||= id
169
+ index[display_path(source_path)] ||= id
170
+ end
113
171
  end
114
172
 
115
173
  def google_fonts_css_asset_owner(asset)
@@ -127,14 +185,18 @@ module Klenod
127
185
  asset.metadata[:source_url]
128
186
  end
129
187
 
130
- def query_module_id_for(logical_name)
131
- module_id = query_module_ids_by_path.fetch(logical_name, nil)
132
- [:module, module_id] if module_id
188
+ def asset_metadata_owners(asset)
189
+ return [] unless asset.metadata[:javascript_runtime] == :asset_metadata
190
+
191
+ @bundle.assets.values
192
+ .select { it.metadata[:image_metadata] || it.metadata[:svg_metadata] }
193
+ .sort_by(&:output_path)
194
+ .map { [:asset, it] }
133
195
  end
134
196
 
135
197
  def query_module_ids_by_path
136
198
  @query_module_ids_by_path ||=
137
- module_ids.each_with_object({}) do |id, index|
199
+ all_module_ids.each_with_object({}) do |id, index|
138
200
  path, query = id.split("?", 2)
139
201
  next unless query
140
202
 
@@ -218,6 +280,15 @@ module Klenod
218
280
  ["edge", import.eager ? "edge-import" : "edge-import edge-lazy"].join(" ")
219
281
  end
220
282
 
283
+ def internal_virtual_module?(id)
284
+ id.start_with?("virtual:/klenod/", "virtual:klenod/")
285
+ end
286
+
287
+ def visible_module?(id)
288
+ @visible_module_ids ||= module_ids.to_set
289
+ @visible_module_ids.include?(id)
290
+ end
291
+
221
292
  def entrypoint?(id)
222
293
  entrypoint_ids.include?(id)
223
294
  end
@@ -30,6 +30,7 @@ module Klenod
30
30
  DEFAULT_FACTORY = ComponentDefaults::DEFAULT_FACTORY
31
31
  DEFAULT_COMPONENT_CHILDREN = :eager
32
32
  COMPONENT_CHILDREN_MODES = %i[eager lazy].freeze
33
+ I18N_OPTIONS = %i[class constant].freeze
33
34
  HAML_HELPER_SPECIFIER = "virtual:klenod/haml_helper"
34
35
  HAML_HELPER_MODULE_ID = ModuleId.new("#{HAML_HELPER_SPECIFIER}.rb", nil)
35
36
  STATIC_CLASS_SOURCE_PATTERN = /^[ \t]*(?:%[-:\w]+)?(?:#[\w-]+)?\.[\w-]|[({][^)}\n]*\bclass\s*=/m
@@ -47,6 +48,7 @@ module Klenod
47
48
  DEFAULT_FACTORY = HamlPlugin::DEFAULT_FACTORY
48
49
  DEFAULT_COMPONENT_CHILDREN = HamlPlugin::DEFAULT_COMPONENT_CHILDREN
49
50
  COMPONENT_CHILDREN_MODES = HamlPlugin::COMPONENT_CHILDREN_MODES
51
+ I18N_OPTIONS = HamlPlugin::I18N_OPTIONS
50
52
  HAML_HELPER_SPECIFIER = HamlPlugin::HAML_HELPER_SPECIFIER
51
53
  HAML_HELPER_MODULE_ID = HamlPlugin::HAML_HELPER_MODULE_ID
52
54
  STATIC_CLASS_SOURCE_PATTERN = HamlPlugin::STATIC_CLASS_SOURCE_PATTERN
@@ -64,15 +66,14 @@ module Klenod
64
66
  factory: DEFAULT_FACTORY,
65
67
  component_children: DEFAULT_COMPONENT_CHILDREN,
66
68
  variables: nil,
67
- i18n_class: nil,
68
- i18n_constant: nil,
69
+ i18n: nil,
69
70
  cache_static_subtrees: false
70
71
  )
71
72
  @component_base_class = component_base_class
72
73
  @factory = factory
73
74
  @component_children = validate_component_children(component_children)
74
75
  @variables = validate_variables(variables)
75
- @i18n_class, @i18n_constant = validate_i18n_options(i18n_class, i18n_constant)
76
+ @i18n_class, @i18n_constant = validate_i18n_options(i18n)
76
77
  @cache_static_subtrees = cache_static_subtrees
77
78
  @transformer = Transformer.new
78
79
  end
@@ -296,15 +297,23 @@ module Klenod
296
297
  raise ArgumentError, "variables[#{kind.inspect}] must be a Ruby expression"
297
298
  end
298
299
 
299
- def validate_i18n_options(i18n_class, i18n_constant)
300
- return [nil, nil] if i18n_class.nil? && i18n_constant.nil?
301
- raise ArgumentError, "i18n_class must be configured when i18n_constant is configured" if i18n_class.nil?
300
+ def validate_i18n_options(i18n)
301
+ return [nil, nil] if i18n.nil?
302
+ raise ArgumentError, "i18n must be a Hash" unless i18n.is_a?(Hash)
302
303
 
303
- i18n_constant = (i18n_constant || "I18n").to_s
304
- raise ArgumentError, "i18n_constant must be a Ruby constant name" unless i18n_constant.match?(/\A[A-Z]\w*\z/)
304
+ unknown_options = i18n.keys - I18N_OPTIONS
305
+ unless unknown_options.empty?
306
+ raise ArgumentError, "i18n contains unknown options: #{unknown_options.map(&:inspect).join(", ")}"
307
+ end
308
+
309
+ i18n_class = i18n[:class]
310
+ raise ArgumentError, "i18n[:class] must be configured" if i18n_class.nil?
311
+
312
+ i18n_constant = (i18n[:constant] || "I18n").to_s
313
+ raise ArgumentError, "i18n[:constant] must be a Ruby constant name" unless i18n_constant.match?(/\A[A-Z]\w*\z/)
305
314
 
306
315
  [
307
- Transformer::ConstPath.parse(i18n_class, name: "i18n_class").to_s,
316
+ Transformer::ConstPath.parse(i18n_class, name: "i18n[:class]").to_s,
308
317
  i18n_constant
309
318
  ]
310
319
  end
@@ -191,6 +191,8 @@ module Klenod
191
191
  super(src:, width:, height:, content_type:, aspect_ratio:, variants: variants.dup.freeze)
192
192
  end
193
193
 
194
+ alias to_s src
195
+
194
196
  def srcset
195
197
  return nil if variants.empty?
196
198
 
@@ -205,7 +207,9 @@ module Klenod
205
207
  end
206
208
  end
207
209
 
208
- ImageVariant = Data.define(:src, :width, :height, :content_type, :aspect_ratio, :format, :descriptor, :quality)
210
+ ImageVariant = Data.define(:src, :width, :height, :content_type, :aspect_ratio, :format, :descriptor, :quality) do
211
+ alias to_s src
212
+ end
209
213
  RUBY
210
214
  end
211
215
 
@@ -94,7 +94,9 @@ module Klenod
94
94
 
95
95
  def svg_runtime_source
96
96
  <<~RUBY
97
- SvgMetadata = Data.define(:src, :width, :height, :content_type, :aspect_ratio)
97
+ SvgMetadata = Data.define(:src, :width, :height, :content_type, :aspect_ratio) do
98
+ alias to_s src
99
+ end
98
100
  RUBY
99
101
  end
100
102
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Klenod
4
4
  module Build
5
- VERSION = "0.0.3"
5
+ VERSION = "0.0.5"
6
6
  end
7
7
  end
@@ -53,10 +53,11 @@ module Klenod
53
53
  end
54
54
  end
55
55
 
56
- def initialize(source_dir:, context:, debounce_interval: 0.1)
56
+ def initialize(source_dir:, context:, debounce_interval: 0.1, ignore: nil)
57
57
  @source_dir = source_dir
58
58
  @context = context
59
59
  @debounce_interval = debounce_interval
60
+ @ignore = ignore
60
61
  @graph_version = 0
61
62
  @pending_changes = PendingChanges.new
62
63
  @pending_mutex = Mutex.new
@@ -68,7 +69,7 @@ module Klenod
68
69
  def start
69
70
  @worker_thread = Thread.new { process_pending_updates }
70
71
  @listener =
71
- Listen.to(@source_dir) do |modified, added, removed|
72
+ Listen.to(@source_dir, ignore: @ignore) do |modified, added, removed|
72
73
  enqueue_update(modified + added, removed)
73
74
  end
74
75
  @listener.start
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.3
4
+ version: 0.0.5
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.3
18
+ version: 0.0.5
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.3
25
+ version: 0.0.5
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: async
28
28
  requirement: !ruby/object:Gem::Requirement