primer_view_components 0.0.46 → 0.0.50

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +144 -0
  3. data/app/components/primer/base_component.rb +2 -2
  4. data/app/components/primer/beta/auto_complete.rb +159 -0
  5. data/app/components/primer/beta/auto_complete/auto_complete.d.ts +1 -0
  6. data/app/components/primer/{auto_complete → beta/auto_complete}/auto_complete.html.erb +0 -0
  7. data/app/components/primer/beta/auto_complete/auto_complete.js +1 -0
  8. data/app/components/primer/{auto_complete → beta/auto_complete}/auto_complete.ts +0 -0
  9. data/app/components/primer/beta/auto_complete/item.rb +44 -0
  10. data/app/components/primer/beta/avatar.rb +77 -0
  11. data/app/components/primer/{avatar_stack_component.html.erb → beta/avatar_stack.html.erb} +0 -0
  12. data/app/components/primer/beta/avatar_stack.rb +92 -0
  13. data/app/components/primer/clipboard_copy.html.erb +2 -2
  14. data/app/components/primer/component.rb +5 -1
  15. data/app/components/primer/details_component.rb +7 -7
  16. data/app/components/primer/image_crop.html.erb +4 -4
  17. data/app/components/primer/label_component.rb +13 -12
  18. data/app/components/primer/markdown.rb +9 -9
  19. data/app/components/primer/navigation/tab_component.rb +30 -2
  20. data/app/components/primer/popover_component.rb +6 -3
  21. data/app/components/primer/primer.d.ts +1 -1
  22. data/app/components/primer/primer.js +1 -1
  23. data/app/components/primer/primer.ts +1 -1
  24. data/app/components/primer/tab_nav_component.rb +4 -3
  25. data/app/components/primer/timeline_item_component.rb +2 -2
  26. data/app/components/primer/truncate.rb +6 -1
  27. data/app/components/primer/underline_nav_component.rb +4 -3
  28. data/app/lib/primer/octicon/cache.rb +1 -1
  29. data/lib/primer/classify.rb +4 -18
  30. data/lib/primer/classify/cache.rb +0 -5
  31. data/lib/primer/classify/utilities.rb +54 -22
  32. data/lib/primer/classify/utilities.yml +16 -0
  33. data/lib/primer/view_components.rb +34 -6
  34. data/lib/primer/view_components/constants.rb +55 -0
  35. data/lib/primer/view_components/linters/argument_mappers/base.rb +74 -0
  36. data/lib/primer/view_components/linters/argument_mappers/button.rb +32 -44
  37. data/lib/primer/view_components/linters/argument_mappers/clipboard_copy.rb +20 -0
  38. data/lib/primer/view_components/linters/argument_mappers/helpers/erb_block.rb +24 -0
  39. data/lib/primer/view_components/linters/argument_mappers/label.rb +50 -0
  40. data/lib/primer/view_components/linters/argument_mappers/system_arguments.rb +4 -1
  41. data/lib/primer/view_components/linters/autocorrectable.rb +30 -0
  42. data/lib/primer/view_components/linters/button_component_migration_counter.rb +9 -23
  43. data/lib/primer/view_components/linters/clipboard_copy_component_migration_counter.rb +21 -0
  44. data/lib/primer/view_components/linters/close_button_component_migration_counter.rb +16 -0
  45. data/lib/primer/view_components/linters/helpers.rb +56 -38
  46. data/lib/primer/view_components/linters/label_component_migration_counter.rb +25 -0
  47. data/lib/primer/view_components/statuses.rb +14 -0
  48. data/lib/primer/view_components/version.rb +1 -1
  49. data/lib/rubocop/config/default.yml +12 -0
  50. data/lib/rubocop/cop/primer.rb +4 -0
  51. data/lib/rubocop/cop/primer/no_tag_memoize.rb +42 -0
  52. data/lib/rubocop/cop/primer/system_argument_instead_of_class.rb +75 -0
  53. data/lib/tasks/constants.rake +12 -0
  54. data/lib/tasks/docs.rake +87 -32
  55. data/lib/tasks/utilities.rake +4 -10
  56. data/lib/yard/docs_helper.rb +12 -3
  57. data/static/arguments.yml +973 -0
  58. data/static/assets/view-components.svg +18 -0
  59. data/static/classes.yml +174 -0
  60. data/static/constants.json +628 -0
  61. data/static/statuses.json +5 -5
  62. metadata +34 -13
  63. data/app/components/primer/auto_complete.rb +0 -157
  64. data/app/components/primer/auto_complete/item.rb +0 -42
  65. data/app/components/primer/avatar_component.rb +0 -75
  66. data/app/components/primer/avatar_stack_component.rb +0 -90
