Skip to content

Latest commit

 

History

History
67 lines (42 loc) · 3.24 KB

File metadata and controls

67 lines (42 loc) · 3.24 KB

Twig Parity Progress

Tracks implementation of missing PHP Twig features relative to the parity table in README.md. Phases group independent items that can be worked on in parallel.


Phase 1 — Pure filter additions

No parser work required. Each filter is independent and follows the existing filter pattern.

  • find filter (3.11+) — first element matching an arrow function predicate; effectively filter returning only the first result
  • shuffle filter (3.11+) — randomize array order
  • invoke filter (3.19+) — call an arrow function value as a filter (e.g. {{ fn|invoke(arg) }})
  • data_uri filter — encode content as a base64 data: URI; optionally accept a MIME type argument
  • slug filter (3.3+) — URL-safe slug; decide on Unicode normalization strategy (e.g. slugify, native Intl, or regex-based)

Phase 2 — New operators

Each is an independent parser + node + executor addition. Light touch — no existing behaviour changes.

  • === / !== strict equality (3.23+) — reuse the comparison logic from the same as test
  • xor logical operator (3.15+) — logical exclusive OR; bitwise b-xor already exists as a template
  • ?. null-safe attribute access (3.23+) — return null instead of throwing when the left-hand side is null

Phase 3 — Missing tests

Each test is a standalone addition with no parser changes.

  • sequence test — is an indexed (non-associative) array
  • mapping test — is an associative array / object
  • instanceof test (3.15+) — checks class inheritance; note sandbox implications

Phase 4 — Language syntax

Requires non-trivial parser changes. Destructuring variants share infrastructure and are best tackled together.

  • = assignment expression (3.23+) — assign within expression context ({% do x = 1 %}, {{ result = fn() }}, chained a = b = v)
  • Sequence destructuring (3.23+){% do [a, b] = arr %} with skip slots and null padding for short arrays
  • Object destructuring (3.23+){% do {name, email} = user %} with key-based extraction

Phase 5 — New tags

Each tag is independent. types is simpler (no runtime effect); guard requires a feature-registry concept.

  • types tag (3.13+) — static type declarations; no runtime effect, compile-time / IDE metadata only
  • guard tag (3.15+) — compile-time feature detection ({% guard filter markdown_to_html %}…{% else %}…{% endguard %})

Phase 6 — Complex / deferred

Higher effort, external dependencies, or JS adaptation not yet scoped.

  • u filter — returns a Unicode proxy object with ~15 methods (truncate, wordwrap, normalize, camel, snake, etc.); effectively a small string library
  • enum function + enum_cases function (3.12+) — PHP enum access; JS has no native enums, so an adapter/registry approach is needed
  • cache tag (3.2+) — fragment caching with TTL and tag-based invalidation; needs a cache adapter interface
  • Inline expression comments # … (3.15+) — lexer change to allow {{ value # comment }}
  • Number literals with _ separator (3.17+)1_000_000, 3.141_592; lexer change only