klenod-build 0.0.4 → 0.0.6

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: 560774e128fafb845afbff51f556e3eb30d3a1b7d280b9fbdc7ac36b48c4b741
4
- data.tar.gz: 559ce8134726f2fa31084811a9dcda01987a957c073370f5ac0595c8d7a3f703
3
+ metadata.gz: 37a480cf40ba06385175cb0156563e300599b888366ea96b5a4c64dc5b7c2af9
4
+ data.tar.gz: 3aba70e34cb4e0c1c8328cea78682181f2079e28dbded35513f57a135becc405
5
5
  SHA512:
6
- metadata.gz: 77cb936bd77e35262827d9903124f1b37cec73bb11db28c1a5e497d02a20d9283e989a46524c2f674b7c0f49734632e3da02b324a4988dbccbe3fe244e591921
7
- data.tar.gz: eccc054b80b674a4f304fb6ec2abbdaf3bdf244576dc0f9bfd7b0d23b7b35ac77f5a47a061ad013cd9743295606b7ca3526a50e8f2dff48cc86ba13d4dac6fc2
6
+ metadata.gz: 0a86cb133c6ce093ef722b7f21b7f10402d80e80f3e8cdef85afb853420f0f552b1ccff4d6b42fb6565e0e898ea42ad713e98d385283842d12066b444fd27fbe
7
+ data.tar.gz: c7e07833d11dd65c47fcf702163157c62a8a670aa44c0017b14018ef658f646088700350b6ffe0e24cfeae475f7e4c5aa6d67b0325a5029904d8765958728a0c
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.
@@ -8,8 +8,9 @@ module Klenod
8
8
  module Build
9
9
  class Asset
10
10
  attr_reader :logical_name, :content_hash, :output_path, :source_path, :content_type, :metadata, :queue_kind, :error
11
+ attr_accessor :url
11
12
 
12
- def initialize(logical_name, content_hash, output_path, source_path, bytes, content_type, metadata, generator: nil, writer: nil, queue: nil, queue_kind: :cpu)
13
+ def initialize(logical_name, content_hash, output_path, source_path, bytes, content_type, metadata, url: nil, generator: nil, writer: nil, queue: nil, queue_kind: :cpu)
13
14
  @logical_name = logical_name
14
15
  @content_hash = content_hash
15
16
  @output_path = output_path
@@ -17,6 +18,7 @@ module Klenod
17
18
  @bytes = bytes
18
19
  @content_type = content_type
19
20
  @metadata = metadata
21
+ @url = url
20
22
  @generator = generator
21
23
  @writer = writer
22
24
  @queue = queue
@@ -28,8 +30,8 @@ module Klenod
28
30
  @error = nil
29
31
  end
30
32
 
31
- def self.generated(logical_name, content_hash, output_path, source_path, content_type, metadata, writer: nil, queue: nil, queue_kind: :cpu, &generator)
32
- new(logical_name, content_hash, output_path, source_path, nil, content_type, metadata, generator: generator, writer: writer, queue: queue, queue_kind: queue_kind)
33
+ def self.generated(logical_name, content_hash, output_path, source_path, content_type, metadata, url: nil, writer: nil, queue: nil, queue_kind: :cpu, &generator)
34
+ new(logical_name, content_hash, output_path, source_path, nil, content_type, metadata, url:, generator: generator, writer: writer, queue: queue, queue_kind: queue_kind)
33
35
  end
34
36
 
35
37
  def bytes
@@ -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
@@ -3,8 +3,8 @@
3
3
  module Klenod
4
4
  module Build
5
5
  Config =