@@ -19,6 +19,7 @@ module Primer
19
19
  # Use the tabs to list navigation items. When `with_panel` is set on the parent, a button is rendered for panel navigation. Otherwise,
20
20
  # an anchor tag is rendered for page navigation. For more information, refer to <%= link_to_component(Primer::Navigation::TabComponent) %>.
21
21
  #
22
+ # @param panel_id [String] Only applies if `with_panel` is `true`. Unique id of panel.
22
23
  # @param selected [Boolean] Whether the tab is selected.
23
24
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
24
25
  renders_many :tabs, lambda { |selected: false, **system_arguments|
@@ -38,7 +39,7 @@ module Primer
38
39
 
39
40
  # Use actions for a call to action.
40
41
  #
41
- # @param tag [String] (Primer::UnderlineNavComponent::ACTIONS_TAG_DEFAULT) <%= one_of(Primer::UnderlineNavComponent::ACTIONS_TAG_OPTIONS) %>
42
+ # @param tag [Symbol] (Primer::UnderlineNavComponent::ACTIONS_TAG_DEFAULT) <%= one_of(Primer::UnderlineNavComponent::ACTIONS_TAG_OPTIONS) %>
42
43
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
43
44
  renders_one :actions, lambda { |tag: ACTIONS_TAG_DEFAULT, **system_arguments|
44
45
  system_arguments[:tag] = fetch_or_fallback(ACTIONS_TAG_OPTIONS, tag, ACTIONS_TAG_DEFAULT)
@@ -104,13 +105,13 @@ module Primer
104
105
  #
105
106
  # @example With panels
106
107
  # <%= render(Primer::UnderlineNavComponent.new(label: "With panels", with_panel: true)) do |component| %>
107
- # <% component.tab(selected: true) do |t| %>
108
+ # <% component.tab(selected: true, id: "tab-1", panel_id: "panel-1") do |t| %>
108
109
  # <% t.text { "Item 1" } %>
109
110
  # <% t.panel do %>
110
111
  # Panel 1
111
112
  # <% end %>
112
113
  # <% end %>
113
- # <% component.tab do |t| %>
114
+ # <% component.tab(id: "tab-2", panel_id: "panel-2") do |t| %>
114
115
  # <% t.text { "Item 2" } %>
115
116
  # <% t.panel do %>
116
117
  # Panel 2
@@ -6,7 +6,7 @@ module Primer
6
6
  class Cache
7
7
  LOOKUP = {} # rubocop:disable Style/MutableConstant
8
8
  # Preload the top 20 used icons.
9
- PRELOADED_ICONS = [:alert, :check, :"chevron-down", :clippy, :clock, :"dot-fill", :info, :"kebab-horizontal", :link, :lock, :mail, :pencil, :plus, :question, :repo, :search, :"shield-lock", :star, :trash, :x].freeze
9
+ PRELOADED_ICONS = [:alert, :check, :"chevron-down", :paste, :clock, :"dot-fill", :info, :"kebab-horizontal", :link, :lock, :mail, :pencil, :plus, :question, :repo, :search, :"shield-lock", :star, :trash, :x].freeze
10
10
 
11
11
  class << self
12
12
  def get_key(symbol:, size:, width: nil, height: nil)
@@ -11,16 +11,6 @@ require_relative "classify/utilities"
11
11
  module Primer
12
12
  # :nodoc:
13
13
  class Classify
14
- # Load the utilities.yml file.
15
- # Disabling because we want to load symbols, strings, and integers from the .yml file
16
- # rubocop:disable Security/YAMLLoad
17
- UTILITIES = YAML.load(
18
- File.read(
19
- File.join(File.dirname(__FILE__), "./classify/utilities.yml")
20
- )
21
- ).freeze
22
- # rubocop:enable Security/YAMLLoad
23
-
24
14
  # Keys where we can simply translate { key: value } into ".key-value"
25
15
  CONCAT_KEYS = %i[text box_shadow].freeze
26
16
 
@@ -90,7 +80,7 @@ module Primer
90
80
  BORDER_RADIUS_KEY = :border_radius
91
81
  TYPOGRAPHY_KEYS = [:font_size].freeze
92
82
  VALID_KEYS = (
93
- UTILITIES.keys +
83
+ Primer::Classify::Utilities::UTILITIES.keys +
94
84
  CONCAT_KEYS +
95
85
  BOOLEAN_MAPPINGS.keys +
96
86
  BORDER_MARGIN_KEYS +
@@ -180,7 +170,9 @@ module Primer
180
170
  def extract_value(memo, key, val, breakpoint)
181
171
  return if val.nil? || val == ""
182
172
 
183
- if Primer::Classify::Utilities.supported_key?(key)
173
+ if (key == WIDTH_KEY || key == HEIGHT_KEY) && !val.is_a?(Symbol)
174
+ memo[key] = val
175
+ elsif Primer::Classify::Utilities.supported_key?(key)
184
176
  memo[:classes] << Primer::Classify::Utilities.classname(key, val, breakpoint)
185
177
  elsif BOOLEAN_MAPPINGS.key?(key)
186
178
  BOOLEAN_MAPPINGS[key][:mappings].each do |m|
@@ -212,12 +204,6 @@ module Primer
212
204
  memo[:classes] << Primer::Classify::Flex.classes(key, val, breakpoint)
213
205
  elsif Primer::Classify::Grid::KEYS.include?(key)
214
206
  memo[:classes] << Primer::Classify::Grid.classes(key, val, breakpoint)
215
- elsif key == WIDTH_KEY || key == HEIGHT_KEY
216
- if val == :fit
217
- memo[:classes] << "#{key}-#{val}"
218
- else
219
- memo[key] = val
220
- end
221
207
  elsif TEXT_KEYS.include?(key)
222
208
  memo[:classes] << "text-#{val.to_s.dasherize}"
223
209
  elsif TYPOGRAPHY_KEYS.include?(key)
@@ -95,11 +95,6 @@ module Primer
95
95
  values: Primer::Classify::Flex::ALIGN_SELF_VALUES
96
96
  )
97
97
 
98
- preload(
99
- keys: [Primer::Classify::WIDTH_KEY, Primer::Classify::HEIGHT_KEY],
100
- values: [:fit]
101
- )
102
-
103
98
  preload(
104
99
  keys: Primer::Classify::BOX_SHADOW_KEY,
105
100
  values: [true, :small, :medium, :large, :extra_large, :none]
@@ -1,17 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "yaml"
4
+
3
5
  # :nodoc:
4
6
  module Primer
5
7
  class Classify
6
8
  # Handler for PrimerCSS utility classes loaded from utilities.rake
7
9
  class Utilities
10
+ # Load the utilities.yml file.
11
+ # Disabling because we want to load symbols, strings, and integers from the .yml file
12
+ # rubocop:disable Security/YAMLLoad
13
+ UTILITIES = YAML.load(
14
+ File.read(
15
+ File.join(File.dirname(__FILE__), "./utilities.yml")
16
+ )
17
+ ).freeze
18
+ # rubocop:enable Security/YAMLLoad
19
+ BREAKPOINTS = ["", "-sm", "-md", "-lg", "-xl"].freeze
20
+
21
+ # Replacements for some classnames that end up being a different argument key
22
+ REPLACEMENT_KEYS = {
23
+ "^anim" => "animation",
24
+ "^v-align" => "vertical_align",
25
+ "^d" => "display",
26
+ "^wb" => "word_break",
27
+ "^v" => "visibility"
28
+ }.freeze
29
+
8
30
  class << self
9
31
  def classname(key, val, breakpoint = "")
10
32
  if (valid = validate(key, val, breakpoint))
11
33
  valid
12
34
  else
13
35
  # Get selector
14
- Primer::Classify::UTILITIES[key][val][Primer::Classify::BREAKPOINTS.index(breakpoint)]
36
+ UTILITIES[key][val][BREAKPOINTS.index(breakpoint)]
15
37
  end
16
38
  end
17
39
 
@@ -19,14 +41,14 @@ module Primer
19
41
  #
20
42
  # returns Boolean
21
43
  def supported_key?(key)
22
- Primer::Classify::UTILITIES[key].present?
44
+ UTILITIES[key].present?
23
45
  end
24
46
 
25
47
  # Does the Utilitiy class support the given key and value
26
48
  #
27
49
  # returns Boolean
28
50
  def supported_value?(key, val)
29
- supported_key?(key) && Primer::Classify::UTILITIES[key][val].present?
51
+ supported_key?(key) && UTILITIES[key][val].present?
30
52
  end
31
53
 
32
54
  # Does the given selector exist in the utilities file
@@ -34,7 +56,7 @@ module Primer
34
56
  # returns Boolean
35
57
  def supported_selector?(selector)
36
58
  # This method is too slow to run in production
37
- return false if Rails.env.production?
59
+ return false if ENV["RAILS_ENV"] == "production"
38
60
 
39
61
  find_selector(selector).present?
40
62
  end
@@ -43,7 +65,7 @@ module Primer
43
65
  #
44
66
  # returns Boolean
45
67
  def responsive?(key, val)
46
- supported_value?(key, val) && Primer::Classify::UTILITIES[key][val].count > 1
68
+ supported_value?(key, val) && UTILITIES[key][val].count > 1
47
69
  end
48
70
 
49
71
  # Get the options for the given key
@@ -52,13 +74,13 @@ module Primer
52
74
  def mappings(key)
53
75
  return unless supported_key?(key)
54
76
 
55
- Primer::Classify::UTILITIES[key].keys
77
+ UTILITIES[key].keys
56
78
  end
57
79
 
58
80
  # Extract hash from classes ie. "mr-1 mb-2 foo" => { mr: 1, mb: 2, classes: "foo" }
59
81
  def classes_to_hash(classes)
60
82
  # This method is too slow to run in production
61
- return { classes: classes } if Rails.env.production?
83
+ return { classes: classes } if ENV["RAILS_ENV"] == "production"
62
84
 
63
85
  obj = {}
64
86
  classes = classes.split(" ")
@@ -93,38 +115,48 @@ module Primer
93
115
  private
94
116
 
95
117
  def find_selector(selector)
96
- # Search each key/value_hash pair, eg. key `:mr` and value_hash `{ 0 => [ "mr-0", "mr-sm-0", "mr-md-0", "mr-lg-0", "mr-xl-0" ] }`
97
- Primer::Classify::UTILITIES.each do |key, value_hash|
98
- # Each value hash will also contain an array of classnames for breakpoints
99
- # Key argument `0`, classes `[ "mr-0", "mr-sm-0", "mr-md-0", "mr-lg-0", "mr-xl-0" ]`
100
- value_hash.each do |key_argument, classnames|
101
- # Skip each value hash until we get one with the selector
102
- next unless classnames.include?(selector)
103
-
104
- # Return [:mr, 0, 1]
105
- # has index of classname, so we can match it up with responsvie array `mr: [nil, 0]`
106
- return [key, key_argument, classnames.index(selector)]
107
- end
118
+ key = infer_selector_key(selector)
119
+ value_hash = UTILITIES[key]
120
+
121
+ return nil if value_hash.blank?
122
+
123
+ # Each value hash will also contain an array of classnames for breakpoints
124
+ # Key argument `0`, classes `[ "mr-0", "mr-sm-0", "mr-md-0", "mr-lg-0", "mr-xl-0" ]`
125
+ value_hash.each do |key_argument, classnames|
126
+ # Skip each value hash until we get one with the selector
127
+ next unless classnames.include?(selector)
128
+
129
+ # Return [:mr, 0, 1]
130
+ # has index of classname, so we can match it up with responsvie array `mr: [nil, 0]`
131
+ return [key, key_argument, classnames.index(selector)]
108
132
  end
109
133
 
110
134
  nil
111
135
  end
112
136
 
137
+ def infer_selector_key(selector)
138
+ REPLACEMENT_KEYS.each do |k, v|
139
+ return v.to_sym if selector.match?(Regexp.new(k))
140
+ end
141
+
142
+ selector.split("-").first.to_sym
143
+ end
144
+
113
145
  def validate(key, val, breakpoint)
114
146
  unless supported_key?(key)
115
- raise ArgumentError, "#{key} is not a valid Primer utility key" unless Rails.env.production?
147
+ raise ArgumentError, "#{key} is not a valid Primer utility key" unless ENV["RAILS_ENV"] == "production"
116
148
 
117
149
  return ""
118
150
  end
119
151
 
120
152
  unless breakpoint.empty? || responsive?(key, val)
121
- raise ArgumentError, "#{key} does not support responsive values" unless Rails.env.production?
153
+ raise ArgumentError, "#{key} does not support responsive values" unless ENV["RAILS_ENV"] == "production"
122
154
 
123
155
  return ""
124
156
  end
125
157
 
126
158
  unless supported_value?(key, val)
127
- raise ArgumentError, "#{val} is not a valid value for :#{key}. Use one of #{mappings(key)}" unless Rails.env.production?
159
+ raise ArgumentError, "#{val} is not a valid value for :#{key}. Use one of #{mappings(key)}" unless ENV["RAILS_ENV"] == "production"
128
160
 
129
161
  return ""
130
162
  end
@@ -85,6 +85,22 @@
85
85
  - float-md-none
86
86
  - float-lg-none
87
87
  - float-xl-none
88
+ :width:
89
+ :fit:
90
+ - width-fit
91
+ :full:
92
+ - width-full
93
+ :auto:
94
+ - width-auto
95
+ - width-sm-auto
96
+ - width-md-auto
97
+ - width-lg-auto
98
+ - width-xl-auto
99
+ :height:
100
+ :fit:
101
+ - height-fit
102
+ :full:
103
+ - height-full
88
104
  :m:
89
105
  0:
90
106
  - m-0
@@ -7,22 +7,21 @@ require "primer/view_components/engine"
7
7
  module Primer
8
8
  # :nodoc:
9
9
  module ViewComponents
10
- DEFAULT_STATUSES_PATH = File.expand_path("static")
10
+ DEFAULT_STATIC_PATH = File.expand_path("static")
11
11
  DEFAULT_STATUS_FILE_NAME = "statuses.json"
12
+ DEFAULT_CONSTANTS_FILE_NAME = "constants.json"
12
13
 
13
14
  # generate_statuses returns a hash mapping component name to
14
15
  # the component's status sorted alphabetically by the component name.
15
16
  def self.generate_statuses
16
- statuses = Primer::Component.descendants.each_with_object({}) do |component, mem|
17
+ Primer::Component.descendants.sort_by(&:name).each_with_object({}) do |component, mem|
17
18
  mem[component.to_s] = component.status.to_s
18
19
  end
19
-
20
- statuses.sort_by { |k, _v| k }.to_h
21
20
  end
22
21
 
23
22
  # dump_statuses generates the status hash and then serializes
24
23
  # it as json at the given path
25
- def self.dump_statuses(path: DEFAULT_STATUSES_PATH)
24
+ def self.dump_statuses(path: DEFAULT_STATIC_PATH)
26
25
  require "json"
27
26
 
28
27
  statuses = generate_statuses
@@ -35,8 +34,37 @@ module Primer
35
34
 
36
35
  # read_statuses returns a JSON string matching the output of
37
36
  # generate_statuses
38
- def self.read_statuses(path: DEFAULT_STATUSES_PATH)
37
+ def self.read_statuses(path: DEFAULT_STATIC_PATH)
39
38
  File.read(File.join(path, DEFAULT_STATUS_FILE_NAME))
40
39
  end
40
+
41
+ # generate_constants returns a hash mapping component name to
42
+ # all of its constants.
43
+ def self.generate_constants
44
+ Primer::Component.descendants.sort_by(&:name).each_with_object({}) do |component, mem|
45
+ mem[component.to_s] = component.constants(false).sort.each_with_object({}) do |constant, h|
46
+ h[constant] = component.const_get(constant)
47
+ end
48
+ end
49
+ end
50
+
51
+ # dump_constants generates the constants hash and then serializes
52
+ # it as json at the given path
53
+ def self.dump_constants(path: DEFAULT_STATIC_PATH)
54
+ require "json"
55
+
56
+ constants = generate_constants
57
+
58
+ File.open(File.join(path, DEFAULT_CONSTANTS_FILE_NAME), "w") do |f|
59
+ f.write(JSON.pretty_generate(constants))
60
+ f.write($INPUT_RECORD_SEPARATOR)
61
+ end
62
+ end
63
+
64
+ # read_constants returns a JSON string matching the output of
65
+ # generate_constants
66
+ def self.read_constants(path: DEFAULT_STATIC_PATH)
67
+ File.read(File.join(path, DEFAULT_CONSTANTS_FILE_NAME))
68
+ end
41
69
  end
42
70
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Primer
6
+ module ViewComponents
7
+ # A module for constants that are used in the view components.
8
+ class Constants
9
+ CONSTANTS = JSON.parse(
10
+ File.read(
11
+ File.join(File.dirname(__FILE__), "../../../static/constants.json")
12
+ )
13
+ ).freeze
14
+
15
+ class << self
16
+ def get(component:, constant:, invert: true, symbolize: false)
17
+ values = CONSTANTS.dig(component, constant)
18
+
19
+ case values
20
+ when Hash
21
+ format_hash(values, invert, symbolize)
22
+ when Array
23
+ format_array(values, symbolize)
24
+ else
25
+ values
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def format_hash(values, invert, symbolize)
32
+ val = values.invert if invert
33
+ # remove defaults
34
+ val = val.except("", nil)
35
+
36
+ return val.transform_values { |v| symbolize_value(v) } if symbolize
37
+
38
+ val
39
+ end
40
+
41
+ def format_array(values, symbolize)
42
+ val = values.select(&:present?)
43
+
44
+ return val.map { |v| symbolize_value(v) } if symbolize
45
+
46
+ val
47
+ end
48
+
49
+ def symbolize_value(value)
50
+ ":#{value}"
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "primer/view_components/constants"
4
+ require "primer/classify/utilities"
5
+ require_relative "conversion_error"
6
+ require_relative "system_arguments"
7
+ require_relative "helpers/erb_block"
8
+
9
+ module ERBLint
10
+ module Linters
11
+ module ArgumentMappers
12
+ # Provides the base interface to implement an `ArgumentMapper`.
13
+ # Override attribute_to_args in a child class to customize its mapping behavior.
14
+ class Base
15
+ DEFAULT_TAG = nil
16
+ ATTRIBUTES = [].freeze
17
+
18
+ def initialize(tag)
19
+ @tag = tag
20
+ end
21
+
22
+ def to_s
23
+ to_args.map { |k, v| "#{k}: #{v}" }.join(", ")
24
+ end
25
+
26
+ def to_args
27
+ args = {}
28
+
29
+ args[:tag] = ":#{@tag.name}" unless self.class::DEFAULT_TAG.nil? || @tag.name == self.class::DEFAULT_TAG
30
+
31
+ @tag.attributes.each do |attribute|
32
+ attr_name = attribute.name
33
+
34
+ if self.class::ATTRIBUTES.include?(attr_name)
35
+ args.merge!(attribute_to_args(attribute))
36
+ elsif attr_name == "class"
37
+ args.merge!(map_classes(attribute))
38
+ else
39
+ # Assume the attribute is a system argument.
40
+ args.merge!(SystemArguments.new(attribute).to_args)
41
+ end
42
+ end
43
+
44
+ args
45
+ end
46
+
47
+ def attribute_to_args(attribute); end
48
+
49
+ def map_classes(classes)
50
+ system_arguments = system_arguments_to_args(classes.value)
51
+ args = classes_to_args(system_arguments[:classes])
52
+
53
+ args.merge(system_arguments.except(:classes))
54
+ end
55
+
56
+ # Override this with your component's mappings
57
+ def classes_to_args(classes)
58
+ raise ConversionError, "Cannot convert classes `#{classes}`" if classes.present?
59
+
60
+ {}
61
+ end
62
+
63
+ def system_arguments_to_args(classes)
64
+ system_arguments = Primer::Classify::Utilities.classes_to_hash(classes)
65
+
66
+ # need to transform symbols to strings with leading `:`
67
+ system_arguments.transform_values do |v|
68
+ v.is_a?(Symbol) ? ":#{v}" : v
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end