klenod-build 0.0.1

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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +29 -0
  3. data/lib/klenod/build/asset.rb +235 -0
  4. data/lib/klenod/build/asset_compression.rb +58 -0
  5. data/lib/klenod/build/asset_generation_queue.rb +50 -0
  6. data/lib/klenod/build/cli/application.rb +108 -0
  7. data/lib/klenod/build/cli.rb +3 -0
  8. data/lib/klenod/build/config.rb +142 -0
  9. data/lib/klenod/build/context.rb +370 -0
  10. data/lib/klenod/build/dependency.rb +21 -0
  11. data/lib/klenod/build/errors.rb +175 -0
  12. data/lib/klenod/build/filesystem_resolver.rb +147 -0
  13. data/lib/klenod/build/graph/invalidator.rb +246 -0
  14. data/lib/klenod/build/graph.rb +864 -0
  15. data/lib/klenod/build/graphviz.rb +282 -0
  16. data/lib/klenod/build/hashing.rb +21 -0
  17. data/lib/klenod/build/invalidation_result.rb +55 -0
  18. data/lib/klenod/build/load_result.rb +7 -0
  19. data/lib/klenod/build/loaded_module.rb +38 -0
  20. data/lib/klenod/build/module_id.rb +100 -0
  21. data/lib/klenod/build/module_record.rb +22 -0
  22. data/lib/klenod/build/plugin.rb +35 -0
  23. data/lib/klenod/build/plugins/class_names_runtime.rb +125 -0
  24. data/lib/klenod/build/plugins/component_defaults.rb +12 -0
  25. data/lib/klenod/build/plugins/data_plugin.rb +117 -0
  26. data/lib/klenod/build/plugins/gem_import_plugin.rb +125 -0
  27. data/lib/klenod/build/plugins/google_fonts_plugin/font_metrics.json +17687 -0
  28. data/lib/klenod/build/plugins/google_fonts_plugin/font_metrics.rb +105 -0
  29. data/lib/klenod/build/plugins/google_fonts_plugin/font_metrics.txt +31 -0
  30. data/lib/klenod/build/plugins/google_fonts_plugin.rb +387 -0
  31. data/lib/klenod/build/plugins/haml_plugin/companions.rb +40 -0
  32. data/lib/klenod/build/plugins/haml_plugin/errors.rb +114 -0
  33. data/lib/klenod/build/plugins/haml_plugin/helper_source.rb +123 -0
  34. data/lib/klenod/build/plugins/haml_plugin/parser.rb +85 -0
  35. data/lib/klenod/build/plugins/haml_plugin/transformer/ruby_builder.rb +1039 -0
  36. data/lib/klenod/build/plugins/haml_plugin/transformer.rb +766 -0
  37. data/lib/klenod/build/plugins/haml_plugin.rb +369 -0
  38. data/lib/klenod/build/plugins/image_plugin.rb +401 -0
  39. data/lib/klenod/build/plugins/intl_plugin.rb +34 -0
  40. data/lib/klenod/build/plugins/markdown_compiler.rb +180 -0
  41. data/lib/klenod/build/plugins/markdown_plugin.rb +161 -0
  42. data/lib/klenod/build/plugins/router_plugin.rb +942 -0
  43. data/lib/klenod/build/plugins/ruby_plugin.rb +34 -0
  44. data/lib/klenod/build/plugins/svg_plugin.rb +197 -0
  45. data/lib/klenod/build/plugins.rb +22 -0
  46. data/lib/klenod/build/profiler.rb +79 -0
  47. data/lib/klenod/build/resolution_error_formatter.rb +42 -0
  48. data/lib/klenod/build/resolver.rb +95 -0
  49. data/lib/klenod/build/ruby_import_rewriter.rb +436 -0
  50. data/lib/klenod/build/source_map/editor.rb +110 -0
  51. data/lib/klenod/build/source_map/map.rb +168 -0
  52. data/lib/klenod/build/source_map/vlq.rb +68 -0
  53. data/lib/klenod/build/source_map.rb +12 -0
  54. data/lib/klenod/build/transform_result.rb +12 -0
  55. data/lib/klenod/build/version.rb +7 -0
  56. data/lib/klenod/build/watched_pattern.rb +11 -0
  57. data/lib/klenod/build/watcher.rb +141 -0
  58. data/lib/klenod/build.rb +15 -0
  59. metadata +310 -0
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Klenod
4
+ module Build
5
+ module Plugins
6
+ module HamlPlugin
7
+ module HelperSource
8
+ private
9
+
10
+ def haml_helper_dependency(module_id)
11
+ Dependency
12
+ .create(
13
+ specifier: HAML_HELPER_SPECIFIER,
14
+ importer_id: module_id,
15
+ kind: :haml_helper
16
+ )
17
+ .with(id: "#{module_id}:haml_helper")
18
+ end
19
+
20
+ def haml_helper_source
21
+ <<~RUBY
22
+ # frozen_string_literal: true
23
+
24
+ module Default
25
+ def self.merge_props(component_class, *sources)
26
+ result = {}
27
+ classes = []
28
+
29
+ sources.each do |source|
30
+ next unless source
31
+
32
+ source.each do |key, value|
33
+ key = normalize_prop_key(key)
34
+ if key == :class
35
+ collect_class_values(classes, value)
36
+ else
37
+ result[key] = value
38
+ end
39
+ end
40
+ end
41
+
42
+ class_name = class_name(component_class, classes)
43
+ result[:class] = class_name if class_name
44
+ result
45
+ end
46
+
47
+ def self.normalize_prop_key(key)
48
+ return key if key.is_a?(Symbol) && !key.to_s.include?("-")
49
+
50
+ key.to_s.tr("-", "_").to_sym
51
+ end
52
+
53
+ def self.collect_class_values(classes, value)
54
+ case value
55
+ when nil, false
56
+ nil
57
+ when Array
58
+ value.each { |item| collect_class_values(classes, item) }
59
+ else
60
+ classes << value
61
+ end
62
+ end
63
+
64
+ def self.class_name(component_class, classes)
65
+ return nil if classes.empty?
66
+
67
+ styles = component_class.const_defined?(:ClassNames, false) ? component_class::ClassNames : nil
68
+ return nil unless styles.respond_to?(:class_name)
69
+
70
+ styles.class_name(*classes)
71
+ end
72
+
73
+ def self.render_slot(component, name = nil, fallback = nil)
74
+ children =
75
+ if component.respond_to?(:children)
76
+ name ? component.children[name] : component.children
77
+ elsif component.respond_to?(:__slots)
78
+ component.__slots[name&.to_sym]
79
+ end
80
+
81
+ return children if children && !children.empty?
82
+
83
+ fallback
84
+ end
85
+
86
+ def self.freeze_static(value, seen = {})
87
+ return value if value.nil? || value == true || value == false || value.is_a?(Symbol) || value.is_a?(Numeric)
88
+
89
+ object_id = value.object_id
90
+ return value if seen[object_id]
91
+
92
+ seen[object_id] = true
93
+
94
+ case value
95
+ when String
96
+ nil
97
+ when Array
98
+ value.each { |child| freeze_static(child, seen) }
99
+ when Hash
100
+ value.each do |key, child|
101
+ freeze_static(key, seen)
102
+ freeze_static(child, seen)
103
+ end
104
+ else
105
+ value.deconstruct.each { |child| freeze_static(child, seen) } if value.respond_to?(:deconstruct)
106
+ end
107
+
108
+ value.freeze
109
+ end
110
+ end
111
+ RUBY
112
+ end
113
+
114
+ def haml_helper_needed?(source, styleable:)
115
+ return true if styleable
116
+
117
+ source.match?(STATIC_CLASS_SOURCE_PATTERN) || source.match?(/^\s*%slot\b/)
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ripper"
4
+ require "syntax_tree/haml"
5
+
6
+ module Klenod
7
+ module Build
8
+ module Plugins
9
+ module HamlPlugin
10
+ def self.parse_haml(source, module_id: nil)
11
+ parser = ParserWithMetadata.new({})
12
+ parser.call(source)
13
+ rescue ::Haml::SyntaxError => error
14
+ raise ParseError.new(error, source: source, module_id: module_id)
15
+ end
16
+
17
+ class ParserWithMetadata < ::Haml::Parser
18
+ def initialize(...)
19
+ @tag_metadata_by_line = Hash.new { |hash, key| hash[key] = [] }
20
+ super
21
+ end
22
+
23
+ def call(source)
24
+ root = super
25
+ annotate_tag_nodes(root)
26
+ root
27
+ end
28
+
29
+ private
30
+
31
+ def parse_tag(text)
32
+ result = super
33
+ _, shorthand_attributes, attribute_hashes = result
34
+ @tag_metadata_by_line[@line.index + 1] << class_metadata(shorthand_attributes, attribute_hashes)
35
+ result
36
+ end
37
+
38
+ def annotate_tag_nodes(root)
39
+ queue = root.children.dup
40
+ until queue.empty?
41
+ node = queue.shift
42
+ if node.type == :tag
43
+ metadata = @tag_metadata_by_line.fetch(node.line, []).shift
44
+ node.value[:klenod_class_metadata] = metadata if metadata
45
+ end
46
+ queue.concat(node.children)
47
+ end
48
+ end
49
+
50
+ def class_metadata(shorthand_attributes, attribute_hashes)
51
+ shorthand = ::Haml::Parser.parse_class_and_id(shorthand_attributes).fetch("class", "").split
52
+ literal = []
53
+
54
+ if (new_attributes = attribute_hashes[:new])
55
+ literal.concat(Array(new_attributes.fetch(0)["class"]).flat_map { it.to_s.split })
56
+ end
57
+
58
+ if (old_attributes = attribute_hashes[:old])
59
+ literal.concat(literal_class_names_from_old_attributes(old_attributes))
60
+ end
61
+
62
+ {shorthand: shorthand, literal: literal}
63
+ end
64
+
65
+ def literal_class_names_from_old_attributes(source)
66
+ parsed = ::Haml::AttributeParser.parse(source)
67
+ return [] unless parsed&.key?("class")
68
+
69
+ value = static_string_literal_value(parsed.fetch("class"))
70
+ value ? value.split : []
71
+ end
72
+
73
+ def static_string_literal_value(source)
74
+ case Ripper.sexp(source)
75
+ in [:program, [[:string_literal, [:string_content, [:@tstring_content, String => value, _location]]]]]
76
+ value
77
+ else
78
+ nil
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end