Placeholder substitution for Neos CMS: replaces {{variable}} placeholders in
rendered content with values configured via Fusion. Ships with a Neos UI
richtext editor plugin that lets editors insert placeholders from a searchable
dropdown in the CKEditor toolbar.
composer require networkteam/neos-contentsubstitutionThe package provides the Fusion object Networkteam.Neos:ContentSubstitution,
which replaces all placeholders matching a configurable pattern (default:
{{...}}) in a string with values from its variables map:
prototype(Networkteam.Neos:ContentSubstitution) {
value = ${value}
pattern = '/\{\{(.*?)\}\}/'
variables = Neos.Fusion:DataStructure
}
- Unknown placeholders are left untouched (the original
{{...}}text is kept). - Substitution only happens in the
liveworkspace — in the backend, editors see the raw placeholder, making it obvious that a substitution will happen. - Variable names are trimmed, so
{{ myVariable }}and{{myVariable}}are equivalent.
By default the substitution is applied to the whole body of every page via a
@process on Neos.Neos:Page:
prototype(Neos.Neos:Page) {
body.@process.networkteamContentSubstitution = Networkteam.Neos:ContentSubstitution
}
Declare the available variables and their values in your site package's Fusion:
prototype(Networkteam.Neos:ContentSubstitution) {
variables {
companyName = 'ACME Inc.'
supportMail = ${Configuration.setting('Vendor.Site.supportMail')}
}
}
Values are evaluated per request with node in context, so they can depend on
the current dimension, site, or any other context.
To offer editors a dropdown for inserting placeholders in a richtext editor, list the variable names in the frontend configuration:
Neos:
Neos:
Ui:
frontendConfiguration:
'Networkteam.Neos.ContentSubstitution':
variables:
- companyName
- supportMailEntries can also be objects with a separate human-readable label shown in the
dropdown (the value is what gets inserted as {{value}}):
variables:
- value: 'company.name'
label: 'Company name'and enable the feature per property via editorOptions:
'Vendor.Site:Content.Text':
properties:
text:
ui:
inline:
editorOptions:
contentSubstitution: trueThe Networkteam.Neos:Placeholder prototype renders a placeholder string, e.g.
for use in templates that should be substituted later:
placeholder = Networkteam.Neos:Placeholder {
variable = 'companyName'
}
Networkteam.Neos:ContentSubstitution can be applied as a @process to any
string value, as long as node is in context:
title = ${q(node).property('title')}
title.@process.contentSubstitution = Networkteam.Neos:ContentSubstitution
For PHP-based rendering (e.g. a custom Fusion implementation), declare the
object as a sub-path of your prototype and evaluate it per value with the
runtime — see the Fusion object's value property, which can be fed from any
context variable.
The editor plugin sources live in
Resources/Private/Scripts/ContentSubstitutionEditor. Rebuild the bundle with:
yarn install
yarn build # requires NODE_OPTIONS=--openssl-legacy-provider on Node >= 17The build output is committed to Resources/Public/ContentSubstitution.
GPL-2.0-or-later, see LICENSE.