herb 0.9.5-arm-linux-gnu → 0.9.7-arm-linux-gnu
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/ext/herb/extension.c +8 -0
- data/ext/herb/extension_helpers.c +1 -0
- data/lib/herb/3.0/herb.so +0 -0
- data/lib/herb/3.1/herb.so +0 -0
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/4.0/herb.so +0 -0
- data/lib/herb/action_view/helper_registry.rb +8107 -0
- data/lib/herb/parser_options.rb +7 -2
- data/lib/herb/project.rb +2 -5
- data/lib/herb/version.rb +1 -1
- data/sig/herb/action_view/helper_registry.rbs +1144 -0
- data/sig/herb/parser_options.rbs +6 -2
- data/src/analyze/action_view/generated_handlers.c +355 -0
- data/src/analyze/action_view/generated_handlers.h +16 -0
- data/src/analyze/action_view/helper_registry.c +7244 -0
- data/src/analyze/action_view/image_tag.c +4 -31
- data/src/analyze/action_view/javascript_include_tag.c +1 -42
- data/src/analyze/action_view/javascript_tag.c +0 -52
- data/src/analyze/action_view/registry.c +2 -2
- data/src/analyze/action_view/tag_helpers.c +8 -120
- data/src/analyze/action_view/turbo_frame_tag.c +1 -36
- data/src/analyze/analyze.c +7 -0
- data/src/analyze/postfix_conditionals.c +326 -0
- data/src/analyze/ternary_conditionals.c +265 -0
- data/src/include/analyze/action_view/helper_registry.h +325 -0
- data/src/include/analyze/action_view/tag_helpers.h +0 -1
- data/src/include/analyze/postfix_conditionals.h +9 -0
- data/src/include/analyze/ternary_conditionals.h +15 -0
- data/src/include/parser/parser.h +1 -0
- data/src/include/version.h +1 -1
- data/src/parser.c +1 -0
- data/templates/java/org/herb/ast/HelperRegistry.java.erb +258 -0
- data/templates/javascript/packages/core/src/action-view-helpers.ts.erb +171 -0
- data/templates/javascript/packages/core/src/nodes.ts.erb +5 -1
- data/templates/lib/herb/action_view/helper_registry.rb.erb +288 -0
- data/templates/rust/src/action_view_helpers.rs.erb +154 -0
- data/templates/src/analyze/action_view/generated_handlers.c.erb +230 -0
- data/templates/src/analyze/action_view/generated_handlers.h.erb +12 -0
- data/templates/src/analyze/action_view/helper_registry.c.erb +114 -0
- data/templates/src/include/analyze/action_view/helper_registry.h.erb +82 -0
- data/templates/template.rb +338 -1
- metadata +19 -3
- data/src/analyze/action_view/content_tag.c +0 -78
- data/src/analyze/action_view/tag.c +0 -87
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
export enum HelperType {
|
|
2
|
+
<%- helpers.each do |helper| -%>
|
|
3
|
+
<%= helper.camel_case_name %> = "<%= helper.name %>",
|
|
4
|
+
<%- end -%>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type HelperDetectStyle = "call_name" | "receiver_call"
|
|
8
|
+
export type HelperOutput = "html" | "text" | "url" | "boolean" | "void" | "object"
|
|
9
|
+
|
|
10
|
+
export interface HelperArgument {
|
|
11
|
+
readonly name: string
|
|
12
|
+
readonly position: number
|
|
13
|
+
readonly type: string
|
|
14
|
+
readonly optional: boolean
|
|
15
|
+
readonly default: string | null
|
|
16
|
+
readonly splat: boolean
|
|
17
|
+
readonly description: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface HelperOption {
|
|
21
|
+
readonly name: string
|
|
22
|
+
readonly type: string
|
|
23
|
+
readonly mapsTo: string | null
|
|
24
|
+
readonly description: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface HelperImplicitAttribute {
|
|
28
|
+
readonly name: string
|
|
29
|
+
readonly source: string
|
|
30
|
+
readonly sourceWithBlock: string | null
|
|
31
|
+
readonly wrapper: string
|
|
32
|
+
readonly skipWrappingFor: string[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface HelperEntry {
|
|
36
|
+
readonly name: string
|
|
37
|
+
readonly type: HelperType
|
|
38
|
+
readonly source: string
|
|
39
|
+
readonly gem: string
|
|
40
|
+
readonly output: HelperOutput
|
|
41
|
+
readonly visibility: "public" | "internal"
|
|
42
|
+
readonly tagName: string | null
|
|
43
|
+
readonly isVoid: boolean
|
|
44
|
+
readonly supportsBlock: boolean
|
|
45
|
+
readonly preferredForTag: boolean
|
|
46
|
+
readonly supported: boolean
|
|
47
|
+
readonly detectStyle: HelperDetectStyle
|
|
48
|
+
readonly description: string
|
|
49
|
+
readonly signature: string
|
|
50
|
+
readonly documentationURL: string
|
|
51
|
+
readonly implicitAttribute: HelperImplicitAttribute | null
|
|
52
|
+
readonly arguments: HelperArgument[]
|
|
53
|
+
readonly options: HelperOption[]
|
|
54
|
+
readonly specialBehaviors: string[]
|
|
55
|
+
readonly aliases: string[]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
<%- helpers.each do |helper| -%>
|
|
59
|
+
const <%= helper.lower_camel_case_name %>Entry: HelperEntry = {
|
|
60
|
+
name: "<%= helper.name %>",
|
|
61
|
+
type: HelperType.<%= helper.camel_case_name %>,
|
|
62
|
+
source: "<%= helper.source %>",
|
|
63
|
+
gem: "<%= helper.gem %>",
|
|
64
|
+
output: "<%= helper.output %>",
|
|
65
|
+
visibility: "<%= helper.visibility %>",
|
|
66
|
+
tagName: <%= helper.tag_name ? "\"#{helper.tag_name}\"" : "null" %>,
|
|
67
|
+
isVoid: <%= helper.void? %>,
|
|
68
|
+
supportsBlock: <%= helper.supports_block %>,
|
|
69
|
+
preferredForTag: <%= helper.preferred_for_tag %>,
|
|
70
|
+
supported: <%= helper.supported %>,
|
|
71
|
+
detectStyle: "<%= helper.detect_style || "call_name" %>",
|
|
72
|
+
description: "<%= helper.escaped_description %>",
|
|
73
|
+
signature: "<%= helper.escaped_signature %>",
|
|
74
|
+
documentationURL: "<%= helper.documentation_url %>",
|
|
75
|
+
<%- if helper.implicit_attribute? -%>
|
|
76
|
+
implicitAttribute: {
|
|
77
|
+
name: "<%= helper.implicit_attribute.name %>",
|
|
78
|
+
source: "<%= helper.implicit_attribute.source %>",
|
|
79
|
+
sourceWithBlock: <%= helper.implicit_attribute.source_with_block ? "\"#{helper.implicit_attribute.source_with_block}\"" : "null" %>,
|
|
80
|
+
wrapper: "<%= helper.implicit_attribute.wrapper %>",
|
|
81
|
+
skipWrappingFor: [<%= helper.implicit_attribute.skip_wrapping_for.map { |s| "\"#{s}\"" }.join(", ") %>],
|
|
82
|
+
},
|
|
83
|
+
<%- else -%>
|
|
84
|
+
implicitAttribute: null,
|
|
85
|
+
<%- end -%>
|
|
86
|
+
arguments: [
|
|
87
|
+
<%- helper.arguments.each do |arg| -%>
|
|
88
|
+
{ name: "<%= arg.name %>", position: <%= arg.position %>, type: "<%= arg.type_display %>", optional: <%= arg.optional %>, default: <%= arg.default ? "\"#{arg.escaped_default}\"" : "null" %>, splat: <%= arg.splat %>, description: "<%= arg.escaped_description %>" },
|
|
89
|
+
<%- end -%>
|
|
90
|
+
],
|
|
91
|
+
options: [
|
|
92
|
+
<%- helper.options.each do |opt| -%>
|
|
93
|
+
{ name: "<%= opt.name %>", type: "<%= opt.type_display %>", mapsTo: <%= opt.maps_to ? "\"#{opt.maps_to}\"" : "null" %>, description: "<%= opt.escaped_description %>" },
|
|
94
|
+
<%- end -%>
|
|
95
|
+
],
|
|
96
|
+
specialBehaviors: [<%= helper.special_behaviors.map { |b| "\"#{b}\"" }.join(", ") %>],
|
|
97
|
+
aliases: [<%= helper.aliases.map { |a| "\"#{a}\"" }.join(", ") %>],
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
<%- end -%>
|
|
101
|
+
export const HELPER_REGISTRY: Record<string, HelperEntry> = {
|
|
102
|
+
<%- helpers.each do |helper| -%>
|
|
103
|
+
"<%= helper.name %>": <%= helper.lower_camel_case_name %>Entry,
|
|
104
|
+
<%- helper.aliases.each do |alias_name| -%>
|
|
105
|
+
"<%= alias_name %>": <%= helper.lower_camel_case_name %>Entry,
|
|
106
|
+
<%- end -%>
|
|
107
|
+
<%- end -%>
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const HELPER_BY_SOURCE: Record<string, HelperEntry> = {
|
|
111
|
+
<%- helpers.each do |helper| -%>
|
|
112
|
+
"<%= helper.source %>": <%= helper.lower_camel_case_name %>Entry,
|
|
113
|
+
<%- end -%>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
<%- helpers_by_tag = helpers.select(&:static_tag_name?).group_by(&:tag_name) -%>
|
|
117
|
+
export const HELPERS_BY_TAG_NAME: Record<string, HelperEntry[]> = {
|
|
118
|
+
<%- helpers_by_tag.each do |tag_name, helpers| -%>
|
|
119
|
+
"<%= tag_name %>": [<%= helpers.map { |h| "#{h.lower_camel_case_name}Entry" }.join(", ") %>],
|
|
120
|
+
<%- end -%>
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function getHelper(name: string): HelperEntry | undefined {
|
|
124
|
+
return HELPER_REGISTRY[name]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function getHelperBySource(source: string): HelperEntry | undefined {
|
|
128
|
+
return HELPER_BY_SOURCE[source]
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function getHelperEntries(): HelperEntry[] {
|
|
132
|
+
return Object.values(HELPER_REGISTRY)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function isHelperSupported(name: string): boolean {
|
|
136
|
+
return HELPER_REGISTRY[name]?.supported ?? false
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function helperExists(name: string): boolean {
|
|
140
|
+
return name in HELPER_REGISTRY
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function getHelpersForTag(tagName: string): HelperEntry[] {
|
|
144
|
+
return HELPERS_BY_TAG_NAME[tagName] ?? []
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function findPreferredHelperForTag(tagName: string): HelperEntry | undefined {
|
|
148
|
+
const helpers = HELPERS_BY_TAG_NAME[tagName]
|
|
149
|
+
if (!helpers) return undefined
|
|
150
|
+
|
|
151
|
+
return helpers.find(entry => entry.preferredForTag) ?? helpers[0]
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function getSupportedHelpers(): HelperEntry[] {
|
|
155
|
+
return Object.values(HELPER_REGISTRY).filter(entry => entry.supported)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function getHelpersByGem(gem: string): HelperEntry[] {
|
|
159
|
+
return Object.values(HELPER_REGISTRY).filter(entry => entry.gem === gem)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function getHelpersByOutput(output: HelperOutput): HelperEntry[] {
|
|
163
|
+
return Object.values(HELPER_REGISTRY).filter(entry => entry.output === output)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function getHelpersByModule(moduleName: string): HelperEntry[] {
|
|
167
|
+
return Object.values(HELPER_REGISTRY).filter(entry => {
|
|
168
|
+
const parts = entry.source.split("#")[0].split("::")
|
|
169
|
+
return parts[parts.length - 1] === moduleName
|
|
170
|
+
})
|
|
171
|
+
}
|
|
@@ -318,7 +318,11 @@ export class <%= node.name %> extends Node {
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
accept(visitor: Visitor): void {
|
|
321
|
-
visitor.visit<%= node.name %>(
|
|
321
|
+
const visitMethod = visitor.visit<%= node.name %> as ((node: <%= node.name %>) => void) | undefined
|
|
322
|
+
|
|
323
|
+
if (typeof visitMethod === "function") {
|
|
324
|
+
visitMethod.call(visitor, this)
|
|
325
|
+
}
|
|
322
326
|
}
|
|
323
327
|
|
|
324
328
|
childNodes(): (Node | null | undefined)[] {
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
module Herb
|
|
2
|
+
module ActionView
|
|
3
|
+
module HelperType
|
|
4
|
+
<%- helpers.each do |helper| -%>
|
|
5
|
+
<%= helper.constant_name %> = :<%= helper.name %>
|
|
6
|
+
<%- end -%>
|
|
7
|
+
|
|
8
|
+
ALL = [
|
|
9
|
+
<%- helpers.each do |helper| -%>
|
|
10
|
+
<%= helper.constant_name %>,
|
|
11
|
+
<%- end -%>
|
|
12
|
+
].freeze #: Array[Symbol]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class HelperArgument
|
|
16
|
+
attr_reader :name #: String
|
|
17
|
+
attr_reader :position #: Integer
|
|
18
|
+
attr_reader :type #: String
|
|
19
|
+
attr_reader :default #: String?
|
|
20
|
+
attr_reader :description #: String
|
|
21
|
+
|
|
22
|
+
#: (String, Integer, String, bool, String?, bool, String) -> void
|
|
23
|
+
def initialize(name, position, type, optional, default, splat, description)
|
|
24
|
+
@name = name
|
|
25
|
+
@position = position
|
|
26
|
+
@type = type
|
|
27
|
+
@optional = optional
|
|
28
|
+
@default = default
|
|
29
|
+
@splat = splat
|
|
30
|
+
@description = description
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#: () -> bool
|
|
34
|
+
def optional? = @optional
|
|
35
|
+
|
|
36
|
+
#: () -> bool
|
|
37
|
+
def splat? = @splat
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class HelperOption
|
|
41
|
+
attr_reader :name #: String
|
|
42
|
+
attr_reader :type #: String
|
|
43
|
+
attr_reader :maps_to #: String?
|
|
44
|
+
attr_reader :description #: String
|
|
45
|
+
|
|
46
|
+
#: (String, String, String?, String) -> void
|
|
47
|
+
def initialize(name, type, maps_to, description)
|
|
48
|
+
@name = name
|
|
49
|
+
@type = type
|
|
50
|
+
@maps_to = maps_to
|
|
51
|
+
@description = description
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#: () -> bool
|
|
55
|
+
def maps_to_data_attribute? = maps_to&.start_with?("data-") || false
|
|
56
|
+
|
|
57
|
+
#: () -> bool
|
|
58
|
+
def maps_to_aria_attribute? = maps_to&.start_with?("aria-") || false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class HelperImplicitAttribute
|
|
62
|
+
attr_reader :name #: String
|
|
63
|
+
attr_reader :source #: String
|
|
64
|
+
attr_reader :source_with_block #: String?
|
|
65
|
+
attr_reader :wrapper #: String
|
|
66
|
+
attr_reader :skip_wrapping_for #: Array[String]
|
|
67
|
+
|
|
68
|
+
#: (String, String, String?, String, Array[String]) -> void
|
|
69
|
+
def initialize(name, source, source_with_block, wrapper, skip_wrapping_for)
|
|
70
|
+
@name = name
|
|
71
|
+
@source = source
|
|
72
|
+
@source_with_block = source_with_block
|
|
73
|
+
@wrapper = wrapper
|
|
74
|
+
@skip_wrapping_for = skip_wrapping_for
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
class HelperEntry
|
|
79
|
+
attr_reader :name #: String
|
|
80
|
+
attr_reader :type #: Symbol
|
|
81
|
+
attr_reader :source #: String
|
|
82
|
+
attr_reader :gem #: String
|
|
83
|
+
attr_reader :output #: Symbol
|
|
84
|
+
attr_reader :visibility #: String
|
|
85
|
+
attr_reader :tag_name #: String?
|
|
86
|
+
attr_reader :detect_style #: Symbol
|
|
87
|
+
attr_reader :description #: String
|
|
88
|
+
attr_reader :signature #: String
|
|
89
|
+
attr_reader :documentation_url #: String
|
|
90
|
+
attr_reader :implicit_attribute #: HelperImplicitAttribute?
|
|
91
|
+
attr_reader :arguments #: Array[HelperArgument]
|
|
92
|
+
attr_reader :options #: Array[HelperOption]
|
|
93
|
+
attr_reader :special_behaviors #: Array[Symbol]
|
|
94
|
+
attr_reader :aliases #: Array[String]
|
|
95
|
+
|
|
96
|
+
#: (name: String, type: Symbol, source: String, gem: String, output: Symbol, visibility: String, tag_name: String?, is_void: bool, supports_block: bool, preferred_for_tag: bool, supported: bool, detect_style: Symbol, description: String, signature: String, documentation_url: String, implicit_attribute: HelperImplicitAttribute?, arguments: Array[HelperArgument], options: Array[HelperOption], special_behaviors: Array[Symbol], aliases: Array[String]) -> void
|
|
97
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
|
98
|
+
name:, type:, source:, gem:, output:, visibility:, tag_name:, is_void:, supports_block:,
|
|
99
|
+
preferred_for_tag:, supported:, detect_style:, description:, signature:, documentation_url:,
|
|
100
|
+
implicit_attribute:, arguments:, options:, special_behaviors:, aliases:
|
|
101
|
+
)
|
|
102
|
+
@name = name
|
|
103
|
+
@type = type
|
|
104
|
+
@source = source
|
|
105
|
+
@gem = gem
|
|
106
|
+
@output = output
|
|
107
|
+
@visibility = visibility
|
|
108
|
+
@tag_name = tag_name
|
|
109
|
+
@is_void = is_void
|
|
110
|
+
@supports_block = supports_block
|
|
111
|
+
@preferred_for_tag = preferred_for_tag
|
|
112
|
+
@supported = supported
|
|
113
|
+
@detect_style = detect_style
|
|
114
|
+
@description = description
|
|
115
|
+
@signature = signature
|
|
116
|
+
@documentation_url = documentation_url
|
|
117
|
+
@implicit_attribute = implicit_attribute
|
|
118
|
+
@arguments = arguments
|
|
119
|
+
@options = options
|
|
120
|
+
@special_behaviors = special_behaviors
|
|
121
|
+
@aliases = aliases
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
#: () -> bool
|
|
125
|
+
def void? = @is_void
|
|
126
|
+
|
|
127
|
+
#: () -> bool
|
|
128
|
+
def supports_block? = @supports_block
|
|
129
|
+
|
|
130
|
+
#: () -> bool
|
|
131
|
+
def preferred_for_tag? = @preferred_for_tag
|
|
132
|
+
|
|
133
|
+
#: () -> bool
|
|
134
|
+
def supported? = @supported
|
|
135
|
+
|
|
136
|
+
#: () -> bool
|
|
137
|
+
def static_tag_name? = !@tag_name.nil?
|
|
138
|
+
|
|
139
|
+
#: () -> bool
|
|
140
|
+
def implicit_attribute? = !@implicit_attribute.nil?
|
|
141
|
+
|
|
142
|
+
#: () -> bool
|
|
143
|
+
def call_name_detect? = @detect_style == :call_name
|
|
144
|
+
|
|
145
|
+
#: () -> bool
|
|
146
|
+
def receiver_call_detect? = @detect_style == :receiver_call
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
module HelperRegistry
|
|
150
|
+
<%- helpers.each do |helper| -%>
|
|
151
|
+
<%= helper.constant_name %> = HelperEntry.new(
|
|
152
|
+
name: "<%= helper.name %>",
|
|
153
|
+
type: HelperType::<%= helper.constant_name %>,
|
|
154
|
+
source: "<%= helper.source %>",
|
|
155
|
+
gem: "<%= helper.gem %>",
|
|
156
|
+
output: :<%= helper.output %>,
|
|
157
|
+
visibility: "<%= helper.visibility %>",
|
|
158
|
+
tag_name: <%= helper.tag_name ? "\"#{helper.tag_name}\"" : "nil" %>,
|
|
159
|
+
is_void: <%= helper.void? %>,
|
|
160
|
+
supports_block: <%= helper.supports_block %>,
|
|
161
|
+
preferred_for_tag: <%= helper.preferred_for_tag %>,
|
|
162
|
+
supported: <%= helper.supported %>,
|
|
163
|
+
detect_style: :<%= helper.detect_style || "call_name" %>,
|
|
164
|
+
description: "<%= helper.escaped_description %>",
|
|
165
|
+
signature: "<%= helper.escaped_signature %>",
|
|
166
|
+
documentation_url: "<%= helper.documentation_url %>",
|
|
167
|
+
<%- if helper.implicit_attribute? -%>
|
|
168
|
+
implicit_attribute: HelperImplicitAttribute.new(
|
|
169
|
+
"<%= helper.implicit_attribute.name %>",
|
|
170
|
+
"<%= helper.implicit_attribute.source %>",
|
|
171
|
+
<%= helper.implicit_attribute.source_with_block ? "\"#{helper.implicit_attribute.source_with_block}\"" : "nil" %>,
|
|
172
|
+
"<%= helper.implicit_attribute.wrapper %>",
|
|
173
|
+
[<%= helper.implicit_attribute.skip_wrapping_for.map { |s| "\"#{s}\"" }.join(", ") %>]
|
|
174
|
+
),
|
|
175
|
+
<%- else -%>
|
|
176
|
+
implicit_attribute: nil,
|
|
177
|
+
<%- end -%>
|
|
178
|
+
arguments: [
|
|
179
|
+
<%- helper.arguments.each do |arg| -%>
|
|
180
|
+
HelperArgument.new("<%= arg.name %>", <%= arg.position %>, "<%= arg.type_display %>", <%= arg.optional %>, <%= arg.default ? "\"#{arg.escaped_default}\"" : "nil" %>, <%= arg.splat %>, "<%= arg.escaped_description %>"),
|
|
181
|
+
<%- end -%>
|
|
182
|
+
],
|
|
183
|
+
options: [
|
|
184
|
+
<%- helper.options.each do |opt| -%>
|
|
185
|
+
HelperOption.new("<%= opt.name %>", "<%= opt.type_display %>", <%= opt.maps_to ? "\"#{opt.maps_to}\"" : "nil" %>, "<%= opt.escaped_description %>"),
|
|
186
|
+
<%- end -%>
|
|
187
|
+
],
|
|
188
|
+
special_behaviors: [<%= helper.special_behaviors.map { |b| ":#{b}" }.join(", ") %>],
|
|
189
|
+
aliases: [<%= helper.aliases.map { |a| "\"#{a}\"" }.join(", ") %>],
|
|
190
|
+
).freeze #: HelperEntry
|
|
191
|
+
|
|
192
|
+
<%- end -%>
|
|
193
|
+
ENTRIES = {
|
|
194
|
+
<%- helpers.each do |helper| -%>
|
|
195
|
+
"<%= helper.name %>" => <%= helper.constant_name %>,
|
|
196
|
+
<%- helper.aliases.each do |alias_name| -%>
|
|
197
|
+
"<%= alias_name %>" => <%= helper.constant_name %>,
|
|
198
|
+
<%- end -%>
|
|
199
|
+
<%- end -%>
|
|
200
|
+
}.freeze #: Hash[String, HelperEntry]
|
|
201
|
+
|
|
202
|
+
BY_SOURCE = {
|
|
203
|
+
<%- helpers.each do |helper| -%>
|
|
204
|
+
"<%= helper.source %>" => <%= helper.constant_name %>,
|
|
205
|
+
<%- end -%>
|
|
206
|
+
}.freeze #: Hash[String, HelperEntry]
|
|
207
|
+
|
|
208
|
+
<%- helpers_by_tag = helpers.select(&:static_tag_name?).group_by(&:tag_name) -%>
|
|
209
|
+
|
|
210
|
+
BY_TAG_NAME = {
|
|
211
|
+
<%- helpers_by_tag.each do |tag_name, helpers| -%>
|
|
212
|
+
"<%= tag_name %>" => [<%= helpers.map(&:constant_name).join(", ") %>].freeze,
|
|
213
|
+
<%- end -%>
|
|
214
|
+
}.freeze #: Hash[String, Array[HelperEntry]]
|
|
215
|
+
|
|
216
|
+
class << self
|
|
217
|
+
#: (String) -> HelperEntry?
|
|
218
|
+
def get(name)
|
|
219
|
+
ENTRIES[name.to_s]
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
#: (String) -> HelperEntry?
|
|
223
|
+
def find_by_source(source)
|
|
224
|
+
BY_SOURCE[source]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
#: () -> Array[HelperEntry]
|
|
228
|
+
def entries
|
|
229
|
+
ENTRIES.values
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
#: () { (HelperEntry) -> void } -> void
|
|
233
|
+
def each(&block)
|
|
234
|
+
entries.each(&block)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
#: (String) -> Array[HelperEntry]
|
|
238
|
+
def helpers_for_tag(tag_name)
|
|
239
|
+
BY_TAG_NAME[tag_name] || []
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
#: (String) -> HelperEntry?
|
|
243
|
+
def find_preferred_for_tag(tag_name)
|
|
244
|
+
helpers = BY_TAG_NAME[tag_name]
|
|
245
|
+
return nil unless helpers
|
|
246
|
+
|
|
247
|
+
helpers.find(&:preferred_for_tag?) || helpers.first
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
#: () -> Integer
|
|
251
|
+
def count
|
|
252
|
+
ENTRIES.size
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
#: (String) -> bool
|
|
256
|
+
def supported?(name)
|
|
257
|
+
entry = get(name)
|
|
258
|
+
entry&.supported? || false
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
#: (String) -> bool
|
|
262
|
+
def exists?(name)
|
|
263
|
+
ENTRIES.key?(name.to_s)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
#: () -> Array[HelperEntry]
|
|
267
|
+
def supported
|
|
268
|
+
entries.select(&:supported?)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
#: (String) -> Array[HelperEntry]
|
|
272
|
+
def by_gem(gem_name)
|
|
273
|
+
entries.select { |entry| entry.gem == gem_name }
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
#: (Symbol) -> Array[HelperEntry]
|
|
277
|
+
def by_output(output)
|
|
278
|
+
entries.select { |entry| entry.output == output }
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
#: (String) -> Array[HelperEntry]
|
|
282
|
+
def by_module(module_name)
|
|
283
|
+
entries.select { |entry| entry.source.split("#").first.split("::").last == module_name }
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
2
|
+
pub enum HelperType {
|
|
3
|
+
<%- helpers.each do |helper| -%>
|
|
4
|
+
/// `<%= helper.name %>` — <%= helper.source %>
|
|
5
|
+
<%= helper.camel_case_name %>,
|
|
6
|
+
<%- end -%>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
impl HelperType {
|
|
10
|
+
pub fn as_str(&self) -> &'static str {
|
|
11
|
+
match self {
|
|
12
|
+
<%- helpers.each do |helper| -%>
|
|
13
|
+
HelperType::<%= helper.camel_case_name %> => "<%= helper.name %>",
|
|
14
|
+
<%- end -%>
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn from_name(name: &str) -> Option<HelperType> {
|
|
19
|
+
match name {
|
|
20
|
+
<%- helpers.each do |helper| -%>
|
|
21
|
+
"<%= helper.name %>" => Some(HelperType::<%= helper.camel_case_name %>),
|
|
22
|
+
<%- end -%>
|
|
23
|
+
_ => None,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#[derive(Debug, Clone)]
|
|
29
|
+
pub struct HelperArgument {
|
|
30
|
+
pub name: &'static str,
|
|
31
|
+
pub position: usize,
|
|
32
|
+
pub argument_type: &'static str,
|
|
33
|
+
pub optional: bool,
|
|
34
|
+
pub default: Option<&'static str>,
|
|
35
|
+
pub splat: bool,
|
|
36
|
+
pub description: &'static str,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#[derive(Debug, Clone)]
|
|
40
|
+
pub struct HelperOption {
|
|
41
|
+
pub name: &'static str,
|
|
42
|
+
pub option_type: &'static str,
|
|
43
|
+
pub maps_to: Option<&'static str>,
|
|
44
|
+
pub description: &'static str,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#[derive(Debug, Clone)]
|
|
48
|
+
pub struct HelperImplicitAttribute {
|
|
49
|
+
pub name: &'static str,
|
|
50
|
+
pub source: &'static str,
|
|
51
|
+
pub source_with_block: Option<&'static str>,
|
|
52
|
+
pub wrapper: &'static str,
|
|
53
|
+
pub skip_wrapping_for: &'static [&'static str],
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#[derive(Debug, Clone)]
|
|
57
|
+
pub struct HelperEntry {
|
|
58
|
+
pub name: &'static str,
|
|
59
|
+
pub helper_type: HelperType,
|
|
60
|
+
pub source: &'static str,
|
|
61
|
+
pub gem: &'static str,
|
|
62
|
+
pub output: &'static str,
|
|
63
|
+
pub visibility: &'static str,
|
|
64
|
+
pub tag_name: Option<&'static str>,
|
|
65
|
+
pub is_void: bool,
|
|
66
|
+
pub supports_block: bool,
|
|
67
|
+
pub preferred_for_tag: bool,
|
|
68
|
+
pub supported: bool,
|
|
69
|
+
pub detect_style: &'static str,
|
|
70
|
+
pub description: &'static str,
|
|
71
|
+
pub signature: &'static str,
|
|
72
|
+
pub documentation_url: &'static str,
|
|
73
|
+
pub implicit_attribute: Option<&'static HelperImplicitAttribute>,
|
|
74
|
+
pub arguments: &'static [HelperArgument],
|
|
75
|
+
pub options: &'static [HelperOption],
|
|
76
|
+
pub special_behaviors: &'static [&'static str],
|
|
77
|
+
pub aliases: &'static [&'static str],
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
<%- helpers.each do |helper| -%>
|
|
81
|
+
<%- if helper.implicit_attribute? -%>
|
|
82
|
+
static <%= helper.constant_name %>_IMPLICIT_ATTR: HelperImplicitAttribute = HelperImplicitAttribute {
|
|
83
|
+
name: "<%= helper.implicit_attribute.name %>",
|
|
84
|
+
source: "<%= helper.implicit_attribute.source %>",
|
|
85
|
+
source_with_block: <%= helper.implicit_attribute.source_with_block ? "Some(\"#{helper.implicit_attribute.source_with_block}\")" : "None" %>,
|
|
86
|
+
wrapper: "<%= helper.implicit_attribute.wrapper %>",
|
|
87
|
+
skip_wrapping_for: &[<%= helper.implicit_attribute.skip_wrapping_for.map { |s| "\"#{s}\"" }.join(", ") %>],
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
<%- end -%>
|
|
91
|
+
<%- end -%>
|
|
92
|
+
|
|
93
|
+
static REGISTRY: [HelperEntry; <%= helpers.size %>] = [
|
|
94
|
+
<%- helpers.each do |helper| -%>
|
|
95
|
+
HelperEntry {
|
|
96
|
+
name: "<%= helper.name %>",
|
|
97
|
+
helper_type: HelperType::<%= helper.camel_case_name %>,
|
|
98
|
+
source: "<%= helper.source %>",
|
|
99
|
+
gem: "<%= helper.gem %>",
|
|
100
|
+
output: "<%= helper.output %>",
|
|
101
|
+
visibility: "<%= helper.visibility %>",
|
|
102
|
+
tag_name: <%= helper.tag_name ? "Some(\"#{helper.tag_name}\")" : "None" %>,
|
|
103
|
+
is_void: <%= helper.void? %>,
|
|
104
|
+
supports_block: <%= helper.supports_block %>,
|
|
105
|
+
preferred_for_tag: <%= helper.preferred_for_tag %>,
|
|
106
|
+
supported: <%= helper.supported %>,
|
|
107
|
+
detect_style: "<%= helper.detect_style || "call_name" %>",
|
|
108
|
+
description: "<%= helper.escaped_description %>",
|
|
109
|
+
signature: "<%= helper.escaped_signature %>",
|
|
110
|
+
documentation_url: "<%= helper.documentation_url %>",
|
|
111
|
+
implicit_attribute: <%= helper.implicit_attribute? ? "Some(&#{helper.constant_name}_IMPLICIT_ATTR)" : "None" %>,
|
|
112
|
+
arguments: &[
|
|
113
|
+
<%- helper.arguments.each do |arg| -%>
|
|
114
|
+
HelperArgument { name: "<%= arg.name %>", position: <%= arg.position %>, argument_type: "<%= arg.type_display %>", optional: <%= arg.optional %>, default: <%= arg.default ? "Some(\"#{arg.escaped_default}\")" : "None" %>, splat: <%= arg.splat %>, description: "<%= arg.escaped_description %>" },
|
|
115
|
+
<%- end -%>
|
|
116
|
+
],
|
|
117
|
+
options: &[
|
|
118
|
+
<%- helper.options.each do |opt| -%>
|
|
119
|
+
HelperOption { name: "<%= opt.name %>", option_type: "<%= opt.type_display %>", maps_to: <%= opt.maps_to ? "Some(\"#{opt.maps_to}\")" : "None" %>, description: "<%= opt.escaped_description %>" },
|
|
120
|
+
<%- end -%>
|
|
121
|
+
],
|
|
122
|
+
special_behaviors: &[<%= helper.special_behaviors.map { |b| "\"#{b}\"" }.join(", ") %>],
|
|
123
|
+
aliases: &[<%= helper.aliases.map { |a| "\"#{a}\"" }.join(", ") %>],
|
|
124
|
+
},
|
|
125
|
+
<%- end -%>
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
pub fn get(helper_type: HelperType) -> &'static HelperEntry {
|
|
129
|
+
®ISTRY[helper_type as usize]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
pub fn find_by_name(name: &str) -> Option<&'static HelperEntry> {
|
|
133
|
+
REGISTRY.iter().find(|entry| entry.name == name)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
pub fn find_by_source(source: &str) -> Option<&'static HelperEntry> {
|
|
137
|
+
REGISTRY.iter().find(|entry| entry.source == source)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
pub fn helpers_for_tag(tag_name: &str) -> Vec<&'static HelperEntry> {
|
|
141
|
+
REGISTRY.iter().filter(|entry| entry.tag_name == Some(tag_name)).collect()
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
pub fn find_preferred_for_tag(tag_name: &str) -> Option<&'static HelperEntry> {
|
|
145
|
+
REGISTRY.iter().find(|entry| entry.tag_name == Some(tag_name) && entry.preferred_for_tag)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
pub fn entries() -> &'static [HelperEntry] {
|
|
149
|
+
®ISTRY
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
pub fn count() -> usize {
|
|
153
|
+
REGISTRY.len()
|
|
154
|
+
}
|