tina4ruby 3.13.88 → 3.13.89

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8878ff3cfcfe50696d437b251a372f66d99a8098707e7cfd919554ec24d996fb
4
- data.tar.gz: dbc5ae0b61c125a88fda3310d7dff72e0bb5a5d52d94ae863455ff607c5aab35
3
+ metadata.gz: c9a4969bc3af1b2a6f203d215043c4fb9497aa40e71a0f7d1c17d92eddeecea3
4
+ data.tar.gz: 67a4a34e48ca3e167201ab06ac5cab96be36b4f4224a97f04cae0c58f700184c
5
5
  SHA512:
6
- metadata.gz: b51a87207d60bff1cd55241e23eb3b7325980752430bfef840ed8fce8e1ba491fbdf4096dd8369548112163ec40147b5e70874b3d6b66c174d82a5161e3f2062
7
- data.tar.gz: 8b03d0f03526f60931fefafdf78f21e84b3e85dfb040af5106a1a7c26677e110fc21a2274b8d623bbbab60c23ba70661d8612ae02c43f024d29e02a82ca5e167
6
+ metadata.gz: a89938265a10f5b8f0a48966f370c55006937a236285fe6b8f2fd9c5f75464d5c4fc0fc65cf1583f76539e24cd095701e3c092d87fb9d1197978d1d9774f552c
7
+ data.tar.gz: af228d8eebfab34598468e44f6962ac701280d4ad1207e4184f2eee6aabc631c5dda36753de7c99b1e8aea4dde7cff635fa2c44c30fff469532124cab0d9f11a
data/lib/tina4/frond.rb CHANGED
@@ -143,6 +143,26 @@ module Tina4
143
143
  IMPORT_AS_RE = /\Aimport\s+["'](.+?)["']\s+as\s+(\w+)/
144
144
  CACHE_RE = /\Acache\s+["'](.+?)["']\s*(\d+)?/
145
145
  SPACELESS_RE = />\s+</
146
+
147
+ # Every tag that OPENS a construct. An unknown tag is a typo, and 3.13.89
148
+ # makes it raise rather than render its body: a mistyped guard --
149
+ # {% iff is_admin %} instead of {% if is_admin %} -- used to render the gated
150
+ # content UNCONDITIONALLY, so a reviewer saw a guard that was not there. Twig
151
+ # and Jinja2 both raise on an unknown tag; Frond now does too. There is no
152
+ # user-extension point for tags in any of the four frameworks, so an unknown
153
+ # name is always a mistake, never a plugin.
154
+ KNOWN_TAGS = %w[
155
+ autoescape block cache extends for from if import include live macro raw set
156
+ spaceless
157
+ ].freeze
158
+
159
+ # Terminators and branch keywords. These reach the tag dispatch only when
160
+ # stray (their own collector consumes them in the normal case), and a stray
161
+ # one keeps the old render-nothing behaviour -- see the comment at the raise.
162
+ TERMINATOR_TAGS = %w[
163
+ elif else elseif endautoescape endblock endcache endfor endif endlive
164
+ endmacro endraw endset endspaceless
165
+ ].freeze
146
166
  AUTOESCAPE_RE = /\Aautoescape\s+(false|true)/
147
167
  STRIPTAGS_RE = /<[^>]+>/
148
168
  THOUSANDS_RE = /(\d)(?=(\d{3})+(?!\d))/
@@ -713,8 +733,17 @@ module Tina4
713
733
  result, i = handle_for(tokens, i, context)
714
734
  output << result
715
735
  when "set"
716
- handle_set(content, context)
717
- i += 1
736
+ # An assignment has an "="; without one this is the BLOCK form,
737
+ # {% set name %}...{% endset %}, which captures its rendered body.
738
+ # A bare include? is exact here, not a shortcut: the block form's tag
739
+ # content is only ever "set <name>", so an "=" anywhere -- even inside
740
+ # a quoted value like {% set m = "a = b" %} -- means assignment.
741
+ if content.include?("=")
742
+ handle_set(content, context)
743
+ i += 1
744
+ else
745
+ i = handle_set_block(tokens, i, context)
746
+ end
718
747
  when "include"
719
748
  if @sandbox && @allowed_tags && !@allowed_tags.include?("include")
720
749
  i += 1
@@ -746,6 +775,15 @@ module Tina4
746
775
  i += 1
747
776
  else
748
777
  i += 1
778
+ unless tag.empty? || TERMINATOR_TAGS.include?(tag)
779
+ raise ArgumentError,
780
+ %(Frond: unknown tag "#{tag}" -- known tags are: #{KNOWN_TAGS.sort.join(", ")})
781
+ end
782
+ # An empty tag ({% %}) or a stray terminator (an {% endif %} with
783
+ # no {% if %}): no output.
784
+ # Malformed, but it has always rendered nothing, and nothing is the
785
+ # safe answer -- unlike an unknown tag it cannot expose content that
786
+ # was meant to be gated.
749
787
  end
750
788
 
751
789
  if strip_a && i < tokens.length && tokens[i][0] == TEXT
@@ -2344,6 +2382,48 @@ module Tina4
2344
2382
  )
2345
2383
  end
2346
2384
 
2385
+ # {% set name %}...{% endset %} -- render the body and bind it.
2386
+ #
2387
+ # Emits nothing itself. The captured value is a SafeString because it is
2388
+ # template output that has already been escaped on the way in; re-escaping it
2389
+ # at {{ name }} would double-encode every entity. Twig and Jinja2 both mark
2390
+ # the capture safe. Returns the index just past {% endset %}.
2391
+ def handle_set_block(tokens, start, context)
2392
+ content, _, _ = strip_tag(tokens[start][1])
2393
+ name = (content.split[1] || "").strip
2394
+
2395
+ body_tokens = []
2396
+ i = start + 1
2397
+ depth = 0
2398
+ while i < tokens.length
2399
+ if tokens[i][0] == BLOCK
2400
+ tc, _, _ = strip_tag(tokens[i][1])
2401
+ tag = tc.split[0] || ""
2402
+ if tag == "set" && !tc.include?("=")
2403
+ depth += 1
2404
+ body_tokens << tokens[i]
2405
+ elsif tag == "endset"
2406
+ if depth.zero?
2407
+ i += 1
2408
+ break
2409
+ end
2410
+ depth -= 1
2411
+ body_tokens << tokens[i]
2412
+ else
2413
+ body_tokens << tokens[i]
2414
+ end
2415
+ else
2416
+ body_tokens << tokens[i]
2417
+ end
2418
+ i += 1
2419
+ end
2420
+
2421
+ unless name.empty?
2422
+ context[name] = Tina4::SafeString.new(render_tokens(body_tokens.dup, context))
2423
+ end
2424
+ i
2425
+ end
2426
+
2347
2427
  def handle_spaceless(tokens, start, context)
2348
2428
  body_tokens = []
2349
2429
  i = start + 1
data/lib/tina4/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tina4
4
- VERSION = "3.13.88"
4
+ VERSION = "3.13.89"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tina4ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.88
4
+ version: 3.13.89
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tina4 Team