klenod-build 0.0.2 → 0.0.4

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: 3f6f0bd5e9b747b26e394d5c041f30ce22aa9436f8483689172c48ae2219af1b
4
- data.tar.gz: 8a11818a46097229cab6c5c2f94515306f9f989c7b2c49eefcb045b46e68a3a8
3
+ metadata.gz: 560774e128fafb845afbff51f556e3eb30d3a1b7d280b9fbdc7ac36b48c4b741
4
+ data.tar.gz: 559ce8134726f2fa31084811a9dcda01987a957c073370f5ac0595c8d7a3f703
5
5
  SHA512:
6
- metadata.gz: f10d5c296da38e42bfd54e37366dd28e834bbb21b2ed455ea0ab1b325eb4e43ca2e8dc41b0e0d30b6709db8563441573ed5132a9d85ef1f81d8287459a9c40a0
7
- data.tar.gz: ed6f70303f40f60b71147980de86b84482106407d927ac7aa248efccb92c2ee83cff94fdf0baa382e2e18229460e526cad265679383d27b8d80aa2ce8106edde
6
+ metadata.gz: 77cb936bd77e35262827d9903124f1b37cec73bb11db28c1a5e497d02a20d9283e989a46524c2f674b7c0f49734632e3da02b324a4988dbccbe3fe244e591921
7
+ data.tar.gz: eccc054b80b674a4f304fb6ec2abbdaf3bdf244576dc0f9bfd7b0d23b7b35ac77f5a47a061ad013cd9743295606b7ca3526a50e8f2dff48cc86ba13d4dac6fc2
@@ -161,6 +161,7 @@ module Klenod
161
161
  end
162
162
 
163
163
  class DynamicImportError < Error; end
164
+ class TestImportError < ResolveError; end
164
165
  class UnsupportedFileError < Error; end
165
166
 
166
167
  class ImportCycleError < Error
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ require_relative "../asset"
6
+ require_relative "../hashing"
7
+
8
+ module Klenod
9
+ module Build
10
+ module Plugins
11
+ module AssetJavaScriptMetadata
12
+ IDENTIFIER_PATTERN = /\A[$A-Z_a-z][$0-9A-Z_a-z]*\z/
13
+ LOGICAL_NAME = "virtual:klenod/asset-metadata.js"
14
+ SOURCE = <<~JAVASCRIPT
15
+ export class ImageBase {
16
+ constructor({ src, width, height, contentType, aspectRatio }) {
17
+ this.src = src;
18
+ this.width = width;
19
+ this.height = height;
20
+ this.contentType = contentType;
21
+ this.aspectRatio = aspectRatio;
22
+ }
23
+ }
24
+
25
+ export class ImageVariant extends ImageBase {
26
+ constructor({ src, width, height, contentType, aspectRatio, format, descriptor, quality }) {
27
+ super({ src, width, height, contentType, aspectRatio });
28
+ this.format = format;
29
+ this.descriptor = descriptor;
30
+ this.quality = quality;
31
+ Object.freeze(this);
32
+ }
33
+ }
34
+
35
+ export default class ImageMetadata extends ImageBase {
36
+ constructor({ src, width, height, contentType, aspectRatio, variants = [] }) {
37
+ super({ src, width, height, contentType, aspectRatio });
38
+ this.variants = Object.freeze([...variants]);
39
+ Object.freeze(this);
40
+ }
41
+
42
+ get srcset() {
43
+ if (this.variants.length === 0) return null;
44
+ return this.variants.map((variant) => `${variant.src} ${variant.descriptor}`).join(", ");
45
+ }
46
+
47
+ get sizes() {
48
+ const variantWidths = this.variants.map((variant) => variant.width).filter(Boolean);
49
+ const displayWidth = variantWidths.length > 0 ? Math.max(...variantWidths) : this.width;
50
+ return displayWidth ? `(max-width: ${displayWidth}px) 100vw, ${displayWidth}px` : null;
51
+ }
52
+ }
53
+
54
+ export class SvgMetadata extends ImageBase {
55
+ constructor({ src, width, height, contentType, aspectRatio }) {
56
+ super({ src, width, height, contentType, aspectRatio });
57
+ Object.freeze(this);
58
+ }
59
+ }
60
+ JAVASCRIPT
61
+ CONTENT_HASH = Hashing.short(SOURCE)
62
+ OUTPUT_PATH = "/assets/klenod_asset_metadata.#{CONTENT_HASH}.js"
63
+
64
+ module_function
65
+
66
+ def object_literal(properties)
67
+ "{#{properties.map { |key, value| property(key, value) }.join(",")}}"
68
+ end
69
+
70
+ def aspect_ratio(width, height)
71
+ return nil unless width && height && !height.zero?
72
+
73
+ width.to_f / height
74
+ end
75
+
76
+ def property(key, value)
77
+ name = key.to_s
78
+ name = JSON.generate(name) unless name.match?(IDENTIFIER_PATTERN)
79
+ "#{name}:#{JSON.generate(value)}"
80
+ end
81
+
82
+ def asset
83
+ Asset.new(
84
+ LOGICAL_NAME,
85
+ CONTENT_HASH,
86
+ OUTPUT_PATH,
87
+ nil,
88
+ SOURCE,
89
+ "application/javascript",
90
+ {type: :javascript, javascript_runtime: :asset_metadata}
91
+ )
92
+ end
93
+ end
94
+ end
95
+ end
96
+ 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
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "image_size"
4
- require "json"
5
4
  require "rmagick"
