evc_rails 0.2.1 → 0.2.3
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 +87 -0
- data/README.md +44 -0
- data/lib/evc_rails/template_handler.rb +17 -12
- data/lib/evc_rails/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0083734e9b8f16100d769aa08c7393c7e60105a5c9bcbc3774c5955cc3c71def'
|
4
|
+
data.tar.gz: 9099d7be89c3b5c6805fbd0b7b9316409c53a89ff62b1460391265c4a18fa97b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 742227dddbef882cf3a085bfd2c8642e4decc61a76bb83f858b55bb900d1064d09b9507beb3cbfbb62d5472a644793f4457057d23962cce134a6d75aa018bfca
|
7
|
+
data.tar.gz: 13948d925ffc1419337d7d6a104be86bdae102577a133393978cb8c00eab2f7ee63bc627c6e15667c34671534f020588cf5e97297cbc82f6e0d79e800c9b416e
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [0.2.2] - 2024-12-19
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- **Boolean attribute shorthand**: Support for HTML-style boolean attributes without values
|
15
|
+
- `<Button disabled required />` now converts to `disabled: true, required: true`
|
16
|
+
- Makes templates more concise and readable for boolean parameters
|
17
|
+
- Works with any boolean parameter your component defines
|
18
|
+
|
19
|
+
### Changed
|
20
|
+
|
21
|
+
- Updated test suite to use new snake_case variable naming convention
|
22
|
+
- Improved block variable syntax consistency across all examples
|
23
|
+
|
24
|
+
## [0.2.1] - 2024-12-19
|
25
|
+
|
26
|
+
### Added
|
27
|
+
|
28
|
+
- **Custom block variable naming**: Support for `as` attribute to customize yielded variable names
|
29
|
+
- `<Card as="my_card">` yields `|my_card|` instead of `|card|`
|
30
|
+
- Helps avoid variable name collisions in nested components
|
31
|
+
- Useful for accessing parent component context from nested components
|
32
|
+
|
33
|
+
### Changed
|
34
|
+
|
35
|
+
- **Block variable naming**: Components now yield snake_case variable names by default
|
36
|
+
- `<Card>` now yields `|card|` instead of `|c|`
|
37
|
+
- More descriptive and consistent with Ruby naming conventions
|
38
|
+
- Only yields variables when slots are present in the component
|
39
|
+
|
40
|
+
### Fixed
|
41
|
+
|
42
|
+
- Improved slot method naming to match ViewComponent conventions
|
43
|
+
- `<WithHeader>` maps to `with_header` method (not `header`)
|
44
|
+
- `<WithItem>` maps to `with_item` method for both `renders_one` and `renders_many`
|
45
|
+
- Ensures compatibility with ViewComponent's generated method names
|
46
|
+
|
47
|
+
## [0.2.0] - 2024-12-19
|
48
|
+
|
49
|
+
### Added
|
50
|
+
|
51
|
+
- **Slot support**: Full support for ViewComponent slots with `<With...>` syntax
|
52
|
+
- `<WithHeader>` for `renders_one :header`
|
53
|
+
- `<WithItem>` for `renders_many :items` (uses singular method name)
|
54
|
+
- Support for slot attributes and Ruby expressions
|
55
|
+
- Automatic block variable yielding when slots are present
|
56
|
+
- **Namespaced component support**: Components in subdirectories
|
57
|
+
- `<UI::Button />` maps to `app/components/ui/button_component.rb`
|
58
|
+
- `<Forms::Fields::TextField />` for deeply nested components
|
59
|
+
- **Enhanced error messages**: Line numbers and column positions for better debugging
|
60
|
+
- **Production caching**: Automatic template caching using Rails.cache
|
61
|
+
- **Cache management**: Methods to clear and inspect template cache
|
62
|
+
|
63
|
+
### Changed
|
64
|
+
|
65
|
+
- **Template handler architecture**: Improved performance and reliability
|
66
|
+
- **Error handling**: More descriptive error messages with context
|
67
|
+
|
68
|
+
## [0.1.0] - 2024-12-19
|
69
|
+
|
70
|
+
### Added
|
71
|
+
|
72
|
+
- **Initial release**: Basic JSX-like syntax for ViewComponent
|
73
|
+
- **Self-closing components**: `<Button />` syntax
|
74
|
+
- **Block components**: `<Card>content</Card>` syntax
|
75
|
+
- **Attribute support**: String, Ruby expressions, and multiple attributes
|
76
|
+
- **ERB integration**: Full support for ERB tags and Ruby expressions
|
77
|
+
- **Drop-in replacement**: Works as a replacement for `.erb` files
|
78
|
+
- **Basic caching**: Template compilation caching for performance
|
79
|
+
|
80
|
+
---
|
81
|
+
|
82
|
+
## Version History Notes
|
83
|
+
|
84
|
+
- **0.1.0**: Initial release with core functionality
|
85
|
+
- **0.2.0**: Major feature addition with slots and namespaced components
|
86
|
+
- **0.2.1**: Improved variable naming and slot method compatibility
|
87
|
+
- **0.2.2**: Added boolean attribute shorthand for cleaner templates
|
data/README.md
CHANGED
@@ -176,6 +176,22 @@ There are two ways to pass information to a component:
|
|
176
176
|
- **As attributes:** Data passed as attributes on the main component tag (e.g. `<Card title="...">`) is sent to its `initialize` method.
|
177
177
|
- **As slot content:** Rich content passed via `<With...>` tags is used to populate the component's named slots.
|
178
178
|
|
179
|
+
#### Boolean Attribute Shorthand
|
180
|
+
|
181
|
+
You can use HTML-style boolean attributes in EVC. If you specify an attribute with no value, it will be passed as `true` to your component initializer. This makes templates more concise and readable:
|
182
|
+
|
183
|
+
```erb
|
184
|
+
<Button disabled required />
|
185
|
+
```
|
186
|
+
|
187
|
+
is equivalent to:
|
188
|
+
|
189
|
+
```erb
|
190
|
+
<%= render ButtonComponent.new(disabled: true, required: true) %>
|
191
|
+
```
|
192
|
+
|
193
|
+
This works for any boolean parameter your component defines.
|
194
|
+
|
179
195
|
#### When a Block Variable is Yielded
|
180
196
|
|
181
197
|
The contextual variable (e.g., `|card|`) is only yielded if one or more `<With...>` slot tags are present inside the component block. If you render a component like `<Card></Card>` with no slots inside, `evc_rails` is smart enough to render it without the `do |card|` part.
|
@@ -282,6 +298,34 @@ end
|
|
282
298
|
|
283
299
|
This generates distinct variables, `outer_card` and `inner_card`, allowing you to access the context of each component without collision.
|
284
300
|
|
301
|
+
#### Passing a Collection to a Plural Slot (Array Notation)
|
302
|
+
|
303
|
+
You can also pass an array directly to a plural slot method using embedded Ruby inside your EVC template. For this advanced use case, block variables are not inferred automatically and it is necessary to define block variables with the `as` attribute.
|
304
|
+
|
305
|
+
```erb
|
306
|
+
<Navigation as="navigation">
|
307
|
+
<% navigation.with_links([
|
308
|
+
{ name: "Home", href: "/" },
|
309
|
+
{ name: "Pricing", href: "/pricing" },
|
310
|
+
{ name: "Sign Up", href: "/sign-up" }
|
311
|
+
]) %>
|
312
|
+
</Navigation>
|
313
|
+
```
|
314
|
+
|
315
|
+
This is equivalent to the ERB version:
|
316
|
+
|
317
|
+
```erb
|
318
|
+
<%= render NavigationComponent.new do |navigation| %>
|
319
|
+
<% navigation.with_links([
|
320
|
+
{ name: "Home", href: "/" },
|
321
|
+
{ name: "Pricing", href: "/pricing" },
|
322
|
+
{ name: "Sign Up", href: "/sign-up" }
|
323
|
+
]) %>
|
324
|
+
<% end %>
|
325
|
+
```
|
326
|
+
|
327
|
+
You can use this approach for any plural slot method generated by `renders_many`. The block variable (e.g., `navigation`) is always available inside the component block when you use the `as` attribute, even if there are no `<With...>` slot tags present.
|
328
|
+
|
285
329
|
### Mixed Content
|
286
330
|
|
287
331
|
You can mix regular HTML, ERB, and component tags:
|
@@ -13,7 +13,7 @@ module EvcRails
|
|
13
13
|
CLOSE_TAG_REGEX = %r{</([A-Z][a-zA-Z0-9_]*(?:::[A-Z][a-zA-Z0-9_]*)*)>}
|
14
14
|
|
15
15
|
# Regex for attributes
|
16
|
-
ATTRIBUTE_REGEX = /(\w+)
|
16
|
+
ATTRIBUTE_REGEX = /(\w+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([^}]*)\}))?/
|
17
17
|
|
18
18
|
# Cache for compiled templates
|
19
19
|
@template_cache = {}
|
@@ -150,8 +150,10 @@ module EvcRails
|
|
150
150
|
else
|
151
151
|
component_class = "#{tag_name}Component"
|
152
152
|
variable_name = as_variable || component_variable_name(tag_name)
|
153
|
+
# If as_variable is present, force block variable to be yielded
|
154
|
+
force_block_variable = !as_variable.nil?
|
153
155
|
stack << [tag_name, component_class, param_str, result.length, :component, nil, false, match.begin(0),
|
154
|
-
variable_name]
|
156
|
+
variable_name, force_block_variable]
|
155
157
|
result << if param_str.empty?
|
156
158
|
"<%= render #{component_class}.new do %>"
|
157
159
|
else
|
@@ -188,10 +190,10 @@ module EvcRails
|
|
188
190
|
tag_type = open_tag_data[4]
|
189
191
|
|
190
192
|
if tag_type == :component
|
191
|
-
_tag_name, component_class, param_str, start_pos, _type, _slot_name, slot_used, _open_pos, variable_name = open_tag_data
|
193
|
+
_tag_name, component_class, param_str, start_pos, _type, _slot_name, slot_used, _open_pos, variable_name, force_block_variable = open_tag_data
|
192
194
|
|
193
|
-
# Patch in |variable_name| for component if a slot was used
|
194
|
-
if slot_used
|
195
|
+
# Patch in |variable_name| for component if a slot was used or as_variable was present
|
196
|
+
if slot_used || force_block_variable
|
195
197
|
# More robustly find the end of the `do` block to insert the variable.
|
196
198
|
# This avoids faulty regex matching on complex parameters.
|
197
199
|
relevant_part = result[start_pos..-1]
|
@@ -254,13 +256,16 @@ module EvcRails
|
|
254
256
|
|
255
257
|
params = []
|
256
258
|
attributes_str.scan(attribute_regex) do |key, quoted_value, single_quoted_value, ruby_expression|
|
257
|
-
if ruby_expression
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
259
|
+
params << if ruby_expression
|
260
|
+
"#{key}: #{ruby_expression}"
|
261
|
+
elsif quoted_value
|
262
|
+
"#{key}: \"#{quoted_value.gsub('"', '\\"')}\""
|
263
|
+
elsif single_quoted_value
|
264
|
+
"#{key}: \"#{single_quoted_value.gsub("'", "\\'")}\""
|
265
|
+
else
|
266
|
+
# Standalone attribute (no value) - treat as boolean true
|
267
|
+
"#{key}: true"
|
268
|
+
end
|
264
269
|
end
|
265
270
|
[params, as_variable]
|
266
271
|
end
|
data/lib/evc_rails/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: evc_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- scttymn
|
@@ -77,6 +77,7 @@ extensions: []
|
|
77
77
|
extra_rdoc_files: []
|
78
78
|
files:
|
79
79
|
- ".rubocop.yml"
|
80
|
+
- CHANGELOG.md
|
80
81
|
- LICENSE.txt
|
81
82
|
- README.md
|
82
83
|
- Rakefile
|