twig_ruby 0.0.3 → 0.0.5
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/README.md +124 -14
- data/lib/tasks/twig_parity.rake +1 -1
- data/lib/twig/environment.rb +1 -1
- data/lib/twig/extension/core.rb +1 -1
- data/lib/twig/loader/{array.rb → hash.rb} +1 -1
- data/lib/twig/node/expression/name.rb +2 -7
- data/lib/twig/runtime/context.rb +18 -0
- data/lib/twig/token_parser/yield.rb +10 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e727b10dc2226c2da43a9a2b8e1cd4a2e1b5a18ffb16eca116611b0d0f307cf
|
4
|
+
data.tar.gz: ef48d56a8bef43bd999cd17dc3def1371b58c12e4fba6c6bb143ba8b21dba6c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cbec5dd395ca0c306ab6eee643aa5954e46cd3181985e55fac994a2eecbdc4473aaba91a344e9681ad1aa28be3e77980461da775a740e908ec2dbb2fdbf73dc
|
7
|
+
data.tar.gz: fa32c024631b8cb528fb35463422b09e8b461ed75c1ef440bc4ccd8268686d928bcad868a82b9f98d5621a1e99047b2c4949589d7d967de23bcdf4ebe2b192ad
|
data/README.md
CHANGED
@@ -2,11 +2,105 @@
|
|
2
2
|
|
3
3
|
Implementation of [Twig](https://twig.symfony.com/) in Ruby.
|
4
4
|
|
5
|
+
## Table of Contents
|
6
|
+
|
7
|
+
- [Installation](#installation)
|
8
|
+
- [Quick Start](#quick-start)
|
9
|
+
- [Template Features](#template-features)
|
10
|
+
- [Filters](#filters)
|
11
|
+
- [Functions](#functions)
|
12
|
+
- [Tests](#tests)
|
13
|
+
- [Tags](#tags)
|
14
|
+
- [Rails Integration](#rails-integration)
|
15
|
+
- [Advanced Features](#advanced-features)
|
16
|
+
- [Configuration](#configuration)
|
17
|
+
- Advanced Docs
|
18
|
+
- [Loaders](doc/loaders.md)
|
19
|
+
- [Extensions](doc/extensions.md)
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
5
23
|
```bash
|
6
|
-
bundle add
|
24
|
+
bundle add twig_ruby
|
25
|
+
```
|
26
|
+
|
27
|
+
## Quick Start
|
28
|
+
|
29
|
+
Here's a simple example to get you started:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
require 'twig_ruby'
|
33
|
+
|
34
|
+
# Create a loader with your templates
|
35
|
+
loader = Twig::Loader::Hash.new({
|
36
|
+
'hello.twig' => 'Hello {{ name }}!'
|
37
|
+
})
|
38
|
+
|
39
|
+
# Create environment and render
|
40
|
+
environment = Twig::Environment.new(loader)
|
41
|
+
template = environment.load('hello.twig')
|
42
|
+
puts template.render({ name: "World" })
|
43
|
+
# Output: Hello World!
|
44
|
+
```
|
45
|
+
|
46
|
+
Or from your file system:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
loader = Twig::Loader::Filesystem.new(__dir__, ['app/views'])
|
50
|
+
```
|
51
|
+
|
52
|
+
## Template Features
|
53
|
+
|
54
|
+
Twig has the notion of Filters, Functions, and Tests
|
55
|
+
|
56
|
+
### Filters
|
57
|
+
|
58
|
+
Filters are used to modify variables.
|
59
|
+
|
60
|
+
```twig
|
61
|
+
{{ "hello"|capitalize }} {# Hello #}
|
62
|
+
{{ ["Hello", "World"]|join(" ") }} {# Hello World #}
|
63
|
+
```
|
64
|
+
|
65
|
+
### Functions
|
66
|
+
|
67
|
+
Functions are used to generate content.
|
68
|
+
|
69
|
+
```twig
|
70
|
+
{{ max([1, 2, 3]) }} {# 3 #}
|
71
|
+
{{ include("other.twig") }} {# contents of other.twig #}
|
7
72
|
```
|
8
73
|
|
9
|
-
|
74
|
+
### Tests
|
75
|
+
|
76
|
+
Tests are used to evaluate variables.
|
77
|
+
|
78
|
+
```twig
|
79
|
+
{{ 2 is even ? 'yup' : 'nope' }} {# yup #}
|
80
|
+
{{ ([1, 2, 3] has some n => n % 2 == 0) ? 'yup' : 'nope' }} {# yup #}
|
81
|
+
```
|
82
|
+
|
83
|
+
### Tags
|
84
|
+
|
85
|
+
Tags are used to control the logic of the template.
|
86
|
+
|
87
|
+
```twig
|
88
|
+
{% if n > 1 %}
|
89
|
+
Some
|
90
|
+
{% else %}
|
91
|
+
None
|
92
|
+
{% endif %}
|
93
|
+
```
|
94
|
+
|
95
|
+
```twig
|
96
|
+
<ul>
|
97
|
+
{% for i in [1, 2, 3] %}
|
98
|
+
<li>Item {{ i }}</li>
|
99
|
+
{% endfor %}
|
100
|
+
</ul>
|
101
|
+
```
|
102
|
+
|
103
|
+
## Rails Integration
|
10
104
|
|
11
105
|
This gem includes a Railtie that will automatically add your views folder and
|
12
106
|
register a `:twig` template handler. Just simply create your views such as
|
@@ -22,7 +116,14 @@ register a `:twig` template handler. Just simply create your views such as
|
|
22
116
|
{% endblock %}
|
23
117
|
```
|
24
118
|
|
25
|
-
|
119
|
+
Since Twig supports layouts through template inheritance (which is more flexible than Rails layouts),
|
120
|
+
you'll typically want to use Twig's inheritance system instead of Rails layouts. This allows you to:
|
121
|
+
|
122
|
+
1. Create a base template with common structure
|
123
|
+
2. Override specific blocks in child templates
|
124
|
+
3. Nest layouts for more complex page structures
|
125
|
+
|
126
|
+
To use Twig's inheritance instead of Rails layouts, disable Rails layouts in your controller:
|
26
127
|
|
27
128
|
```ruby
|
28
129
|
class ApplicationController < ActionController::Base
|
@@ -30,20 +131,21 @@ class ApplicationController < ActionController::Base
|
|
30
131
|
end
|
31
132
|
```
|
32
133
|
|
33
|
-
##
|
134
|
+
## Configuration
|
34
135
|
|
35
136
|
These are all the defaults. You only need this configuration if you plan to change anything.
|
36
137
|
|
37
138
|
```ruby
|
38
139
|
Rails.application.configure do
|
39
|
-
config.twig.root = ::Rails.root
|
40
|
-
config.twig.paths = %w[/ app/views/]
|
41
|
-
config.twig.debug = ::Rails.env.development
|
42
|
-
config.twig.allow_helper_methods = true
|
43
|
-
config.twig.cache = ::Rails.root.join('tmp/cache/twig').to_s
|
44
|
-
config.twig.charset = 'UTF-8'
|
45
|
-
config.twig.strict_variables = true
|
46
|
-
config.twig.
|
140
|
+
config.twig.root = ::Rails.root # Used for default Filesystem Loader
|
141
|
+
config.twig.paths = %w[/ app/views/] # Used for default Filesystem Loader
|
142
|
+
config.twig.debug = ::Rails.env.development?
|
143
|
+
config.twig.allow_helper_methods = true
|
144
|
+
config.twig.cache = ::Rails.root.join('tmp/cache/twig').to_s
|
145
|
+
config.twig.charset = 'UTF-8'
|
146
|
+
config.twig.strict_variables = true
|
147
|
+
config.twig.autoescape = :name
|
148
|
+
config.twig.auto_reload = nil
|
47
149
|
config.twig.loader = lambda do
|
48
150
|
::Twig::Loader::Filesystem.new(
|
49
151
|
current.root,
|
@@ -66,7 +168,7 @@ end
|
|
66
168
|
If you plan to create your own loader that loads templates from another source like the database, you can provide
|
67
169
|
a different lamba in the config for initializing it.
|
68
170
|
|
69
|
-
##
|
171
|
+
## Advanced Features
|
70
172
|
|
71
173
|
Twig Ruby supports symbols as Ruby does and can be used in places strings can as
|
72
174
|
hash keys, arguments, etc.
|
@@ -85,6 +187,14 @@ can be used with helpers like `form_with`
|
|
85
187
|
{{ f.email_field(:email) }}
|
86
188
|
{% endyield %}
|
87
189
|
```
|
190
|
+
|
191
|
+
Rails helpers can also be called. Parenthesis is only required when passing arguments:
|
192
|
+
|
193
|
+
```twig
|
194
|
+
{{ stylesheet_link_tag(:app, "data-turbo-track": "reload") }}
|
195
|
+
{{ javascript_importmap_tags }}
|
196
|
+
```
|
197
|
+
|
88
198
|
### Cache Tag
|
89
199
|
|
90
200
|
The way the `cache` tag works in Rails is that it captures output from the buffer that
|
@@ -96,7 +206,7 @@ Using `{% yield cache() do %}` WILL NOT WORK CORRECTLY.
|
|
96
206
|
```twig
|
97
207
|
{% cache(product) %}
|
98
208
|
...
|
99
|
-
{%
|
209
|
+
{% endcache %}
|
100
210
|
```
|
101
211
|
|
102
212
|
Macros can also use Ruby notation for default values:
|
data/lib/tasks/twig_parity.rake
CHANGED
@@ -150,7 +150,7 @@ class TwigFixture
|
|
150
150
|
replace(template, replacements[:fixture]) + (' ' * index)
|
151
151
|
end
|
152
152
|
|
153
|
-
loader = ::Twig::Loader::
|
153
|
+
loader = ::Twig::Loader::Hash.new(gsub_templates)
|
154
154
|
environment = ::Twig::Environment.new(loader, {
|
155
155
|
cache: false,
|
156
156
|
strict_variables: true,
|
data/lib/twig/environment.rb
CHANGED
data/lib/twig/extension/core.rb
CHANGED
@@ -997,7 +997,7 @@ module Twig
|
|
997
997
|
(object.respond_to?(:empty?) && object.empty?) ||
|
998
998
|
(object.respond_to?(:length) && (object.length&.== 0)) || # rubocop:disable Style/ZeroLengthPredicate
|
999
999
|
(object.respond_to?(:size) && (object.size&.== 0)) || # rubocop:disable Style/ZeroLengthPredicate
|
1000
|
-
(object.respond_to?(:to_s) && (object.to_s
|
1000
|
+
(object.respond_to?(:to_s) && (object.to_s == ''))
|
1001
1001
|
end
|
1002
1002
|
|
1003
1003
|
# @param [Environment] environment
|
@@ -30,13 +30,8 @@ module Twig
|
|
30
30
|
|
31
31
|
compiler.add_debug_info(self)
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
get = "context.call_context.instance_variable_get('#{name}')"
|
36
|
-
else
|
37
|
-
check = "context.key?(:#{name})"
|
38
|
-
get = "context[:#{name}]"
|
39
|
-
end
|
33
|
+
check = "context.has?(:#{name})"
|
34
|
+
get = "context.get(:#{name})"
|
40
35
|
|
41
36
|
if define_test_enabled?
|
42
37
|
if attributes[:always_defined] || SPECIAL_VARS.key?(name)
|
data/lib/twig/runtime/context.rb
CHANGED
@@ -52,6 +52,24 @@ module Twig
|
|
52
52
|
self.class.new(other, call_context:, output_buffer:)
|
53
53
|
end
|
54
54
|
|
55
|
+
def has?(name)
|
56
|
+
if name[0] == '@'
|
57
|
+
call_context.instance_variable_defined?(name)
|
58
|
+
else
|
59
|
+
key?(name) || call_context.respond_to?(name)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def get(name)
|
64
|
+
if name[0] == '@'
|
65
|
+
call_context.instance_variable_get(name)
|
66
|
+
elsif key?(name)
|
67
|
+
self[name]
|
68
|
+
elsif call_context.respond_to?(name)
|
69
|
+
call_context.send(name)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
55
73
|
def push_stack
|
56
74
|
stack.push({ remove: [], replace: {} })
|
57
75
|
end
|
@@ -27,6 +27,16 @@ module Twig
|
|
27
27
|
body = parser.subparse(method(:decide_yield_end), drop_needle: true)
|
28
28
|
stream.expect(Token::BLOCK_END_TYPE)
|
29
29
|
|
30
|
+
# If it's a context variable, turn it into a helper method
|
31
|
+
# ex: {% yield turbo_frame_tag do %}
|
32
|
+
if expr.is_a?(Node::Expression::Variable::Context)
|
33
|
+
expr = Node::Expression::HelperMethod.new(
|
34
|
+
expr.attributes[:name],
|
35
|
+
Node::Nodes.new({}),
|
36
|
+
lineno
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
30
40
|
Node::Yield.new(expr, body, arguments, lineno)
|
31
41
|
end
|
32
42
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twig_ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Craig Blanchette
|
8
8
|
- Fabian Potencier
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -84,10 +84,10 @@ files:
|
|
84
84
|
- lib/twig/extension_set.rb
|
85
85
|
- lib/twig/file_extension_escaping_strategy.rb
|
86
86
|
- lib/twig/lexer.rb
|
87
|
-
- lib/twig/loader/array.rb
|
88
87
|
- lib/twig/loader/base.rb
|
89
88
|
- lib/twig/loader/chain.rb
|
90
89
|
- lib/twig/loader/filesystem.rb
|
90
|
+
- lib/twig/loader/hash.rb
|
91
91
|
- lib/twig/node/auto_escape.rb
|
92
92
|
- lib/twig/node/base.rb
|
93
93
|
- lib/twig/node/block.rb
|
@@ -220,7 +220,7 @@ files:
|
|
220
220
|
- lib/twig_ruby.rb
|
221
221
|
homepage: https://rubygems.org/gems/twig-ruby
|
222
222
|
licenses:
|
223
|
-
-
|
223
|
+
- BSD-3-Clause
|
224
224
|
metadata:
|
225
225
|
allowed_push_host: https://rubygems.org
|
226
226
|
rubygems_mfa_required: 'true'
|