6
- Data.define(:source_dir, :entrypoints, :output, :assets_dir, :plugins, :mode, :base_dir) do
7
- def initialize(source_dir: "src", entrypoints: [], output: "dist/klenod.bundle", assets_dir: nil, plugins: Context::DEFAULT_PLUGINS, mode: :development, base_dir: Dir.pwd)
6
+ Data.define(:source_dir, :entrypoints, :output, :assets_dir, :plugins, :mode, :base_dir, :base) do
7
+ def initialize(source_dir: "src", entrypoints: [], output: "dist/klenod.bundle", assets_dir: nil, plugins: Context::DEFAULT_PLUGINS, mode: :development, base_dir: Dir.pwd, base: Runtime::AssetUrl::DEFAULT_BASE)
8
8
  super(
9
9
  source_dir: source_dir,
10
10
  entrypoints: Array(entrypoints),
@@ -12,7 +12,8 @@ module Klenod
12
12
  assets_dir: assets_dir,
13
13
  plugins: plugins,
14
14
  mode: mode,
15
- base_dir: base_dir
15
+ base_dir: base_dir,
16
+ base: Runtime::AssetUrl.normalize(base)
16
17
  )
17
18
  end
18
19
 
@@ -25,6 +26,7 @@ module Klenod
25
26
  source_dir: source_path,
26
27
  plugins: plugins,
27
28
  mode: mode,
29
+ base: base,
28
30
  **overrides
29
31
  )
30
32
  end
@@ -60,6 +62,7 @@ module Klenod
60
62
  @plugins = Context::DEFAULT_PLUGINS
61
63
  @mode = :development
62
64
  @base_dir = base_dir
65
+ @base = Runtime::AssetUrl::DEFAULT_BASE
63
66
  end
64
67
 
65
68
  def source_dir(value = nil)
@@ -100,6 +103,12 @@ module Klenod
100
103
  @mode = value
101
104
  end
102
105
 
106
+ def base(value = nil)
107
+ return @base unless value
108
+
109
+ @base = value
110
+ end
111
+
103
112
  def config
104
113
  Config.new(
105
114
  source_dir: @source_dir,
@@ -108,7 +117,8 @@ module Klenod
108
117
  assets_dir: @assets_dir,
109
118
  plugins: @plugins,
110
119
  mode: @mode,
111
- base_dir: @base_dir
120
+ base_dir: @base_dir,
121
+ base: @base
112
122
  )
113
123
  end
114
124
  end
@@ -108,6 +108,7 @@ module Klenod
108
108
  source_dir:,
109
109
  plugins: DEFAULT_PLUGINS,
110
110
  mode: :development,
111
+ base: Runtime::AssetUrl::DEFAULT_BASE,
111
112
  asset_generation_concurrency: AssetGenerationQueue::DEFAULT_CONCURRENCY,
112
113
  asset_download_concurrency: AssetGenerationQueue::DEFAULT_DOWNLOAD_CONCURRENCY,
113
114
  profiler: nil
@@ -116,19 +117,21 @@ module Klenod
116
117
  plugins = plugins.to_a if plugins.equal?(DEFAULT_PLUGINS)
117
118
  @plugins = plugins
118
119
  @mode = mode
120
+ @base = Runtime::AssetUrl.normalize(base)
119
121
  @update_handlers = []
120
122
  @graph =
121
123
  Graph.new(
122
124
  source_dir: source_dir,
123
125
  plugins: plugins,
124
126
  mode: mode,
127
+ base: @base,
125
128
  asset_generation_concurrency: asset_generation_concurrency,
126
129
  asset_download_concurrency: asset_download_concurrency,
127
130
  profiler: profiler
128
131
  )
129
132
  end
130
133
 
131
- attr_reader :graph, :mode
134
+ attr_reader :graph, :mode, :base
132
135
 
133
136
  def evaluate(specifier)
134
137
  @graph.load(specifier)
@@ -177,6 +180,10 @@ module Klenod
177
180
  @graph.asset(output_path)
178
181
  end
179
182
 
183
+ def asset_url(asset_or_output_path)
184
+ @graph.asset_url(asset_or_output_path)
185
+ end
186
+
180
187
  def exports(record_or_module_id)
181
188
  return record_or_module_id.exports if record_or_module_id.is_a?(LoadedModule)
182
189
 
@@ -161,7 +161,6 @@ module Klenod
161
161
  end
162
162
 
163
163
  class DynamicImportError < Error; end
164
- class TestImportError < ResolveError; end
165
164
  class UnsupportedFileError < Error; end
166
165
 
167
166
  class ImportCycleError < Error
