167 lines
6.6 KiB
ReStructuredText
167 lines
6.6 KiB
ReStructuredText
.. include:: /Includes.rst.txt
|
|
|
|
.. _feature-97816-1656350667:
|
|
|
|
================================================
|
|
Feature: #97816 - TypoScript syntax improvements
|
|
================================================
|
|
|
|
See :issue:`97816`
|
|
|
|
Description
|
|
===========
|
|
|
|
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 :ref:`breaking-97816-1656350406`
|
|
for an overview of breaking syntax changes.
|
|
|
|
Impact
|
|
======
|
|
|
|
Improved comment parsing
|
|
------------------------
|
|
|
|
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 (:typoscript:`*/`) on a single line to close the comment
|
|
section has been removed.
|
|
|
|
A couple of examples to clarify:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
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!
|
|
|
|
@import in conditions
|
|
---------------------
|
|
|
|
Placing an :typoscript:`@import` keyword within a condition is now supported,
|
|
the example below works. Note this obsoletes the clumsy :typoscript:`<INCLUDE_TYPOSCRIPT:`
|
|
syntax, and integrators are encouraged to fully switch to :typoscript:`@import`.
|
|
|
|
.. code-block:: typoscript
|
|
|
|
[frontend.user.isLoggedIn]
|
|
@import 'EXT:my_extension/Configuration/TypoScript/LoggedInUser.typoscript'
|
|
[ELSE]
|
|
@import 'EXT:my_extension/Configuration/TypoScript/NotLoggedInUser.typoscript'
|
|
[END]
|
|
|
|
Scope restriction to file / snipped level
|
|
-----------------------------------------
|
|
|
|
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 :typoscript:`}` in one file do not destroy block
|
|
integrity of a following include anymore. Same for conditions: A missing closing
|
|
condition block (:typoscript:`[END]` or :typoscript:`[GLOBALS]`) no longer leaks
|
|
to another file - a conditions ends at the end of a file or snippet.
|
|
|
|
Nesting conditions is partially supported
|
|
-----------------------------------------
|
|
|
|
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:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
[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: :file:`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 :file:`LoggedInUserDevelopment.typoscript` is only
|
|
included if a user is logged in *and* the application is in development context.
|
|
|
|
.. code-block:: typoscript
|
|
|
|
[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]
|
|
|
|
Irrelevant order of <INCLUDE_TYPOSCRIPT: tokens
|
|
-----------------------------------------------
|
|
|
|
The :typoscript:`<INCLUDE_TYPOSCRIPT:` keywords has the three properties
|
|
:typoscript:`source`, :typoscript:`condition` and :typoscript:`extensions`. They had to
|
|
be in a specific order with the old parser, but can be placed in arbitrary order now.
|
|
|
|
Further clarifications
|
|
----------------------
|
|
|
|
* The "reference" :typoscript:`=<` operator is not a direct language construct. The parser
|
|
understands the syntax, but does not resolve it. Allowed :typoscript:`=<` operator are very
|
|
limited: In general, it can *only* be used for Frontend Content Objects, typically like this:
|
|
:typoscript:`tt_content.bullets =< lib.contentElement`. Another usage is referencing :typoscript:`lib.parseFunc`.
|
|
Using the :typoscript:`=<` 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, namely :php:`ContentObjectRenderer->cObjGetSingle()` and
|
|
:php:`ContentObjectRenderer->mergeTSRef()`.
|
|
This also means: The :typoscript:`=<` 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
|
|
with :typoscript:`20 < .10` and similar.
|
|
|
|
* The new parser has a minor change in behavior with the "copy" :typoscript:`<` operator on top-level.
|
|
This shouldn't have huge impact in real life usage and is documented for completeness. Consider this
|
|
example:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
lib.viewConfig {
|
|
baz = bazValue
|
|
}
|
|
|
|
first = FLUIDTEMPLATE
|
|
first < lib.viewConfig
|
|
|
|
The situation is there that :typoscript:`lib.viewConfig` has no assigned value (just children). The
|
|
target :typoscript:`first` however has value :typoscript:`FLUIDTEMPLATE`. The old TypoScript parser
|
|
usually keeps the "target" value in such cases, but only if the TypoScript object is not on top level
|
|
(:typoscript:`first` in contrast to :typoscript:`first.10` or similar). In the example above, value
|
|
:typoscript:`FLUIDTEMPLATE` would vanish with the old parser, but is now kept with the new parser.
|
|
|
|
.. index:: Backend, Frontend, TSConfig, TypoScript, ext:core
|