6
5
  require "uri"
7
6
 
@@ -11,6 +10,7 @@ require_relative "../hashing"
11
10
  require_relative "../load_result"
12
11
  require_relative "../plugin"
13
12
  require_relative "../transform_result"
13
+ require_relative "asset_javascript_metadata"
14
14
 
15
15
  module Klenod
16
16
  module Build
@@ -52,7 +52,7 @@ module Klenod
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
54
  javascript_asset = javascript_image_asset(module_id, asset, variant_assets)
55
- assets = [asset, *variant_assets, javascript_asset]
55
+ assets = [asset, *variant_assets]
56
56
  image_runtime_dependency =
57
57
  Dependency
58
58
  .create(
@@ -69,7 +69,7 @@ module Klenod
69
69
  nil,
70
70
  assets,
71
71
  [],
72
- {image_javascript_asset_path: javascript_asset.output_path}
72
+ {image_javascript_asset: javascript_asset}
73
73
  )
74
74
  LoadResult.new(
75
75
  image_source(module_id),
@@ -185,8 +185,14 @@ module Klenod
185
185
 
186
186
  def image_runtime_source
187
187
  <<~RUBY
188
- Image =
189
- Data.define(:src, :width, :height, :content_type, :variants) do
188
+ ImageMetadata =
189
+ Data.define(:src, :width, :height, :content_type, :aspect_ratio, :variants) do
190
+ def initialize(src:, width:, height:, content_type:, aspect_ratio:, variants:)
191
+ super(src:, width:, height:, content_type:, aspect_ratio:, variants: variants.dup.freeze)
192
+ end
193
+
194
+ alias to_s src
195
+
190
196
  def srcset
191
197
  return nil if variants.empty?
192
198
 
@@ -201,7 +207,9 @@ module Klenod
201
207
  end
202
208
  end
203
209
 
204
- ImageVariant = Data.define(:src, :width, :height, :content_type, :format, :descriptor, :metadata)
210
+ ImageVariant = Data.define(:src, :width, :height, :content_type, :aspect_ratio, :format, :descriptor, :quality) do
211
+ alias to_s src
212
+ end
205
213
  RUBY
206
214
  end
207
215
 
@@ -216,11 +224,12 @@ module Klenod
216
224
  <<~RUBY
217
225
  ImageRuntime = __klenod_import__(#{image_runtime_dependency.id.inspect})
218
226
  Default =
219
- ImageRuntime::Image.new(
227
+ ImageRuntime::ImageMetadata.new(
220
228
  src: #{asset.output_path.inspect},
221
229
  width: #{asset.metadata[:width].inspect},
222
230
  height: #{asset.metadata[:height].inspect},
223
231
  content_type: #{asset.content_type.inspect},
232
+ aspect_ratio: #{AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height]).inspect},
224
233
  variants: [
225
234
  #{variants.join(",\n ")}
226
235
  ]
@@ -236,9 +245,10 @@ module Klenod
236
245
  width: #{asset.metadata[:width].inspect},
237
246
  height: #{asset.metadata[:height].inspect},
238
247
  content_type: #{asset.content_type.inspect},
248
+ aspect_ratio: #{AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height]).inspect},
239
249
  format: #{asset.metadata[:format].inspect},
240
250
  descriptor: #{asset.metadata[:descriptor].inspect},
241
- metadata: #{asset.metadata.inspect}
251
+ quality: #{asset.metadata[:quality].inspect}
242
252
  )
243
253
  RUBY
244
254
  end
@@ -249,7 +259,7 @@ module Klenod
249
259
  Asset.new(
250
260
  module_id.path,
251
261
  hash,
252
- "#{asset.output_path}.js",
262
+ "/assets/#{asset_name(module_id)}.#{hash}#{module_id.extname}.js",
253
263
  nil,
254
264
  code,
255
265
  "application/javascript",
@@ -258,21 +268,20 @@ module Klenod
258
268
  end
259
269
 
260
270
  def javascript_image_module_source(asset, variant_assets)
261
- variants = variant_assets.map { |variant_asset| javascript_image_variant(variant_asset) }
262
- srcset = variant_assets.empty? ? nil : variant_assets.map { "#{it.output_path} #{it.metadata[:descriptor]}" }.join(", ")
263
- display_width = variant_assets.filter_map { it.metadata[:width] }.max || asset.metadata[:width]
264
- sizes = display_width ? "(max-width: #{display_width}px) 100vw, #{display_width}px" : nil
265
- metadata = {
271
+ variants = variant_assets.map { "new ImageVariant(#{AssetJavaScriptMetadata.object_literal(javascript_image_variant(it))})" }
272
+ properties = {
266
273
  src: asset.output_path,
267
274
  width: asset.metadata[:width],
268
275
  height: asset.metadata[:height],
269
276
  contentType: asset.content_type,
270
- variants: variants,
271
- srcset: srcset,
272
- sizes: sizes
273
- }
274
-
275
- "export default #{JSON.generate(metadata)};\n"
277
+ aspectRatio: AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height])
278
+ }.map { |key, value| AssetJavaScriptMetadata.property(key, value) }
279
+ properties << %(variants:[#{variants.join(",")}])
280
+
281
+ <<~JAVASCRIPT
282
+ import ImageMetadata, { ImageVariant } from #{AssetJavaScriptMetadata::OUTPUT_PATH.inspect};
283
+ export default new ImageMetadata({#{properties.join(",")}});
284
+ JAVASCRIPT
276
285
  end
277
286
 
278
287
  def javascript_image_variant(asset)
@@ -281,10 +290,11 @@ module Klenod
281
290
  width: asset.metadata[:width],
282
291
  height: asset.metadata[:height],
283
292
  contentType: asset.content_type,
293
+ aspectRatio: AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height]),
284
294
  format: asset.metadata[:format],
285
295
  descriptor: asset.metadata[:descriptor],
286
- metadata: asset.metadata
287
- }
296
+ quality: asset.metadata[:quality]
297
+ }.compact
288
298
  end
289
299
 
290
300
  def image_asset(assets)
@@ -334,8 +344,7 @@ module Klenod
334
344
  width: width,
335
345
  height: scaled_height(dimensions, width),
336
346
  format: format.to_sym,
337
- descriptor: descriptor,
338
- source_width: width
347
+ descriptor: descriptor
339
348
  }
340
349
  metadata[:quality] = quality if quality
341
350
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
4
-
5
3
  require_relative "../asset"
6
4
  require_relative "../dependency"
7
5
  require_relative "../errors"
@@ -9,6 +7,7 @@ require_relative "../hashing"
9
7
  require_relative "../module_id"
10
8
  require_relative "../plugin"
11
9
  require_relative "../transform_result"
10
+ require_relative "asset_javascript_metadata"
12
11
 
13
12
  module Klenod
14
13
  module Build
@@ -71,9 +70,9 @@ module Klenod
71
70
  svg_module_source(asset, svg_runtime_dependency),
72
71
  [svg_runtime_dependency],
73
72
  nil,
74
- [asset, javascript_asset],
73
+ [asset],
75
74
  [],
76
- {asset_bytes: code, svg_javascript_asset_path: javascript_asset.output_path}
75
+ {asset_bytes: code, svg_javascript_asset: javascript_asset}
77
76
  )
