primer_view_components 0.0.51 → 0.0.55
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 +4 -4
- data/CHANGELOG.md +159 -0
- data/app/components/primer/alpha/tab_nav.html.erb +11 -0
- data/app/components/primer/alpha/tab_nav.rb +130 -0
- data/app/components/primer/{tab_nav_component.html.erb → alpha/tab_panels.html.erb} +3 -8
- data/app/components/primer/alpha/tab_panels.rb +82 -0
- data/app/components/primer/alpha/underline_nav.html.erb +15 -0
- data/app/components/primer/alpha/underline_nav.rb +137 -0
- data/app/components/primer/{underline_nav_component.html.erb → alpha/underline_panels.html.erb} +3 -8
- data/app/components/primer/alpha/underline_panels.rb +86 -0
- data/app/components/primer/base_component.rb +1 -1
- data/app/components/primer/beta/avatar_stack.rb +9 -9
- data/app/components/primer/{breadcrumb_component.html.erb → beta/breadcrumbs.html.erb} +2 -1
- data/app/components/primer/beta/breadcrumbs.rb +61 -0
- data/app/components/primer/beta/truncate.html.erb +5 -0
- data/app/components/primer/beta/truncate.rb +110 -0
- data/app/components/primer/border_box_component.rb +27 -1
- data/app/components/primer/clipboard_copy.rb +1 -1
- data/app/components/primer/dropdown.rb +7 -7
- data/app/components/primer/icon_button.rb +1 -1
- data/app/components/primer/navigation/tab_component.rb +8 -6
- data/app/components/primer/octicon_component.rb +6 -1
- data/app/components/primer/progress_bar_component.rb +0 -3
- data/app/components/primer/tab_container_component.rb +1 -1
- data/app/lib/primer/class_name_helper.rb +14 -13
- data/app/lib/primer/fetch_or_fallback_helper.rb +2 -0
- data/app/lib/primer/octicon/cache.rb +10 -2
- data/app/lib/primer/tab_nav_helper.rb +35 -0
- data/app/lib/primer/tabbed_component_helper.rb +5 -5
- data/app/lib/primer/underline_nav_helper.rb +44 -0
- data/app/lib/primer/view_helper.rb +1 -0
- data/lib/primer/classify/cache.rb +0 -6
- data/lib/primer/classify/flex.rb +1 -1
- data/lib/primer/classify/functional_colors.rb +1 -1
- data/lib/primer/classify/utilities.rb +17 -2
- data/lib/primer/classify/utilities.yml +35 -0
- data/lib/primer/classify/validation.rb +18 -0
- data/lib/primer/classify.rb +4 -13
- data/lib/primer/view_components/constants.rb +1 -1
- data/lib/primer/view_components/linters/argument_mappers/base.rb +34 -8
- data/lib/primer/view_components/linters/argument_mappers/button.rb +5 -6
- data/lib/primer/view_components/linters/argument_mappers/clipboard_copy.rb +4 -3
- data/lib/primer/view_components/linters/argument_mappers/close_button.rb +43 -0
- data/lib/primer/view_components/linters/argument_mappers/flash.rb +32 -0
- data/lib/primer/view_components/linters/argument_mappers/helpers/erb_block.rb +48 -5
- data/lib/primer/view_components/linters/argument_mappers/label.rb +3 -4
- data/lib/primer/view_components/linters/argument_mappers/system_arguments.rb +5 -7
- data/lib/primer/view_components/linters/autocorrectable.rb +6 -4
- data/lib/primer/view_components/linters/{helpers.rb → base_linter.rb} +69 -29
- data/lib/primer/view_components/linters/button_component_migration_counter.rb +4 -3
- data/lib/primer/view_components/linters/clipboard_copy_component_migration_counter.rb +3 -4
- data/lib/primer/view_components/linters/close_button_component_migration_counter.rb +110 -3
- data/lib/primer/view_components/linters/flash_component_migration_counter.rb +18 -3
- data/lib/primer/view_components/linters/label_component_migration_counter.rb +2 -3
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/rubocop/config/default.yml +5 -0
- data/lib/rubocop/cop/primer/base_cop.rb +28 -0
- data/lib/rubocop/cop/primer/deprecated_arguments.rb +263 -0
- data/lib/rubocop/cop/primer/no_tag_memoize.rb +1 -0
- data/lib/rubocop/cop/primer/primer_octicon.rb +178 -0
- data/lib/rubocop/cop/primer/system_argument_instead_of_class.rb +4 -32
- data/lib/rubocop/cop/primer.rb +1 -2
- data/lib/tasks/coverage.rake +4 -0
- data/lib/tasks/docs.rake +10 -8
- data/lib/tasks/utilities.rake +7 -3
- data/lib/yard/docs_helper.rb +6 -3
- data/static/arguments.yml +82 -64
- data/static/classes.yml +10 -0
- data/static/constants.json +44 -30
- data/static/statuses.json +10 -6
- metadata +57 -18
- data/app/components/primer/auto_complete/auto_component.d.ts +0 -1
- data/app/components/primer/auto_complete/auto_component.js +0 -1
- data/app/components/primer/breadcrumb_component.rb +0 -57
- data/app/components/primer/tab_nav_component.rb +0 -151
- data/app/components/primer/underline_nav_component.rb +0 -187
- data/lib/primer/classify/functional_text_colors.rb +0 -64
@@ -85,7 +85,7 @@ module Primer
|
|
85
85
|
return { classes: classes } if ENV["RAILS_ENV"] == "production"
|
86
86
|
|
87
87
|
obj = {}
|
88
|
-
classes = classes.split
|
88
|
+
classes = classes.split
|
89
89
|
# Loop through all classes supplied and reject ones we find a match for
|
90
90
|
# So when we're at the end of the loop we have classes left with any non-system classes.
|
91
91
|
classes.reject! do |classname|
|
@@ -114,6 +114,21 @@ module Primer
|
|
114
114
|
obj
|
115
115
|
end
|
116
116
|
|
117
|
+
def classes_to_args(classes)
|
118
|
+
classes_to_hash(classes).map do |key, value|
|
119
|
+
val = case value
|
120
|
+
when Symbol
|
121
|
+
":#{value}"
|
122
|
+
when String
|
123
|
+
value.to_json
|
124
|
+
else
|
125
|
+
value
|
126
|
+
end
|
127
|
+
|
128
|
+
"#{key}: #{val}"
|
129
|
+
end.join(", ")
|
130
|
+
end
|
131
|
+
|
117
132
|
private
|
118
133
|
|
119
134
|
def find_selector(selector)
|
@@ -160,7 +175,7 @@ module Primer
|
|
160
175
|
unless supported_value?(key, val)
|
161
176
|
raise ArgumentError, "#{val} is not a valid value for :#{key}. Use one of #{mappings(key)}" unless ENV["RAILS_ENV"] == "production"
|
162
177
|
|
163
|
-
return ""
|
178
|
+
return "#{key.to_s.dasherize}-#{val.to_s.dasherize}"
|
164
179
|
end
|
165
180
|
|
166
181
|
nil
|
@@ -22,6 +22,39 @@
|
|
22
22
|
- anim-hover-grow
|
23
23
|
:rotate:
|
24
24
|
- anim-rotate
|
25
|
+
:color:
|
26
|
+
:text_primary:
|
27
|
+
- color-text-primary
|
28
|
+
:text_secondary:
|
29
|
+
- color-text-secondary
|
30
|
+
:text_tertiary:
|
31
|
+
- color-text-tertiary
|
32
|
+
:text_link:
|
33
|
+
- color-text-link
|
34
|
+
:text_success:
|
35
|
+
- color-text-success
|
36
|
+
:text_warning:
|
37
|
+
- color-text-warning
|
38
|
+
:text_danger:
|
39
|
+
- color-text-danger
|
40
|
+
:text_inverse:
|
41
|
+
- color-text-inverse
|
42
|
+
:text_white:
|
43
|
+
- color-text-white
|
44
|
+
:icon_primary:
|
45
|
+
- color-icon-primary
|
46
|
+
:icon_secondary:
|
47
|
+
- color-icon-secondary
|
48
|
+
:icon_tertiary:
|
49
|
+
- color-icon-tertiary
|
50
|
+
:icon_info:
|
51
|
+
- color-icon-info
|
52
|
+
:icon_danger:
|
53
|
+
- color-icon-danger
|
54
|
+
:icon_success:
|
55
|
+
- color-icon-success
|
56
|
+
:icon_warning:
|
57
|
+
- color-icon-warning
|
25
58
|
:position:
|
26
59
|
:static:
|
27
60
|
- position-static
|
@@ -1220,6 +1253,8 @@
|
|
1220
1253
|
- py-lg-12
|
1221
1254
|
- py-xl-12
|
1222
1255
|
:word_break:
|
1256
|
+
:break_word:
|
1257
|
+
- wb-break-word
|
1223
1258
|
:break_all:
|
1224
1259
|
- wb-break-all
|
1225
1260
|
:display:
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "utilities"
|
4
|
+
|
5
|
+
module Primer
|
6
|
+
class Classify
|
7
|
+
# :nodoc:
|
8
|
+
class Validation
|
9
|
+
INVALID_CLASS_NAME_PREFIXES = /bg-|color-|text-|box-shadow-|text-|box_shadow-/.freeze
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def invalid?(class_name)
|
13
|
+
class_name.start_with?(INVALID_CLASS_NAME_PREFIXES) || Primer::Classify::Utilities.supported_selector?(class_name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/primer/classify.rb
CHANGED
@@ -4,9 +4,9 @@ require_relative "classify/cache"
|
|
4
4
|
require_relative "classify/flex"
|
5
5
|
require_relative "classify/functional_background_colors"
|
6
6
|
require_relative "classify/functional_border_colors"
|
7
|
-
require_relative "classify/functional_text_colors"
|
8
7
|
require_relative "classify/grid"
|
9
8
|
require_relative "classify/utilities"
|
9
|
+
require_relative "classify/validation"
|
10
10
|
|
11
11
|
module Primer
|
12
12
|
# :nodoc:
|
@@ -14,10 +14,6 @@ module Primer
|
|
14
14
|
# Keys where we can simply translate { key: value } into ".key-value"
|
15
15
|
CONCAT_KEYS = %i[text box_shadow].freeze
|
16
16
|
|
17
|
-
INVALID_CLASS_NAME_PREFIXES =
|
18
|
-
(["bg-", "color-", "text-", "box-shadow-"] + CONCAT_KEYS.map { |k| "#{k}-" }).freeze
|
19
|
-
|
20
|
-
COLOR_KEY = :color
|
21
17
|
BG_KEY = :bg
|
22
18
|
TEXT_KEYS = %i[font_family font_style font_weight text_align text_transform].freeze
|
23
19
|
BOX_SHADOW_KEY = :box_shadow
|
@@ -90,7 +86,6 @@ module Primer
|
|
90
86
|
BORDER_KEY,
|
91
87
|
BORDER_COLOR_KEY,
|
92
88
|
BORDER_RADIUS_KEY,
|
93
|
-
COLOR_KEY,
|
94
89
|
BG_KEY,
|
95
90
|
BOX_SHADOW_KEY,
|
96
91
|
CONTAINER_KEY
|
@@ -109,7 +104,7 @@ module Primer
|
|
109
104
|
extracted_results[:style] = [
|
110
105
|
extracted_results.delete(:styles),
|
111
106
|
style
|
112
|
-
].compact.join
|
107
|
+
].compact.join.presence
|
113
108
|
|
114
109
|
extracted_results
|
115
110
|
end
|
@@ -121,8 +116,8 @@ module Primer
|
|
121
116
|
|
122
117
|
if force_system_arguments? && !ENV["PRIMER_WARNINGS_DISABLED"]
|
123
118
|
invalid_class_names =
|
124
|
-
classes.split
|
125
|
-
memo << class_name if
|
119
|
+
classes.split.each_with_object([]) do |class_name, memo|
|
120
|
+
memo << class_name if Primer::Classify::Validation.invalid?(class_name)
|
126
121
|
end
|
127
122
|
|
128
123
|
raise ArgumentError, "Use System Arguments (https://primer.style/view-components/system-arguments) instead of Primer CSS class #{'name'.pluralize(invalid_class_names.length)} #{invalid_class_names.to_sentence}. This warning will not be raised in production. Set PRIMER_WARNINGS_DISABLED=1 to disable this warning." if invalid_class_names.any?
|
@@ -178,8 +173,6 @@ module Primer
|
|
178
173
|
else
|
179
174
|
memo[:classes] << Primer::Classify::FunctionalBackgroundColors.color(val)
|
180
175
|
end
|
181
|
-
elsif key == COLOR_KEY
|
182
|
-
memo[:classes] << Primer::Classify::FunctionalTextColors.color(val)
|
183
176
|
elsif key == BORDER_KEY
|
184
177
|
border_value = if val == true
|
185
178
|
"border"
|
@@ -214,8 +207,6 @@ module Primer
|
|
214
207
|
else
|
215
208
|
"color-shadow-#{val.to_s.dasherize}"
|
216
209
|
end
|
217
|
-
else
|
218
|
-
memo[:classes] << "#{key.to_s.dasherize}#{breakpoint}-#{val.to_s.dasherize}"
|
219
210
|
end
|
220
211
|
end
|
221
212
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "primer/view_components/constants"
|
4
4
|
require "primer/classify/utilities"
|
5
|
+
require "primer/classify/validation"
|
5
6
|
require_relative "conversion_error"
|
6
7
|
require_relative "system_arguments"
|
7
8
|
require_relative "helpers/erb_block"
|
@@ -46,18 +47,37 @@ module ERBLint
|
|
46
47
|
|
47
48
|
def attribute_to_args(attribute); end
|
48
49
|
|
49
|
-
def map_classes(
|
50
|
-
|
51
|
-
args = classes_to_args(system_arguments[:classes])
|
50
|
+
def map_classes(classes_node)
|
51
|
+
erb_helper.raise_if_erb_block(classes_node)
|
52
52
|
|
53
|
-
|
53
|
+
system_arguments = system_arguments_to_args(classes_node.value)
|
54
|
+
args = classes_to_args(system_arguments[:classes]&.split || [])
|
55
|
+
|
56
|
+
invalid_classes = args[:classes].select { |class_name| Primer::Classify::Validation.invalid?(class_name) }
|
57
|
+
|
58
|
+
raise ConversionError, "Cannot convert #{'class'.pluralize(invalid_classes.size)} #{invalid_classes.join(',')}" if invalid_classes.present?
|
59
|
+
|
60
|
+
# Using splat to order the arguments in Component's args -> System Args -> custom classes
|
61
|
+
res = {
|
62
|
+
**args.except(:classes),
|
63
|
+
**system_arguments.except(:classes)
|
64
|
+
}
|
65
|
+
|
66
|
+
if args[:classes].present?
|
67
|
+
res = {
|
68
|
+
**res,
|
69
|
+
classes: args[:classes].join(" ").to_json
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
res
|
54
74
|
end
|
55
75
|
|
56
|
-
# Override this with your component's mappings
|
76
|
+
# Override this with your component's mappings, it should return a hash with the component's arguments,
|
77
|
+
# including a `classes` key that will contain all classes that the mapper couldn't handle.
|
78
|
+
# @returns { classes: Array, ... }
|
57
79
|
def classes_to_args(classes)
|
58
|
-
|
59
|
-
|
60
|
-
{}
|
80
|
+
{ classes: classes }
|
61
81
|
end
|
62
82
|
|
63
83
|
def system_arguments_to_args(classes)
|
@@ -68,6 +88,12 @@ module ERBLint
|
|
68
88
|
v.is_a?(Symbol) ? ":#{v}" : v
|
69
89
|
end
|
70
90
|
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def erb_helper
|
95
|
+
@erb_helper ||= Helpers::ErbBlock.new
|
96
|
+
end
|
71
97
|
end
|
72
98
|
end
|
73
99
|
end
|
@@ -7,8 +7,6 @@ module ERBLint
|
|
7
7
|
module ArgumentMappers
|
8
8
|
# Maps classes in a button element to arguments for the Button component.
|
9
9
|
class Button < Base
|
10
|
-
require "pry"
|
11
|
-
|
12
10
|
SCHEME_MAPPINGS = Primer::ViewComponents::Constants.get(
|
13
11
|
component: "Primer::ButtonComponent",
|
14
12
|
constant: "SCHEME_MAPPINGS",
|
@@ -35,9 +33,10 @@ module ERBLint
|
|
35
33
|
def attribute_to_args(attribute)
|
36
34
|
attr_name = attribute.name
|
37
35
|
|
38
|
-
|
36
|
+
case attr_name
|
37
|
+
when "disabled"
|
39
38
|
{ disabled: true }
|
40
|
-
|
39
|
+
when "type"
|
41
40
|
# button is the default type, so we don't need to do anything.
|
42
41
|
return {} if attribute.value == "button"
|
43
42
|
|
@@ -48,7 +47,7 @@ module ERBLint
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def classes_to_args(classes)
|
51
|
-
classes.
|
50
|
+
classes.each_with_object({ classes: [] }) do |class_name, acc|
|
52
51
|
next if class_name == "btn"
|
53
52
|
|
54
53
|
if SCHEME_MAPPINGS[class_name] && acc[:scheme].nil?
|
@@ -60,7 +59,7 @@ module ERBLint
|
|
60
59
|
elsif class_name == "BtnGroup-item"
|
61
60
|
acc[:group_item] = true
|
62
61
|
else
|
63
|
-
|
62
|
+
acc[:classes] << class_name
|
64
63
|
end
|
65
64
|
end
|
66
65
|
end
|
@@ -8,11 +8,12 @@ module ERBLint
|
|
8
8
|
# Maps attributes in the clipboard-copy element to arguments for the ClipboardCopy component.
|
9
9
|
class ClipboardCopy < Base
|
10
10
|
DEFAULT_TAG = "clipboard-copy"
|
11
|
-
ATTRIBUTES = %w[value].freeze
|
11
|
+
ATTRIBUTES = %w[role tabindex for value id style].freeze
|
12
12
|
|
13
13
|
def attribute_to_args(attribute)
|
14
|
-
|
15
|
-
|
14
|
+
attr_name = attribute.name
|
15
|
+
|
16
|
+
{ attr_name.to_sym => erb_helper.convert(attribute) }
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module ERBLint
|
6
|
+
module Linters
|
7
|
+
module ArgumentMappers
|
8
|
+
# Maps classes in a close-button element to arguments for the CloseButton component.
|
9
|
+
class CloseButton < Base
|
10
|
+
ATTRIBUTES = %w[type].freeze
|
11
|
+
|
12
|
+
TYPE_OPTIONS = Primer::ViewComponents::Constants.get(
|
13
|
+
component: "Primer::CloseButton",
|
14
|
+
constant: "TYPE_OPTIONS"
|
15
|
+
).freeze
|
16
|
+
|
17
|
+
DEFAULT_TYPE = Primer::ViewComponents::Constants.get(
|
18
|
+
component: "Primer::CloseButton",
|
19
|
+
constant: "DEFAULT_TYPE"
|
20
|
+
).freeze
|
21
|
+
|
22
|
+
DEFAULT_CLASS = "close-button"
|
23
|
+
|
24
|
+
def attribute_to_args(attribute)
|
25
|
+
# button is the default type, so we don't need to do anything.
|
26
|
+
return {} if attribute.value == DEFAULT_TYPE
|
27
|
+
|
28
|
+
raise ConversionError, "CloseButton component does not support type \"#{attribute.value}\"" unless TYPE_OPTIONS.include?(attribute.value)
|
29
|
+
|
30
|
+
{ type: ":#{attribute.value}" }
|
31
|
+
end
|
32
|
+
|
33
|
+
def classes_to_args(classes)
|
34
|
+
classes.each_with_object({ classes: [] }) do |class_name, acc|
|
35
|
+
next if class_name == DEFAULT_CLASS
|
36
|
+
|
37
|
+
acc[:classes] << class_name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module ERBLint
|
6
|
+
module Linters
|
7
|
+
module ArgumentMappers
|
8
|
+
# Maps classes in a flash element to arguments for the Flash component.
|
9
|
+
class Flash < Base
|
10
|
+
SCHEME_MAPPINGS = Primer::ViewComponents::Constants.get(
|
11
|
+
component: "Primer::FlashComponent",
|
12
|
+
constant: "SCHEME_MAPPINGS",
|
13
|
+
symbolize: true
|
14
|
+
).freeze
|
15
|
+
|
16
|
+
def classes_to_args(classes)
|
17
|
+
classes.each_with_object({ classes: [] }) do |class_name, acc|
|
18
|
+
next if class_name == "flash"
|
19
|
+
|
20
|
+
if SCHEME_MAPPINGS[class_name] && acc[:scheme].nil?
|
21
|
+
acc[:scheme] = SCHEME_MAPPINGS[class_name]
|
22
|
+
elsif class_name == "flash-full"
|
23
|
+
acc[:full] = true
|
24
|
+
else
|
25
|
+
acc[:classes] << class_name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -8,15 +8,58 @@ module ERBLint
|
|
8
8
|
module Helpers
|
9
9
|
# provides helpers to identify and deal with ERB blocks.
|
10
10
|
class ErbBlock
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
INTERPOLATION_REGEX = /^<%=(?<rb>.*)%>$/.freeze
|
12
|
+
|
13
|
+
def raise_if_erb_block(attribute)
|
14
|
+
raise_error(attribute) if any?(attribute)
|
15
|
+
end
|
16
|
+
|
17
|
+
def convert(attribute)
|
18
|
+
raise_error(attribute) unless interpolation?(attribute)
|
19
|
+
|
20
|
+
if any?(attribute)
|
21
|
+
convert_interpolation(attribute)
|
22
|
+
else
|
23
|
+
attribute.value.to_json
|
14
24
|
end
|
25
|
+
end
|
15
26
|
|
16
|
-
|
17
|
-
|
27
|
+
private
|
28
|
+
|
29
|
+
def interpolation?(attribute)
|
30
|
+
erb_blocks(attribute).all? do |erb|
|
31
|
+
# If the blocks does not have an indicator, it's not an interpolation.
|
32
|
+
erb.children.to_a.compact.any? { |node| node.type == :indicator }
|
18
33
|
end
|
19
34
|
end
|
35
|
+
|
36
|
+
def raise_error(attribute)
|
37
|
+
raise ERBLint::Linters::ArgumentMappers::ConversionError, "Cannot convert attribute \"#{attribute.name}\" because its value contains an erb block"
|
38
|
+
end
|
39
|
+
|
40
|
+
def any?(attribute)
|
41
|
+
erb_blocks(attribute).any?
|
42
|
+
end
|
43
|
+
|
44
|
+
def basic?(attribute)
|
45
|
+
return false if erb_blocks(attribute).size != 1
|
46
|
+
|
47
|
+
attribute.value.match?(INTERPOLATION_REGEX)
|
48
|
+
end
|
49
|
+
|
50
|
+
def erb_blocks(attribute)
|
51
|
+
(attribute.value_node&.children || []).select { |n| n.try(:type) == :erb }
|
52
|
+
end
|
53
|
+
|
54
|
+
def convert_interpolation(attribute)
|
55
|
+
if basic?(attribute)
|
56
|
+
m = attribute.value.match(INTERPOLATION_REGEX)
|
57
|
+
return m[:rb].strip
|
58
|
+
end
|
59
|
+
|
60
|
+
# we use `source` instead of `value` because it does not convert encoded HTML entities.
|
61
|
+
attribute.value_node.loc.source.gsub("<%=", '#{').gsub("%>", "}")
|
62
|
+
end
|
20
63
|
end
|
21
64
|
end
|
22
65
|
end
|