To simplify parsing logic, improve parsing performance and avoid confusion with many new adopters, all tags are now of a single format, differentiated by a token or a set of tokens which appear before a string which identifies the Content Element or Content Tag to be processed; e.g. [[tokenIdentifier]].
Tag Format Changes for Content Elements and Content Tags
| Content Elements | Evolution (Old) | Revolution (New) | Example for Revolution |
|
|---|---|---|---|---|
| Templates | no tag representation | no tag representation | ||
| Resource Fields | [*field*] | [[*field]] |
[[*pagetitle]] | |
| Template Variables | [*templatevar*] | [[*templatevar]] | [[*tags]] |
|
| Chunks | {{chunk }} |
[[$chunk]] | [[$header]] |
|
| Snippets | [[snippet]] | [[snippet]] | [[getResources]] |
|
| Plugins | no tag representation | no tag representation | ||
| Modules | no tag representation | does not exist in Revolution, use CMPs | ||
| Content Tags | ||||
| Placeholders | [+placeholder+] |
[[+placeholder]] | [[+modx.user.id]] |
|
| Links | [~link~] | [[~link]] | [[~[[*id]]? &scheme=`full`]] |
|
| System Settings | [(system_setting)] | [[++system_setting]] | [[++site_start]] |
|
| Language | no tag representation | [[%language_string_key]] | ||
| Comment (see note below) |
[[-this is a comment]] |
Adopting this simplified format allows the new parser to be fully-recursive, following a source-order mechanism that does not depend on regular expressions.
Previously, each tag set was parsed independently in a specific order, one level at a time, with any embedded tags delayed until the next pass. Now tags are parsed as they are encountered regardless of the element types they represent, and embedded tags are parsed before the outer tag to allow much more complex tags to be composed. Combined with the ability to use the previously reserved ? & and = symbols in tag strings (when escaped by the infamous backtick, e.g. ¶m=`?=&is ok now, wow!?&=`), MODx Content Tags offer a powerful new set of capabilities for mashing up your content.
Comment tags
This discussion on the forums shows that some people feel the need for a comments tag. The default behavior when encountering a tag that represents an element that does not exist, is to silently discard the tag completely. Utilizing this behavior you can add comments throughout your templates, chunks and content and none of it would be visible on the front-end.
As of MODX Revolution 2.2 any tag found that starts with a dash (-) is ignored by the parser, and any tags it includes will be silently discarded. Before that, you can use the same however any tags within the commend would be parsed and it would be a tad more resource intensive to do so.
[[- This is a comment, and will be removed from the output. ]]
Structure of a Tag
A tag can contain many sub-parts within it. Below is illustrated on multiple lines a tag broken down into each part and explained:
[[ (opening tags)
! (optional non-cacheable flag)
elementToken (optional token identifying the element type if it's not a snippet, $=chunk, *=resource field/tv, +=placeholder, etc.)
elementName
@propertyset (optional PropertySet identifier)
:filterName=`modifier`:... (optional one or more output filters)
? (optional; indicates beginning of property string)
&propertyName=`propertyValue` &... (optional; any additional properties separated by &)
]] (closing tags)
Note that tags can occur either on one line, or spread out across many lines. Both of these are acceptable:
[[!getResources? &parents=`123` &limit=`5`]] [[!getResources? &parents=`123` &limit=`5` ]]
Properties
All tags - no longer just Snippets - now accept properties, as well, that can be used. For example, let's say we had a Chunk named 'Hello' with the content:
Hello [[+name]]!
You'll note the new placeholder syntax. So, we'll definitely want to parse that Chunk's property. In Evolution, you would need to do this with a Snippet; no longer. You can simply pass a property for the Chunk:
[[$Hello?name=`George`]]
This would output:
Hello George!
The syntax for properties follows the same syntax as 096/Evolution snippet properties.
Caching
In Evolution, Snippets that need to be processed with each request should be on an uncached page or the Snippet itself should be called uncached: [!snippet!]
In Revolution, any tag can be called uncached by inserting an exclamation point immediately after the double-bracket: [[!snippet]], [[!$chunk]], [[!+placeholder]], [[!*template_var]], etc.
?
| If you have some kind of advanced setup in which the site_url setting is being set per request, but your [[~[[*id]]]] links are not being generated properly, remember that any tag can be called uncached, including the link or anchor tag:
[[!~[[*id]]]] However, you will only need that when the site_url is set dynamically and can differ per request. Any normal usage can be cached. |
Parsing Order
If you call an uncached Snippet, it will be executed last in the parsing order.
If you have cached placeholders below that, they will be evaluated before that Snippet is executed - meaning they'll get the last value that was stored in the cache by that Snippet previously (or empty, if not set yet).
If you want to call a Snippet uncached that sets placeholders, you need to make sure the placeholders are set to uncached as well:
[[!Profile]] Hello [[!+username]],
Additional Help
Because the tag syntax is problematic for many newcomers, there are tools available to help highlight problems. Check out the SyntaxChecker plugin.