78
77
  end
79
78
 
@@ -95,7 +94,9 @@ module Klenod
95
94
 
96
95
  def svg_runtime_source
97
96
  <<~RUBY
98
- Svg = Data.define(:src, :width, :height, :content_type)
97
+ SvgMetadata = Data.define(:src, :width, :height, :content_type, :aspect_ratio) do
98
+ alias to_s src
99
+ end
99
100
  RUBY
100
101
  end
101
102
 
@@ -103,11 +104,12 @@ module Klenod
103
104
  <<~RUBY
104
105
  SvgRuntime = __klenod_import__(#{svg_runtime_dependency.id.inspect})
105
106
  Default =
106
- SvgRuntime::Svg.new(
107
+ SvgRuntime::SvgMetadata.new(
107
108
  src: #{asset.output_path.inspect},
108
109
  width: #{asset.metadata[:width].inspect},
109
110
  height: #{asset.metadata[:height].inspect},
110
- content_type: #{asset.content_type.inspect}
111
+ content_type: #{asset.content_type.inspect},
112
+ aspect_ratio: #{AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height]).inspect}
111
113
  )
112
114
 
113
115
  RUBY
@@ -119,7 +121,7 @@ module Klenod
119
121
  Asset.new(
120
122
  module_id.path,
121
123
  hash,
122
- "#{asset.output_path}.js",
124
+ "/assets/#{asset_name(module_id)}.#{hash}#{module_id.extname}.js",
123
125
  nil,
124
126
  code,
125
127
  "application/javascript",
@@ -132,10 +134,14 @@ module Klenod
132
134
  src: asset.output_path,
133
135
  width: asset.metadata[:width],
134
136
  height: asset.metadata[:height],
135
- contentType: asset.content_type
137
+ contentType: asset.content_type,
138
+ aspectRatio: AssetJavaScriptMetadata.aspect_ratio(asset.metadata[:width], asset.metadata[:height])
136
139
  }
137
140
 
138
- "export default #{JSON.generate(metadata)};\n"
141
+ <<~JAVASCRIPT
142
+ import { SvgMetadata } from #{AssetJavaScriptMetadata::OUTPUT_PATH.inspect};
143
+ export default new SvgMetadata(#{AssetJavaScriptMetadata.object_literal(metadata)});
144
+ JAVASCRIPT
139
145
  end
140
146
 
141
147
  def svg_dimensions(code)
@@ -0,0 +1,49 @@
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
@@ -17,6 +17,7 @@ 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__)
20
21
  end
21
22
  end
22
23
  end
@@ -0,0 +1,94 @@
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Klenod
4
4
  module Build
5
- VERSION = "0.0.2"
5
+ VERSION = "0.0.4"
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
data/lib/klenod/build.rb CHANGED
@@ -9,6 +9,8 @@ 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"
12
14
  autoload :UpdateEvent, "klenod/build/watcher"
13
15
  autoload :Watcher, "klenod/build/watcher"
14
16
  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.2
4
+ version: 0.0.4
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.2
18
+ version: 0.0.4
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.2
25
+ version: 0.0.4
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: async
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -249,6 +249,7 @@ files:
249
249
  - lib/klenod/build/module_record.rb
250
250
  - lib/klenod/build/plugin.rb
251
251
  - lib/klenod/build/plugins.rb
252
+ - lib/klenod/build/plugins/asset_javascript_metadata.rb
252
253
  - lib/klenod/build/plugins/class_names_runtime.rb
253
254
  - lib/klenod/build/plugins/component_defaults.rb
254
255
  - lib/klenod/build/plugins/data_plugin.rb
@@ -271,6 +272,7 @@ files:
271
272
  - lib/klenod/build/plugins/router_plugin.rb
272
273
  - lib/klenod/build/plugins/ruby_plugin.rb
273
274
  - lib/klenod/build/plugins/svg_plugin.rb
275
+ - lib/klenod/build/plugins/test_plugin.rb
274
276
  - lib/klenod/build/profiler.rb
275
277
  - lib/klenod/build/resolution_error_formatter.rb
276
278
  - lib/klenod/build/resolver.rb
@@ -279,6 +281,7 @@ files:
279
281
  - lib/klenod/build/source_map/editor.rb
280
282
  - lib/klenod/build/source_map/map.rb
281
283
  - lib/klenod/build/source_map/vlq.rb
284
+ - lib/klenod/build/test_suite.rb
282
285
  - lib/klenod/build/transform_result.rb
283
286
  - lib/klenod/build/version.rb
284
287
  - lib/klenod/build/watched_pattern.rb