evc_rails 0.3.0 → 0.3.2
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 +18 -0
- data/README.md +11 -0
- data/lib/evc_rails/template_handler.rb +86 -12
- data/lib/evc_rails/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 176929bf44d50fb5c8e783d6cdd745c02f09d500b59daf5838f7b0a6f2fdda28
|
4
|
+
data.tar.gz: 285435052b2267b961ff7b670738abdccca2f9b0ad89ecc7eca8508b81a6ce8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aab13dc98534d5888de5756a7cb6ff90e993a882db66f689914d3e68b755f51cc7871f4b1a6b8f59e9a8fe6a99695d7935d584ff8790e3c13f17aa05ca981c78
|
7
|
+
data.tar.gz: e71dc0b00125dd83ea4f1c8f4734e756cdbbc38e6d0892121d5274cac47e3ae40432c83de6a29abd9c7bfce0998d6d223a4710e26f302e4c90a623830f9f7515
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.3.2] - 2024-12-19
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
- **Kebab-case attribute support**: Support for HTML-style kebab-case attributes in addition to snake_case
|
13
|
+
- `<Button data-test-id="value" />` converts to `data_test_id: "value"`
|
14
|
+
- `<Button aria-label="Click me" />` converts to `aria_label: "Click me"`
|
15
|
+
- Works with boolean attributes: `<Button data-disabled aria-hidden />`
|
16
|
+
- Supports Ruby expressions: `<Button data-user-id={@user.id} />`
|
17
|
+
- Fully backward compatible with existing snake_case attributes
|
18
|
+
- Automatically converts kebab-case to snake_case for Ruby compatibility
|
19
|
+
|
20
|
+
## [0.3.1] - 2024-12-19
|
21
|
+
|
22
|
+
### Fixed
|
23
|
+
|
24
|
+
- **Robust attribute parsing**: Fixed a bug where complex or nested Ruby expressions (e.g., arrays or hashes with nested braces) in attribute values could cause parsing errors or incorrect output. The attribute parser is now fully robust and handles any valid Ruby expression inside `{...}` for both component and slot attributes.
|
25
|
+
|
8
26
|
## [0.3.0] - 2024-12-19
|
9
27
|
|
10
28
|
### Added
|
data/README.md
CHANGED
@@ -64,6 +64,17 @@ $ bundle install
|
|
64
64
|
|
65
65
|
The template handler will be automatically registered for `.evc` files.
|
66
66
|
|
67
|
+
## Syntax Highlighting
|
68
|
+
|
69
|
+
For the best development experience with EVC files, install the [EVC Language Support](https://github.com/senordelaflor/evc-language-support) extension for VS Code. This extension provides:
|
70
|
+
|
71
|
+
- **Syntax highlighting** for ERB tags (`<% %>`, `<%= %>`, `<%# %>`)
|
72
|
+
- **JSX-like attribute syntax** support (`prop={value}`)
|
73
|
+
- **Nested bracket matching** for arrays and hashes
|
74
|
+
- **HTML tag completion** via Emmet
|
75
|
+
- **Auto-closing pairs** for brackets and ERB tags
|
76
|
+
- **Proper folding** for ERB blocks
|
77
|
+
|
67
78
|
## Usage
|
68
79
|
|
69
80
|
### Basic Components
|
@@ -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 = /(
|
16
|
+
ATTRIBUTE_REGEX = /([a-zA-Z0-9_-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([^}]*)\}))?/
|
17
17
|
|
18
18
|
# Cache for compiled templates
|
19
19
|
@template_cache = {}
|
@@ -274,6 +274,12 @@ module EvcRails
|
|
274
274
|
name
|
275
275
|
end
|
276
276
|
|
277
|
+
def normalize_attribute_name(attribute_name)
|
278
|
+
# Convert dasherized attributes to snake_case for Ruby compatibility
|
279
|
+
# e.g., "data-test-id" -> "data_test_id"
|
280
|
+
attribute_name.gsub("-", "_")
|
281
|
+
end
|
282
|
+
|
277
283
|
def parse_attributes(attributes_str, attribute_regex = ATTRIBUTE_REGEX)
|
278
284
|
as_variable = nil
|
279
285
|
# Find and remove the `as` attribute, storing its value.
|
@@ -283,17 +289,85 @@ module EvcRails
|
|
283
289
|
end.strip
|
284
290
|
|
285
291
|
params = []
|
286
|
-
attributes_str.
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
292
|
+
str = attributes_str.dup
|
293
|
+
until str.nil? || str.empty?
|
294
|
+
str = "" if str.nil?
|
295
|
+
str.lstrip!
|
296
|
+
str = "" if str.nil?
|
297
|
+
break if str.empty?
|
298
|
+
# Match key
|
299
|
+
break unless str =~ /\A([a-zA-Z0-9_-]+)/
|
300
|
+
|
301
|
+
key = normalize_attribute_name(::Regexp.last_match(1))
|
302
|
+
str = str[::Regexp.last_match(0).length..-1]
|
303
|
+
str = "" if str.nil?
|
304
|
+
str.lstrip!
|
305
|
+
str = "" if str.nil?
|
306
|
+
if str.start_with?("=")
|
307
|
+
str = str[1..-1]
|
308
|
+
str = "" if str.nil?
|
309
|
+
str.lstrip!
|
310
|
+
str = "" if str.nil?
|
311
|
+
if str.start_with?("{")
|
312
|
+
# Parse balanced curly braces
|
313
|
+
depth = 0
|
314
|
+
i = 0
|
315
|
+
found = false
|
316
|
+
while true
|
317
|
+
str = "" if str.nil?
|
318
|
+
break if str.empty? || i >= str.length
|
319
|
+
|
320
|
+
c = str[i]
|
321
|
+
if c == "{"
|
322
|
+
depth += 1
|
323
|
+
elsif c == "}"
|
324
|
+
depth -= 1
|
325
|
+
if depth == 0
|
326
|
+
found = true
|
327
|
+
break
|
328
|
+
end
|
329
|
+
end
|
330
|
+
i += 1
|
331
|
+
end
|
332
|
+
if found
|
333
|
+
ruby_expr = str[1...i] # skip opening '{', up to before closing '}'
|
334
|
+
str = str[(i + 1)..-1]
|
335
|
+
str = "" if str.nil?
|
336
|
+
params << "#{key}: #{ruby_expr}"
|
337
|
+
else
|
338
|
+
# Unbalanced braces, treat as error or fallback
|
339
|
+
params << "#{key}: true"
|
340
|
+
str = ""
|
341
|
+
end
|
342
|
+
elsif str.start_with?("\"")
|
343
|
+
# Double-quoted string
|
344
|
+
if str =~ /\A"([^"]*)"/
|
345
|
+
str = str[::Regexp.last_match(0).length..-1]
|
346
|
+
str = "" if str.nil?
|
347
|
+
params << "#{key}: \"#{::Regexp.last_match(1).gsub('"', '\\"')}\""
|
348
|
+
else
|
349
|
+
params << "#{key}: true"
|
350
|
+
str = ""
|
351
|
+
end
|
352
|
+
elsif str.start_with?("'")
|
353
|
+
# Single-quoted string
|
354
|
+
if str =~ /\A'([^']*)'/
|
355
|
+
str = str[::Regexp.last_match(0).length..-1]
|
356
|
+
str = "" if str.nil?
|
357
|
+
params << "#{key}: \"#{::Regexp.last_match(1).gsub("'", "\\'")}\""
|
358
|
+
else
|
359
|
+
params << "#{key}: true"
|
360
|
+
str = ""
|
361
|
+
end
|
362
|
+
else
|
363
|
+
# Unquoted value or malformed, treat as boolean true
|
364
|
+
params << "#{key}: true"
|
365
|
+
str = ""
|
366
|
+
end
|
367
|
+
else
|
368
|
+
# Standalone attribute (no value) - treat as boolean true
|
369
|
+
params << "#{key}: true"
|
370
|
+
end
|
297
371
|
end
|
298
372
|
[params, as_variable]
|
299
373
|
end
|
data/lib/evc_rails/version.rb
CHANGED