@@ -56,13 +56,14 @@ module Klenod
56
56
  end
57
57
  end
58
58
 
59
- attr_reader :records, :mods, :asset_generation_queue, :mode, :profiler
59
+ attr_reader :records, :mods, :asset_generation_queue, :mode, :profiler, :base
60
60
  attr_reader :plugins
61
61
 
62
62
  def initialize(
63
63
  source_dir:,
64
64
  plugins:,
65
65
  mode: :development,
66
+ base: Runtime::AssetUrl::DEFAULT_BASE,
66
67
  asset_generation_concurrency: AssetGenerationQueue::DEFAULT_CONCURRENCY,
67
68
  asset_download_concurrency: AssetGenerationQueue::DEFAULT_DOWNLOAD_CONCURRENCY,
68
69
  profiler: nil
@@ -71,6 +72,7 @@ module Klenod
71
72
  @resolver = Resolver.new(source_dir: source_dir, profiler: @profiler)
72
73
  @plugins = plugins
73
74
  @mode = mode
75
+ @base = Runtime::AssetUrl.normalize(base)
74
76
  @asset_generation_queue =
75
77
  AssetGenerationQueue.new(
76
78
  concurrency: asset_generation_concurrency,
@@ -112,7 +114,8 @@ module Klenod
112
114
  loaded_entrypoints,
113
115
  runtime_module_specs,
114
116
  runtime_asset_specs,
115
- source_root: source_dir.to_s
117
+ source_root: source_dir.to_s,
118
+ base: base
116
119
  )
117
120
  end
118
121
  end
@@ -125,6 +128,15 @@ module Klenod
125
128
  assets.fetch(output_path)
126
129
  end
127
130
 
131
+ def asset_url(asset_or_output_path)
132
+ if asset_or_output_path.respond_to?(:output_path)
133
+ asset = assets.fetch(asset_or_output_path.output_path, asset_or_output_path)
134
+ return asset.url || Runtime::AssetUrl.join(base, asset.output_path)
135
+ end
136
+
137
+ Runtime::AssetUrl.join(base, asset_or_output_path)
138
+ end
139
+
128
140
  def exports(record_or_module_id)
129
141
  module_id = module_id_for(record_or_module_id)
130
142
  evaluate_module(module_id).const_get(:Exports)
@@ -574,6 +586,7 @@ module Klenod
574
586
  end
575
587
 
576
588
  def build_module_record(module_id, source, source_hash, transformed_hash, transform, resolved_dependencies, cached_or_mod)
589
+ bind_asset_urls(transform.assets)
577
590
  version =
578
591
  if cached_or_mod.is_a?(Runtime::Mod)
579
592
  cached_or_mod.version
@@ -600,6 +613,10 @@ module Klenod
600
613
  )
601
614
  end
602
615
 
616
+ def bind_asset_urls(assets)
617
+ assets.each { |asset| asset.url ||= Runtime::AssetUrl.join(base, asset.output_path) }
618
+ end
619
+
603
620
  def load_dependency_records(resolved_dependencies)
604
621
  return {} if resolved_dependencies.empty?
605
622
 
@@ -771,7 +788,8 @@ module Klenod
771
788
  asset.content_hash,
772
789
  asset.output_path,
773
790
  asset.content_type,
774
- asset.metadata
791
+ asset.metadata,
792
+ asset.url
775
793
  )
776
794
  ]
777
795
  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
@@ -59,7 +59,7 @@ module Klenod
59
59
  }
60
60
  JAVASCRIPT
61
61
  CONTENT_HASH = Hashing.short(SOURCE)
62
- OUTPUT_PATH = "/assets/klenod_asset_metadata.#{CONTENT_HASH}.js"
62
+ OUTPUT_PATH = "/klenod_asset_metadata.#{CONTENT_HASH}.js"
63
63
 
64
64
  module_function
65
65
 
@@ -172,13 +172,14 @@ module Klenod
172
172
  font_url = Regexp.last_match[:url]
173
173
  asset = font_assets[font_url] ||= font_asset(font_url, font_faces[font_url], context)
174
174
 
