See 97816
TYPO3 v12 comes with a new TypoScript syntax parser that is more performant, more robust and allows better tooling in the Backend.
The new parser is more forgiving in many places, this documentation lists the new capabilities.
Also see breaking-97816-1656350406
for an overview of breaking syntax changes.
TypoScript comment detection had various nasty quirks with the old parser. The confusing behavior did lead to many headaches in the past and not sticking to the weird parser restrictions in comment parsing could easily lead to unexpected results, often ignoring bigger sections of the subsequent TypoScript lines.
This has been relaxed heavily: Comment detection should almost always act as developers and integrators would expect from a language. Especially the former obligation to place a closing multiline comment (*/
) on a single line to close the comment section has been removed.
A couple of examples to clarify:
foo # This is a comment to an invalid line
foo < bar // This is a comment
foo < bar /* This is a valid comment, too */
foo > # Another valid comment
foo := addToList(1) # Yes, a comment
[foo = bar] # Much comment. Much wow.
<INCLUDE_TYPOSCRIPT: source="..."> /* A comment */
foo (
# This is NOT a comment but part of the value assignment!
bar = barValue
) # This is a comment
foo = bar // This is NOT a comment but part of the value assignment!
Placing an @import
keyword within a condition is now supported, the example below works. Note that this obsoletes the clumsy <INCLUDE_TYPOSCRIPT:
syntax, and integrators are encouraged to fully switch to @import
.
[frontend.user.isLoggedIn]
@import 'EXT:my_extension/Configuration/TypoScript/LoggedInUser.typoscript'
[ELSE]
@import 'EXT:my_extension/Configuration/TypoScript/NotLoggedInUser.typoscript'
[END]
The old TypoScript parser merged the entire TypoScript for a page into one big chunk of text. The new parser does not do that anymore, but parses each included snippet one-by-one. This automatically means state no longer leaks to subsequent snippets. Missing closing brackets }
in one file do not destroy block integrity of a following include anymore. Same for conditions: A missing closing condition block ([END]
or [GLOBALS]
) no longer leaks to another file - a conditions ends at the end of a file or snippet.
Nesting conditions is partially possible with the new TypoScript parser, if the conditions are in different files. As example, let's first sort what happens when two conditions follow directly in one snippet:
[frontend.user.isLoggedIn]
@import 'EXT:my_extension/Configuration/TypoScript/LoggedInUser.typoscript'
[applicationContext == "Development"]
@import 'EXT:my_extension/Configuration/TypoScript/Development.typoscript'
[END]
This always worked and did not change with the new parser: Opening a new condition automatically closes the preceding one. In the example above, both conditions are standalone: Development.typoscript
is included no matter if a user is logged in or not.
But, and this in new, nesting conditions within different files is possible now. In the example below, file LoggedInUserDevelopment.typoscript
is only included if a user is logged in and the application is in development context.
[frontend.user.isLoggedIn]
@import 'EXT:my_extension/Configuration/TypoScript/LoggedInUser.typoscript'
[END]
# File LoggedInUser.typoscript:
[applicationContext == "Development"]
@import 'EXT:my_extension/Configuration/TypoScript/LoggedInUserDevelopment.typoscript'
[END]
The <INCLUDE_TYPOSCRIPT:
keywords has the three properties source
, condition
and extensions
. They had to be in a specific order with the old parser, but can be placed in arbitrary order now.
- The "reference"
=<
operator is not a direct language construct. The parser understands the syntax, but does not resolve it. Allowed=<
operator are very limited: In general, it can only be used for Frontend Content Objects, typically like this:tt_content.bullets =< lib.contentElement
. Another usage is referencinglib.parseFunc
. Using the=<
operator in these cases can have a performance advantage since it avoids an expensive copy operation that is done lazily if really needed. There are two methods that resolve this operator, namelyContentObjectRenderer->cObjGetSingle()
andContentObjectRenderer->mergeTSRef()
. This also means: The=<
operator is not supported in TypoScript constants, is only supported for specific elements in TypoScript setup, and is not supported in TSconfig. Also note the reference operator does not support "relative" copies like the "copy" operator supports with20 < .10
and similar. The new parser has a minor change in behavior with the "copy"
<
operator on top-level. This shouldn't have huge impact in real life usage and is documented for completeness. Consider this example:lib.viewConfig { baz = bazValue } first = FLUIDTEMPLATE first < lib.viewConfig
The situation is there that
lib.viewConfig
has no assigned value (just children). The targetfirst
however has valueFLUIDTEMPLATE
. The old TypoScript parser usually keeps the "target" value in such cases, but only if the TypoScript object is not on top level (first
in contrast tofirst.10
or similar). In the example above, valueFLUIDTEMPLATE
would vanish with the old parser, but is now kept with the new parser.
Backend, Frontend, TSConfig, TypoScript, ext:core