theo-rails 0.3.0 → 0.4.1

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/theo-rails/theo.rb +34 -14
  3. metadata +20 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a08de40e9205127777dc501ee41131f7c56b5d49ce3d793171a4f5fee114c087
4
- data.tar.gz: 7285c684000a300aefd5c71b9b287656153303fb7eea410a4d59af474e21d494
3
+ metadata.gz: 36c3ddae4b6c1dee1bbf309c1ab2c779c81ddaf511b35d7297a5f60b5b91d300
4
+ data.tar.gz: e3c6a104bca5f66f9f0aad687b6d295d55a0759a0cf816eaab0aff8d1408f647
5
5
  SHA512:
6
- metadata.gz: b5e8ae5ee062f9891934034acaf20e6d652162acdb08c587a2330989b6b10a7fd19a674dbc4ad13a4ce7e370300f3b6cc18de1d990bb6d8ab452855ae4563108
7
- data.tar.gz: aa2cee291cfc7ec96588b068cd52645e0502c53d87bec1f3c69d6e83e74879aede4aa47ef0b25c69219171a669d4ad6bcff430e3fef7de26efb6b9906c00de07
6
+ metadata.gz: 78a5be9f8c14fbe5125a321a1df522976fb5282210a1a704be86e35121f71cdd5ac21588348a078b11e218228d363d67ae788837dc50d63257b8abef7377e74d
7
+ data.tar.gz: 85fc477ad21b22d2cef02f9a72ff86d59612bbeb97af0b70c5ff50fb33738e8554d44ac3efbe7a4b1cc8584aabcb397323266f4f398f63c99aa335c582306087
@@ -1,29 +1,35 @@
1
1
  module Theo
2
2
  module Rails
3
- ATTRIBUTE_NAME = /[\w\-:@]+/
3
+ ATTRIBUTE_NAME = /(?<name>[a-z][\w\-:@]*)/
4
4
  ATTRIBUTE_VALUE = /(?:(?:"(?<value>[^"]*)")|(?:'(?<value>[^']*)'))/
5
- ATTRIBUTE = /(?:(?:(?<name>#{ATTRIBUTE_NAME.source})\s*=\s*#{ATTRIBUTE_VALUE.source})|(?<name>#{ATTRIBUTE_NAME.source}))/
6
- DYNAMIC_ATTRIBUTE = /(?:(?<name>#{ATTRIBUTE_NAME.source})\s*%=\s*#{ATTRIBUTE_VALUE.source})/
5
+ ATTRIBUTE = /(?:(?:#{ATTRIBUTE_NAME.source}\s*=\s*#{ATTRIBUTE_VALUE.source})|#{ATTRIBUTE_NAME.source})/
6
+ DYNAMIC_ATTRIBUTE = /(?:(?:#{ATTRIBUTE_NAME.source}\s*%=\s*#{ATTRIBUTE_VALUE.source})|(?:#{ATTRIBUTE_NAME.source}%))/
7
+ RESERVED_ATTRIBUTE_NAME = %w[alias and begin break case class def do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield].to_set
7
8
  ATTRIBUTES = /(?<attrs>(?:\s+#{ATTRIBUTE.source})*)/
8
9
  LITERAL_ATTRIBUTES = %i[path as yields collection].freeze
9
- PARTIAL_TAG = /(?<partial>_\w+)/
10
- PARTIAL = /(?:<#{PARTIAL_TAG.source}#{ATTRIBUTES.source}\s*>(?<content>.*?)<\/\k<partial>>)|(?:<#{PARTIAL_TAG.source}#{ATTRIBUTES.source}\s*\/>)/
11
- COMPONENT_TAG = /(?<component>[A-Z]\w+)/
12
- COMPONENT = /(?:<#{COMPONENT_TAG.source}#{ATTRIBUTES.source}\s*>(?<content>.*?)<\/\k<component>>)|(?:<#{COMPONENT_TAG.source}#{ATTRIBUTES.source}\s*\/>)/
13
- TEMPLATE = /(?:#{PARTIAL.source})|(?:#{COMPONENT.source})/m
10
+ PARTIAL_TAG = /(?:(?<partial>[A-Z]\w+)|(?<partial>_[\w-]+))/
11
+ PARTIAL = /(?:<#{PARTIAL_TAG.source}#{ATTRIBUTES.source}\s*>(?<content>.*?)<\/\k<partial>>)|(?:<#{PARTIAL_TAG.source}#{ATTRIBUTES.source}\s*\/>)/m
14
12
  DYNAMIC_EXPRESSION = /^<%=([^%]*)%>$/
15
13
 
16
14
  class Theo
17
15
  def process(source)
18
16
  # Attributes
19
- source = source.gsub(DYNAMIC_ATTRIBUTE, '\k<name>="<%= \k<value> %>"')
17
+ source = source.gsub(DYNAMIC_ATTRIBUTE) do |_|
18
+ match = Regexp.last_match
19
+
20
+ name = match[:name]
21
+
22
+ # See https://island94.org/2024/06/rails-strict-locals-local_assigns-and-reserved-keywords for more info
23
+ value = match[:value] || (RESERVED_ATTRIBUTE_NAME.include?(name) ? "binding.local_variable_get('#{name}')" : name)
24
+
25
+ "#{name}=\"<%= #{value} %>\""
26
+ end
20
27
 
21
28
  # Partials
22
- source.gsub(TEMPLATE) do |_|
29
+ source.gsub(PARTIAL) do |_|
23
30
  match = Regexp.last_match
24
31
 
25
32
  partial = match[:partial]
26
- component = match[:component]
27
33
 
28
34
  attributes = match[:attrs] || ''
29
35
  content = match[:content]
@@ -40,8 +46,11 @@ module Theo
40
46
 
41
47
  locals = attributes.empty? ? '' : attributes.map { |k, v| "'#{k}': #{v}" }.join(', ')
42
48
 
43
- if partial
44
- partial = partial.delete_prefix('_')
49
+ is_component = view_component_exists?(partial)
50
+ is_partial = !is_component
51
+
52
+ if is_partial
53
+ partial = partial.delete_prefix('_').underscore
45
54
 
46
55
  partial = "#{path}/#{partial}" if path
47
56
 
@@ -56,7 +65,7 @@ module Theo
56
65
  output = "<%= render partial: '#{partial}'#{collection}#{locals} %>"
57
66
  end
58
67
  else
59
- component = "#{component}Component"
68
+ component = "#{partial}Component"
60
69
 
61
70
  if content
62
71
  output = "<%= render #{component}.new(#{locals}) do#{yields} %>#{process(content)}<% end %>"
@@ -94,6 +103,17 @@ module Theo
94
103
  "'#{source}'"
95
104
  end
96
105
 
106
+ def view_component_loaded?
107
+ @view_component_loaded ||= Object.const_defined?('ViewComponent')
108
+ end
109
+
110
+ def view_component_exists?(component)
111
+ return unless view_component_loaded?
112
+
113
+ is_capitalized = /^[A-Z]/.match?(component)
114
+ is_capitalized && Object.const_defined?("#{component}Component")
115
+ end
116
+
97
117
  def call(template, source = nil)
98
118
  theo = process(source)
99
119
 
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: theo-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jarek Lipski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-28 00:00:00.000000000 Z
11
+ date: 2024-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '7'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rspec
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - ">="
31
+ - - "~>"
18
32
  - !ruby/object:Gem::Version
19
- version: '0'
33
+ version: '3'
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - ">="
38
+ - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: '0'
40
+ version: '3'
27
41
  description: HTML-like template language for Rails with natural partial syntax
28
42
  email: jarek@jareklipski.com
29
43
  executables: []