175
- %(url(#{quote}#{asset.output_path}#{quote}))
175
+ %(url(#{quote}#{asset.url}#{quote}))
176
176
  end
177
177
  rewritten_css = append_fallback_font_faces(rewritten_css, font_faces.values) if @adjust_font_fallback
178
178
 
179
179
  css_asset = css_asset(module_id, url, rewritten_css, font_assets.keys)
180
+ css_asset.url = context.asset_url(css_asset.output_path)
180
181
  @assets_by_module_id[module_id] = [css_asset, *font_assets.values]
181
- ruby_module_source(css_asset.output_path)
182
+ ruby_module_source(css_asset.url)
182
183
  end
183
184
 
184
185
  def transform(module_id, code, _context)
@@ -242,7 +243,7 @@ module Klenod
242
243
 
243
244
  def css_asset(module_id, url, css, font_source_urls)
244
245
  hash = Hashing.short(css)
245
- output_path = "/assets/#{google_fonts_asset_name(url)}.#{hash}.css"
246
+ output_path = "/#{google_fonts_asset_name(url)}.#{hash}.css"
246
247
 
247
248
  Asset.new(
248
249
  module_id.to_s,
@@ -296,7 +297,7 @@ module Klenod
296
297
  hash = Hashing.short(url)
297
298
  uri = URI.parse(url)
298
299
  extname = File.extname(uri.path)
299
- output_path = "/assets/#{font_asset_name(uri, font_face)}.#{hash}#{extname}"
300
+ output_path = "/#{font_asset_name(uri, font_face)}.#{hash}#{extname}"
300
301
 
301
302
  Asset.generated(
302
303
  url,
@@ -314,6 +315,7 @@ module Klenod
314
315
  },
315
316
  writer: ->(io) { write_fetch(url, io) },
316
317
  queue: context.asset_generation_queue,
318
+ url: context.asset_url(output_path),
317
319
  queue_kind: :io
318
320
  ) do
319
321
  fetch(url)
@@ -51,7 +51,9 @@ module Klenod
51
51
  image_options = image_options_for(module_id)
52
52
  asset = default_image_asset(module_id, source_path, source_hash, dimensions, image_options, context.asset_generation_queue)
53
53
  variant_assets = generate_variant_assets(module_id, source_path, source_hash, dimensions, image_options, context.asset_generation_queue)
54
- javascript_asset = javascript_image_asset(module_id, asset, variant_assets)
54
+ [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)
56
+ javascript_asset.url = context.asset_url(javascript_asset.output_path)
55
57
  assets = [asset, *variant_assets]
56
58
  image_runtime_dependency =
57
59
  Dependency
@@ -64,7 +66,7 @@ module Klenod
64
66
 
65
67
  transform =
66
68
  TransformResult.new(
67
- image_module_source(module_id, assets, image_runtime_dependency),
69
+ image_module_source(module_id, assets, image_runtime_dependency, context),
68
70
  [image_runtime_dependency],
69
71
  nil,
70
72
  assets,
@@ -126,7 +128,7 @@ module Klenod
126
128
  Asset.new(
127
129
  module_id.path,
128
130
  hash,
129
- "/assets/#{asset_name(module_id)}.#{hash}#{module_id.extname}",
131
+ "/#{asset_name(module_id)}.#{hash}#{module_id.extname}",
130
132
  source_path,
131
133
  nil,
132
134
  content_type(module_id.extname),
@@ -154,7 +156,7 @@ module Klenod
154
156
  Asset.generated(
155
157
  module_id.path,
156
158
  hash,
157
- "/assets/#{asset_name(module_id)}.#{hash}#{extname}",
159
+ "/#{asset_name(module_id)}.#{hash}#{extname}",
158
160
  source_path,
159
161
  content_type(extname),
160
162
  metadata,
@@ -217,15 +219,15 @@ module Klenod
217
219
  "# image asset: #{module_id}\n"
218
220
  end
219
221
 
220
- def image_module_source(module_id, assets, image_runtime_dependency)
222
+ def image_module_source(module_id, assets, image_runtime_dependency, context)
221
223
  asset = image_asset(assets)
222
- variants = image_variant_assets(assets).map { |variant_asset| image_variant_source(variant_asset) }
224
+ variants = image_variant_assets(assets).map { |variant_asset| image_variant_source(variant_asset, context) }
223
225
 
224
226
  <<~RUBY
225
227
  ImageRuntime = __klenod_import__(#{image_runtime_dependency.id.inspect})
226
228
  Default =
227
229
  ImageRuntime::ImageMetadata.new(
228
- src: #{asset.output_path.inspect},
230
+ src: #{asset.url.inspect},
229
231
  width: #{asset.metadata[:width].inspect},
230
232
  height: #{asset.metadata[:height].inspect},
231
233
  content_type: #{asset.content_type.inspect},
@@ -238,10 +240,10 @@ module Klenod
238
240
  RUBY
239
241
  end
240
242
 
241
- def image_variant_source(asset)
243
+ def image_variant_source(asset, context)
242
244
  <<~RUBY.chomp
243
245
  ImageRuntime::ImageVariant.new(
244
- src: #{asset.output_path.inspect},
246
+ src: #{asset.url.inspect},
245
247
  width: #{asset.metadata[:width].inspect},
246
248
  height: #{asset.metadata[:height].inspect},
247
249
  content_type: #{asset.content_type.inspect},
@@ -253,13 +255,13 @@ module Klenod
253
255
  RUBY
254
256
  end
255
257
 
256
- def javascript_image_asset(module_id, asset, variant_assets)
257
- code = javascript_image_module_source(asset, variant_assets)
258
+ def javascript_image_asset(module_id, asset, variant_assets, context)
259
+ code = javascript_image_module_source(asset, variant_assets, context)
258
260
  hash = Hashing.short(code)
259
261
  Asset.new(
260
262
  module_id.path,
261
263
  hash,
262
- "/assets/#{asset_name(module_id)}.#{hash}#{module_id.extname}.js",
264
+ "/#{asset_name(module_id)}.#{hash}#{module_id.extname}.js",
263
265
  nil,
264
266
  code,
265
267
  "application/javascript",
@@ -267,10 +269,10 @@ module Klenod
267
269
  )
268
270
  end
269
271
 
270
- def javascript_image_module_source(asset, variant_assets)
271
- variants = variant_assets.map { "new ImageVariant(#{AssetJavaScriptMetadata.object_literal(javascript_image_variant(it))})" }
272
+ def javascript_image_module_source(asset, variant_assets, context)
273
+ variants = variant_assets.map { "new ImageVariant(#{AssetJavaScriptMetadata.object_literal(javascript_image_variant(it, context))})" }
272
274
  properties = {
273
- src: asset.output_path,
275
+ src: asset.url,
274
276
  width: asset.metadata[:width],
275
277
  height: asset.metadata[:height],
276
278
  contentType: asset.content_type,
@@ -279,14 +281,14 @@ module Klenod
279
281
  properties << %(variants:[#{variants.join(",")}])
280
282
 
281
283
  <<~JAVASCRIPT
282
- import ImageMetadata, { ImageVariant } from #{AssetJavaScriptMetadata::OUTPUT_PATH.inspect};
284
+ import ImageMetadata, { ImageVariant } from #{context.asset_url(AssetJavaScriptMetadata::OUTPUT_PATH).inspect};
283
285
  export default new ImageMetadata({#{properties.join(",")}});
284
286
  JAVASCRIPT
285
287
  end
286
288
 
287
- def javascript_image_variant(asset)
289
+ def javascript_image_variant(asset, context)
288
290
  {
289
- src: asset.output_path,
291
+ src: asset.url,
290
292
  width: asset.metadata[:width],
291
293
  height: asset.metadata[:height],
292
294
  contentType: asset.content_type,
@@ -338,7 +340,7 @@ module Klenod
338
340
  extname = ".#{format}"
339
341
  descriptor = "#{width}w"
340
342
  hash = Hashing.short("#{source_hash}:#{width}:#{format}:#{quality}")
341
- output_path = "/assets/#{asset_name(module_id)}.#{width}w.#{hash}#{extname}"
343
+ output_path = "/#{asset_name(module_id)}.#{width}w.#{hash}#{extname}"
342
344
  metadata = {
343
345
  type: :image_variant,
344
346
  width: width,
@@ -34,14 +34,14 @@ module Klenod
34
34
  svg_runtime_source
35
35
  end
36
36
 
37
- def transform(module_id, code, _context)
37
+ def transform(module_id, code, context)
38
38
  return super unless EXTENSIONS.include?(module_id.extname)
39
39
 
40
40
  raise UnsupportedFileError, "SVG imports do not support query options: #{module_id}" if module_id.query
41
41
 
42
42
  dimensions = svg_dimensions(code)
43
43
  hash = Hashing.short(code)
44
- output_path = "/assets/#{asset_name(module_id)}.#{hash}.svg"
44
+ output_path = "/#{asset_name(module_id)}.#{hash}.svg"
45
45
  asset =
46
46
  Asset.new(
47
47
  module_id.path,
@@ -56,7 +56,9 @@ module Klenod
56
56
  height: dimensions.height
57
57
  }
58
58
  )
59
- javascript_asset = javascript_svg_asset(module_id, asset)
59
+ asset.url = context.asset_url(asset.output_path)
60
+ javascript_asset = javascript_svg_asset(module_id, asset, context)
61
+ javascript_asset.url = context.asset_url(javascript_asset.output_path)
60
62
  svg_runtime_dependency =
61
63
  Dependency
62
64
  .create(
@@ -67,7 +69,7 @@ module Klenod
67
69
  .with(id: "#{module_id}:svg_runtime")
68
70
 
69
71
  TransformResult.new(
70
- svg_module_source(asset, svg_runtime_dependency),
72
+ svg_module_source(asset, svg_runtime_dependency, context),
71
73
  [svg_runtime_dependency],
72
74
  nil,
73
75
  [asset],
@@ -100,12 +102,12 @@ module Klenod
100
102
  RUBY
101
103
  end
102
104
 
103
- def svg_module_source(asset, svg_runtime_dependency)
105
+ def svg_module_source(asset, svg_runtime_dependency, context)
104
106
  <<~RUBY
105
107
  SvgRuntime = __klenod_import__(#{svg_runtime_dependency.id.inspect})
106
108
  Default =
107
109
  SvgRuntime::SvgMetadata.new(
108
- src: #{asset.output_path.inspect},
110
+ src: #{asset.url.inspect},
109
111
  width: #{asset.metadata[:width].inspect},
110
112
  height: #{asset.metadata[:height].inspect},
111
113
  content_type: #{asset.content_type.inspect},
@@ -115,13 +117,13 @@ module Klenod
115
117
  RUBY
116
118
  end
117
119
 
118
- def javascript_svg_asset(module_id, asset)
119
- code = javascript_svg_module_source(asset)
120
+ def javascript_svg_asset(module_id, asset, context)
121
+ code = javascript_svg_module_source(asset, context)
120
122
  hash = Hashing.short(code)
121
123
  Asset.new(
122
124
  module_id.path,
123
125
  hash,
124
- "/assets/#{asset_name(module_id)}.#{hash}#{module_id.extname}.js",
126
+ "/#{asset_name(module_id)}.#{hash}#{module_id.extname}.js",
125
127
  nil,
126
128
  code,
127
129
  "application/javascript",
@@ -129,9 +131,9 @@ module Klenod
129
131
  )
130
132
  end
131
133
 
132
- def javascript_svg_module_source(asset)
134
+ def javascript_svg_module_source(asset, context)
133
135
  metadata = {
134
- src: asset.output_path,
136
+ src: asset.url,
135
137
  width: asset.metadata[:width],
136
138
  height: asset.metadata[:height],
137
139
  contentType: asset.content_type,
@@ -139,7 +141,7 @@ module Klenod
139
141
  }
140
142
 
141
143
  <<~JAVASCRIPT
142
- import { SvgMetadata } from #{AssetJavaScriptMetadata::OUTPUT_PATH.inspect};
144
+ import { SvgMetadata } from #{context.asset_url(AssetJavaScriptMetadata::OUTPUT_PATH).inspect};
143
145
  export default new SvgMetadata(#{AssetJavaScriptMetadata.object_literal(metadata)});
144
146
  JAVASCRIPT
145
147
  end
@@ -17,7 +17,6 @@ module Klenod
17
17
  autoload :TomlPlugin, File.expand_path("plugins/data_plugin", __dir__)
18
18
  autoload :TextPlugin, File.expand_path("plugins/data_plugin", __dir__)
19
19
  autoload :RouterPlugin, File.expand_path("plugins/router_plugin", __dir__)
20
- autoload :TestPlugin, File.expand_path("plugins/test_plugin", __dir__)
21
20
  end
22
21
  end
23
22
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Klenod
4
4
  module Build
5
- VERSION = "0.0.4"
5
+ VERSION = "0.0.6"
6
6
  end
7
7
  end
data/lib/klenod/build.rb CHANGED
@@ -9,8 +9,6 @@ module Klenod
9
9
 
10
10
  module Build
11
11
  autoload :Graphviz, "klenod/build/graphviz"
12
- autoload :TestSelection, "klenod/build/test_suite"
13
- autoload :TestSuite, "klenod/build/test_suite"
14
12
  autoload :UpdateEvent, "klenod/build/watcher"
15
13
  autoload :Watcher, "klenod/build/watcher"
16
14
  end
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
4
+ version: 0.0.6
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.4
18
+ version: 0.0.6
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.4
25
+ version: 0.0.6
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: async
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -41,16 +41,22 @@ dependencies:
41
41
  name: async-http
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: 0.95.1
47
+ - - "<"
48
+ - !ruby/object:Gem::Version
49
+ version: 0.104.0
47
50
  type: :runtime
48
51
  prerelease: false
49
52
  version_requirements: !ruby/object:Gem::Requirement
50
53
  requirements:
51
- - - "~>"
54
+ - - ">="
52
55
  - !ruby/object:Gem::Version
53
56
  version: 0.95.1
57
+ - - "<"
58
+ - !ruby/object:Gem::Version
59
+ version: 0.104.0
54
60
  - !ruby/object:Gem::Dependency
55
61
  name: brotli
56
62
  requirement: !ruby/object:Gem::Requirement
@@ -272,7 +278,6 @@ files:
272
278
  - lib/klenod/build/plugins/router_plugin.rb
273
279
  - lib/klenod/build/plugins/ruby_plugin.rb
274
280
  - lib/klenod/build/plugins/svg_plugin.rb
275
- - lib/klenod/build/plugins/test_plugin.rb
276
281
  - lib/klenod/build/profiler.rb
277
282
  - lib/klenod/build/resolution_error_formatter.rb
278
283
  - lib/klenod/build/resolver.rb
@@ -281,7 +286,6 @@ files:
281
286
  - lib/klenod/build/source_map/editor.rb
282
287
  - lib/klenod/build/source_map/map.rb
283
288
  - lib/klenod/build/source_map/vlq.rb
284
- - lib/klenod/build/test_suite.rb
285
289
  - lib/klenod/build/transform_result.rb
286
290
  - lib/klenod/build/version.rb
287
291
  - lib/klenod/build/watched_pattern.rb
@@ -299,7 +303,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
299
303
  requirements:
300
304
  - - ">="
301
305
  - !ruby/object:Gem::Version
302
- version: 4.0.6
306
+ version: '4.0'
303
307
  required_rubygems_version: !ruby/object:Gem::Requirement
304
308
  requirements:
305
309
  - - ">="
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../errors"
4
- require_relative "../module_id"
5
- require_relative "../plugin"
6
-
7
- module Klenod
8
- module Build
9
- module Plugins
10
- module TestPlugin
11
- def self.new(...)
12
- Plugin.new(...)
13
- end
14
-
15
- class Plugin < Klenod::Build::Plugin
16
- DEFAULT_PATTERN = "**/*.test.rb"
17
-
18
- def initialize(pattern: DEFAULT_PATTERN)
19
- @pattern = pattern.to_s
20
- end
21
-
22
- attr_reader :pattern
23
-
24
- def discover(source_dir:)
25
- root = Pathname.new(source_dir).expand_path
26
-
27
- root
28
- .glob(pattern)
29
- .select(&:file?)
30
- .map { |path| ModuleId.new(path.relative_path_from(root).to_s.tr("\\", "/"), nil) }
31
- .sort_by(&:to_s)
32
- end
33
-
34
- def test_module_id?(module_id)
35
- module_id.scheme == :app && File.fnmatch?(pattern, module_id.relative_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
36
- end
37
-
38
- def finalize(module_id, result, resolved_dependencies, _dependency_records, _context)
39
- imported_test = resolved_dependencies.find { |dependency| test_module_id?(dependency.module_id) }
40
- return result unless imported_test
41
-
42
- error = TestImportError.new("Test file #{imported_test.module_id.path.inspect} cannot be imported")
43
- raise error.with_resolution_context(dependency: imported_test.dependency, importer_id: module_id)
44
- end
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Klenod
4
- module Build
5
- TestSelection = Data.define(:test_paths, :removed_test_paths) do
6
- def empty?
7
- test_paths.empty? && removed_test_paths.empty?
8
- end
9
- end
10
-
11
- class TestSuite
12
- def initialize(context:, plugin:)
13
- @context = context
14
- @plugin = plugin
15
- @dependency_ids = {}
16
- @failed_test_ids = Set.new
17
- end
18
-
19
- def collect
20
- test_ids = discover
21
- test_ids.each { |test_id| index(test_id) }
22
- selection(test_ids)
23
- end
24
-
25
- def update(event)
26
- previous_test_ids = @dependency_ids.keys.to_set
27
- current_test_ids = discover.to_set
28
- removed_test_ids = previous_test_ids - current_test_ids
29
- added_test_ids = current_test_ids - previous_test_ids
30
- affected_module_ids = update_module_ids(event)
31
- affected_test_ids =
32
- @dependency_ids.filter_map do |test_id, dependency_ids|
33
- test_id if current_test_ids.include?(test_id) && dependency_ids.intersect?(affected_module_ids)
34
- end
35
-
36
- test_ids = (added_test_ids + affected_test_ids + @failed_test_ids).select { |test_id| current_test_ids.include?(test_id) }
37
- removed_test_ids.each { |test_id| remove(test_id) }
38
- test_ids.each { |test_id| index(test_id) }
39
-
40
- selection(test_ids, removed_test_ids)
41
- end
42
-
43
- private
44
-
45
- attr_reader :context, :plugin
46
-
47
- def discover
48
- plugin.discover(source_dir: context.graph.source_dir)
49
- end
50
-
51
- def index(test_id)
52
- dependency_ids = Set[test_id]
53
- @dependency_ids[test_id] = dependency_ids
54
- collect_dependencies(test_id, dependency_ids)
55
- @failed_test_ids.delete(test_id)
56
- rescue
57
- @failed_test_ids << test_id
58
- end
59
-
60
- def collect_dependencies(module_id, dependency_ids)
61
- record = context.graph.records[module_id] || context.graph.collect_module(module_id)
62
-
63
- record.resolved_dependencies.each do |dependency|
64
- dependency_id = dependency.module_id
65
- next unless dependency_ids.add?(dependency_id)
66
-
67
- collect_dependencies(dependency_id, dependency_ids)
68
- end
69
- end
70
-
71
- def remove(test_id)
72
- @dependency_ids.delete(test_id)
73
- @failed_test_ids.delete(test_id)
74
- end
75
-
76
- def update_module_ids(event)
77
- result = event.result
78
- Set.new(
79
- result.changed_module_ids +
80
- result.removed_module_ids +
81
- result.reloaded_module_ids +
82
- result.reevaluated_module_ids
83
- )
84
- end
85
-
86
- def selection(test_ids, removed_test_ids = [])
87
- TestSelection.new(
88
- test_ids.map(&:relative_path).sort.freeze,
89
- removed_test_ids.map(&:relative_path).sort.freeze
90
- )
91
- end
92
- end
93
- end
94
- end