990 lines
22 KiB
Markdown
990 lines
22 KiB
Markdown
# FirstSpirit Template Syntax - Instructions Reference
|
|
|
|
## Overview
|
|
|
|
FirstSpirit template instructions are special tags that enable dynamic content generation, control flow, variable manipulation, and template composition. All instructions follow the pattern `$CMS_...(...)$` where the content inside the brackets is always an expression.
|
|
|
|
### Key Characteristics
|
|
|
|
- **Structure**: Begin with `$CMS_` and end with `)$`
|
|
- **Expression-based**: Content within brackets is evaluated as expressions
|
|
- **Nesting**: Support unlimited nesting depth for complex logic
|
|
- **Block syntax**: Complex instructions use opening/closing tag pairs (e.g., `$CMS_SET(...)$ ... $CMS_END_SET$`)
|
|
- **Parameters**: Multiple parameters separated by commas using `IDENTIFIER:"VALUE"` format
|
|
|
|
### Critical Limitation
|
|
|
|
Expressions within `<CMS_HEADER>` tags remain unresolved - this is one of the main sources of errors in template development.
|
|
|
|
---
|
|
|
|
## Complete Instruction List
|
|
|
|
FirstSpirit provides the following core instructions:
|
|
|
|
- **$CMS_VALUE** - Output variable values and expressions
|
|
- **$CMS_SET** - Define variables and assign values
|
|
- **$CMS_IF** - Conditional output based on criteria
|
|
- **$CMS_FOR** - Loop and iteration control
|
|
- **$CMS_SWITCH** - Multi-case conditional branching
|
|
- **$CMS_RENDER** - Render templates and execute scripts
|
|
- **$CMS_INCLUDE** - Include external file content
|
|
- **$CMS_REF** - Resolve references to store objects
|
|
- **$CMS_TRIM** - Remove unnecessary whitespace
|
|
|
|
---
|
|
|
|
## $CMS_VALUE
|
|
|
|
### Purpose
|
|
|
|
Outputs variable contents, input component values, and expression results within templates, making them visible in browsers.
|
|
|
|
### Syntax
|
|
|
|
```
|
|
$CMS_VALUE(VARIABLE)$
|
|
$CMS_VALUE(CONSTANT)$
|
|
$CMS_VALUE(EXPRESSION)$
|
|
$CMS_VALUE(OBJECT1, default:OBJECT2)$
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- **VARIABLE/CONSTANT/EXPRESSION**: Required. The value to output.
|
|
- **default**: Optional. Fallback content when the primary value is undefined.
|
|
|
|
### Features
|
|
|
|
**Variable Output with Dot Notation:**
|
|
```
|
|
$CMS_VALUE(myVariable.attributeName)$
|
|
```
|
|
|
|
**Expression Evaluation:**
|
|
```
|
|
$CMS_VALUE(myNumber + 2)$
|
|
$CMS_VALUE(6 * 7)$ <!-- Outputs: 42 -->
|
|
```
|
|
|
|
**Default Values:**
|
|
```
|
|
$CMS_VALUE(VARIABLENAME, default:"--VALUE NOT SET--")$
|
|
```
|
|
|
|
**Method Invocation:**
|
|
```
|
|
$CMS_VALUE(characterstring.contains("text"))$
|
|
$CMS_VALUE("1" == "1")$ <!-- Outputs: true -->
|
|
$CMS_VALUE(true || false)$ <!-- Outputs: true -->
|
|
```
|
|
|
|
### Best Practices
|
|
|
|
**Error Prevention:**
|
|
Always test for null/empty values before output:
|
|
|
|
```
|
|
$CMS_IF(!VARIABLE.isNull)$
|
|
$CMS_VALUE(VARIABLE)$
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**Checking Methods:**
|
|
- `.isNull()` - Test for null values
|
|
- `.isEmpty()` - Check if empty
|
|
- `.isSet()` - Check if defined (use cautiously)
|
|
|
|
**Caution**: While `isSet()` and default parameters suppress errors, they may complicate debugging and risk unintended output on generated pages.
|
|
|
|
---
|
|
|
|
## $CMS_SET
|
|
|
|
### Purpose
|
|
|
|
Enables variable definition within templates and assigns values to variables. Supports both immediate object allocation and deferred template fragment execution.
|
|
|
|
### Syntax
|
|
|
|
**Variant 1 - Object Allocation (Immediate Execution):**
|
|
```
|
|
$CMS_SET(IDENTIFIER, OBJECT)$
|
|
```
|
|
|
|
**Variant 2 - Template Fragment (Deferred Execution):**
|
|
```
|
|
$CMS_SET(IDENTIFIER)$
|
|
BODY OF THE TEMPLATE FRAGMENT
|
|
$CMS_END_SET$
|
|
```
|
|
|
|
Multiple variables can be defined in a single statement using comma separation.
|
|
|
|
### Parameters
|
|
|
|
- **IDENTIFIER**: Required. Variable name containing only A-Z, a-z, 0-9, and underscore characters.
|
|
- **OBJECT**: Required for Variant 1. Can be a constant, variable, or expression.
|
|
- **BODY**: Required for Variant 2. Template fragment content that executes when the variable is evaluated.
|
|
|
|
### Supported Instructions in Body
|
|
|
|
Template fragment bodies support:
|
|
- `$CMS_IF(...)$`
|
|
- `$CMS_REF(...)$`
|
|
- `$CMS_SET(...)$`
|
|
- `$CMS_VALUE(...)$`
|
|
|
|
### Critical Restrictions
|
|
|
|
- Neither IDENTIFIER nor OBJECT parameters may contain `$CMS_VALUE(...)$` expressions
|
|
- Using an identifier within its own template fragment body causes infinite loops
|
|
- Variant 1 executes immediately at definition
|
|
- Variant 2 defers execution until variable evaluation
|
|
|
|
### Usage Examples
|
|
|
|
**Simple Variable Assignment:**
|
|
```
|
|
$CMS_SET(myVariable, "Hello World")$
|
|
$CMS_SET(count, 42)$
|
|
```
|
|
|
|
**Expression Resolution:**
|
|
```
|
|
$CMS_SET(result, (5 + 3).toString)$
|
|
```
|
|
|
|
**Creating Collections:**
|
|
```
|
|
$CMS_SET(mySet, { })$ <!-- Empty set -->
|
|
$CMS_SET(myList, [])$ <!-- Empty list -->
|
|
$CMS_SET(myList, ["item1", "item2", "item3"])$
|
|
```
|
|
|
|
**Language-Dependent Values:**
|
|
Use maps to store multilingual content indexed by language abbreviations:
|
|
```
|
|
$CMS_SET(greetings, {
|
|
"en": "Welcome",
|
|
"de": "Willkommen",
|
|
"fr": "Bienvenue"
|
|
})$
|
|
```
|
|
|
|
**Template Fragments:**
|
|
Template fragments execute body code when called, allowing dynamic value reassignment:
|
|
```
|
|
$CMS_SET(dynamicContent)$
|
|
<p>Generated at: $CMS_VALUE(#global.now)$</p>
|
|
$CMS_END_SET$
|
|
```
|
|
|
|
---
|
|
|
|
## $CMS_IF
|
|
|
|
### Purpose
|
|
|
|
Checks a comparable value for 'true' or 'false' and controls output depending on the determined value. Enables conditional logic in templates.
|
|
|
|
### Syntax
|
|
|
|
**Basic Structure:**
|
|
```
|
|
$CMS_IF(CONDITION)$
|
|
EXECUTION PART (FULFILLED CONDITION)
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**With Else Clause:**
|
|
```
|
|
$CMS_IF(CONDITION)$
|
|
EXECUTION PART (FULFILLED)
|
|
$CMS_ELSE$
|
|
EXECUTION PART (UNFULFILLED)
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**With Multiple Conditions:**
|
|
```
|
|
$CMS_IF(CONDITION_1)$
|
|
EXECUTION PART (FULFILLED CONDITION_1)
|
|
$CMS_ELSIF(CONDITION_2)$
|
|
EXECUTION PART (FULFILLED CONDITION_2)
|
|
$CMS_ELSIF(CONDITION_3)$
|
|
EXECUTION PART (FULFILLED CONDITION_3)
|
|
$CMS_ELSE$
|
|
EXECUTION PART (UNFULFILLED CONDITIONS)
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
### Parameters
|
|
|
|
**CONDITION**: Required. A boolean expression consisting of:
|
|
1. Variable or constant
|
|
2. Operator (optional)
|
|
3. Comparable value (optional)
|
|
|
|
### Valid Conditions
|
|
|
|
```
|
|
1 == 1
|
|
a != b
|
|
count > 10
|
|
#global.preview
|
|
myVariable.isEmpty()
|
|
```
|
|
|
|
### Features
|
|
|
|
- Supports nested conditions of any depth
|
|
- `$CMS_ELSIF(...)$` combines else and if functionality
|
|
- Boolean-returning methods require no operator or comparable value
|
|
- Multiple `$CMS_ELSE$` and `$CMS_ELSIF$` tags allowed
|
|
|
|
### Examples
|
|
|
|
**Simple Condition:**
|
|
```
|
|
$CMS_IF(!myVariable.isNull)$
|
|
$CMS_VALUE(myVariable)$
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**With Else:**
|
|
```
|
|
$CMS_IF(#global.preview)$
|
|
<div class="preview-mode">Preview Mode Active</div>
|
|
$CMS_ELSE$
|
|
<div class="live-mode">Live Mode</div>
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**Multiple Conditions:**
|
|
```
|
|
$CMS_IF(userRole == "admin")$
|
|
<button>Edit</button>
|
|
<button>Delete</button>
|
|
$CMS_ELSIF(userRole == "editor")$
|
|
<button>Edit</button>
|
|
$CMS_ELSE$
|
|
<span>Read-only access</span>
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**Nested Conditions:**
|
|
```
|
|
$CMS_IF(!user.isNull)$
|
|
$CMS_IF(user.isActive)$
|
|
Welcome, $CMS_VALUE(user.name)$!
|
|
$CMS_ELSE$
|
|
Your account is inactive.
|
|
$CMS_END_IF$
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
---
|
|
|
|
## $CMS_FOR
|
|
|
|
### Purpose
|
|
|
|
Enables loop implementation within FirstSpirit templates for iterating over collections, lists, maps, and number ranges. Available since FirstSpirit 4.0, replacing the iterative functionality previously handled by `$CMS_RENDER(...)$`.
|
|
|
|
### Syntax
|
|
|
|
```
|
|
$CMS_FOR(IDENTIFIER, OBJECT)$
|
|
LOOP BODY
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- **IDENTIFIER**: Required. Variable name representing the current object during each iteration.
|
|
- **OBJECT**: Required. A set-valued element to iterate over.
|
|
|
|
### Object Types
|
|
|
|
**Number Set (Integers Only):**
|
|
```
|
|
[STARTVALUE .. ENDVALUE]
|
|
```
|
|
|
|
**List:**
|
|
```
|
|
[OBJECT_1, OBJECT_2, ..., OBJECT_N]
|
|
```
|
|
|
|
**Map:**
|
|
```
|
|
{KEY_1: VALUE_1, ..., KEY_N: VALUE_N}
|
|
```
|
|
|
|
### System Object: #for
|
|
|
|
Within the loop body, the `#for` system object provides metadata:
|
|
|
|
- **#for.index**: Current iteration count (zero-based)
|
|
|
|
### Examples
|
|
|
|
**Iterating Over a List:**
|
|
```
|
|
$CMS_FOR(item, ["apple", "banana", "cherry"])$
|
|
<li>$CMS_VALUE(item)$</li>
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
**Number Range Iteration:**
|
|
```
|
|
$CMS_FOR(num, [7 .. 14])$
|
|
<div>Number: $CMS_VALUE(num)$</div>
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
**Using Loop Index:**
|
|
```
|
|
$CMS_FOR(product, productList)$
|
|
<div class="product-$CMS_VALUE(#for.index)$">
|
|
$CMS_VALUE(product.name)$
|
|
</div>
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
**Map Iteration:**
|
|
```
|
|
$CMS_FOR(entry, languageMap)$
|
|
<p>
|
|
Language: $CMS_VALUE(entry.key)$
|
|
Translation: $CMS_VALUE(entry.value)$
|
|
</p>
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
**Complex List Iteration:**
|
|
```
|
|
$CMS_FOR(page, #global.node.children)$
|
|
$CMS_IF(!page.isNull && page.isReleased)$
|
|
<a href="$CMS_REF(page)$">$CMS_VALUE(page.displayName)$</a>
|
|
$CMS_END_IF$
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
### Intended Uses
|
|
|
|
- Outputting lists and complex elements
|
|
- Executing instructions iteratively
|
|
- Generating repetitive HTML structures
|
|
- Processing collections and datasets
|
|
|
|
---
|
|
|
|
## $CMS_SWITCH
|
|
|
|
### Purpose
|
|
|
|
Enables conditional output based on multiple possible values of a single variable, functioning as a case-differentiation mechanism within FirstSpirit templates.
|
|
|
|
### Syntax
|
|
|
|
```
|
|
$CMS_SWITCH(OBJECT)$
|
|
STANDARDEXECUTIONPART
|
|
$CMS_CASE(CONDITION_1)$
|
|
EXECUTIONPART_1
|
|
$CMS_CASE(CONDITION_2)$
|
|
EXECUTIONPART_2
|
|
...
|
|
$CMS_CASE(CONDITION_N)$
|
|
EXECUTIONPART_N
|
|
$CMS_END_SWITCH$
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- **OBJECT**: Required. The value being evaluated. Can be a constant, variable, expression, or method call.
|
|
- **CONDITION**: Required for each case. The value to match against. Can be a constant, variable, expression, or class definition.
|
|
|
|
### Evaluation Logic
|
|
|
|
The instruction compares each `$CMS_CASE(...)$` condition sequentially against the provided object. When a match occurs, its corresponding execution block runs. If no conditions match, the default section (content before the first case) executes.
|
|
|
|
### Default Case Handling
|
|
|
|
Content preceding the first `$CMS_CASE(...)$` block serves as the default, executing when no case conditions match:
|
|
|
|
```
|
|
$CMS_SWITCH(value)$
|
|
Default content here
|
|
$CMS_CASE("option1")$
|
|
Option 1 content
|
|
$CMS_CASE("option2")$
|
|
Option 2 content
|
|
$CMS_END_SWITCH$
|
|
```
|
|
|
|
### Examples
|
|
|
|
**Language-Dependent Output:**
|
|
```
|
|
$CMS_SWITCH(#global.language.abbreviation.toLowerCase)$
|
|
Welcome!
|
|
$CMS_CASE("de")$
|
|
Willkommen!
|
|
$CMS_CASE("en")$
|
|
Welcome!
|
|
$CMS_CASE("fr")$
|
|
Bienvenue!
|
|
$CMS_END_SWITCH$
|
|
```
|
|
|
|
**Type Checking:**
|
|
```
|
|
$CMS_SWITCH(_var)$
|
|
Unknown type
|
|
$CMS_CASE(class("java.lang.String"))$
|
|
This is a String
|
|
$CMS_CASE(class("java.math.BigInteger"))$
|
|
This is an Integer
|
|
$CMS_CASE(class("java.lang.Boolean"))$
|
|
This is a Boolean
|
|
$CMS_END_SWITCH$
|
|
```
|
|
|
|
**User Role Handling:**
|
|
```
|
|
$CMS_SWITCH(user.role)$
|
|
<span>Guest</span>
|
|
$CMS_CASE("admin")$
|
|
<button>Admin Panel</button>
|
|
$CMS_CASE("editor")$
|
|
<button>Edit Content</button>
|
|
$CMS_CASE("viewer")$
|
|
<span>View Only</span>
|
|
$CMS_END_SWITCH$
|
|
```
|
|
|
|
**Status-Based Styling:**
|
|
```
|
|
$CMS_SWITCH(orderStatus)$
|
|
$CMS_CASE("pending")$
|
|
<span class="status-pending">Pending</span>
|
|
$CMS_CASE("shipped")$
|
|
<span class="status-shipped">Shipped</span>
|
|
$CMS_CASE("delivered")$
|
|
<span class="status-delivered">Delivered</span>
|
|
$CMS_CASE("cancelled")$
|
|
<span class="status-cancelled">Cancelled</span>
|
|
$CMS_END_SWITCH$
|
|
```
|
|
|
|
---
|
|
|
|
## $CMS_RENDER
|
|
|
|
### Purpose
|
|
|
|
Used within a template to evaluate another output channel at the calling point, integrate the content of a format template, or call a script. Provides template composition and script execution capabilities.
|
|
|
|
### Syntax
|
|
|
|
**Template Rendering:**
|
|
```
|
|
$CMS_RENDER(template:"IDENTIFIER", PARAM_1:VALUE_1, ...)$
|
|
```
|
|
|
|
**Script Execution:**
|
|
```
|
|
$CMS_RENDER(script:"IDENTIFIER", PARAM_1:VALUE_1, ...)$
|
|
```
|
|
|
|
**Output Channel Inclusion:**
|
|
```
|
|
$CMS_RENDER(#this, templateSet:"IDENTIFIER", pinTemplateSet:BOOLEAN)$
|
|
```
|
|
|
|
### Parameters
|
|
|
|
**Required (Mutually Exclusive):**
|
|
- **template**: Format template identifier for integration
|
|
- **script**: Template-type script identifier created in the project
|
|
- **#this**: Reference to current template for output channel rendering
|
|
|
|
**Optional:**
|
|
- **templateSet**: Identifies which output channel to render
|
|
- **pinTemplateSet**: Boolean controlling channel context behavior (default: true)
|
|
- `true`: Nested template calls remain in the specified channel
|
|
- `false`: Nested calls revert to the original channel
|
|
- **User-defined parameters**: Custom values passed as `IDENTIFIER:VALUE` pairs
|
|
|
|
### Important Constraints
|
|
|
|
- The identifiers `template`, `script`, or `version` should not be used for user-specified parameters
|
|
- Template and script parameters are mandatory when used
|
|
- All other parameters remain optional
|
|
|
|
### Context Behavior
|
|
|
|
`$CMS_RENDER` creates isolated contexts, preventing external variable overwrites - unlike `$CMS_VALUE` calls, which operate within existing scopes.
|
|
|
|
### Examples
|
|
|
|
**Render a Format Template:**
|
|
```
|
|
$CMS_RENDER(template:"header", pageTitle:"Home Page", showNav:true)$
|
|
```
|
|
|
|
**Execute a Script:**
|
|
```
|
|
$CMS_RENDER(script:"calculateTotals", items:cartItems, taxRate:0.08)$
|
|
```
|
|
|
|
**Output Another Channel:**
|
|
```
|
|
$CMS_RENDER(#this, templateSet:"print")$
|
|
```
|
|
|
|
**Render with Custom Parameters:**
|
|
```
|
|
$CMS_RENDER(
|
|
template:"product-card",
|
|
product:currentProduct,
|
|
showPrice:true,
|
|
currency:"USD"
|
|
)$
|
|
```
|
|
|
|
**Pinned Template Set:**
|
|
```
|
|
$CMS_RENDER(#this, templateSet:"mobile", pinTemplateSet:true)$
|
|
```
|
|
|
|
---
|
|
|
|
## $CMS_INCLUDE
|
|
|
|
### Purpose
|
|
|
|
Inserts contents of a file from the Media Store into a template. Useful for including static content, external files, or reusable content fragments.
|
|
|
|
### Syntax
|
|
|
|
```
|
|
$CMS_INCLUDE(
|
|
IDENTIFIER,
|
|
parse:BOOLEAN_VALUE,
|
|
encoding:ENCODING,
|
|
language:LANGUAGEABBREVIATION
|
|
)$
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- **IDENTIFIER**: Required. Object reference using format `type:"name"` or variable name
|
|
- `media:"filename"` - Files/pictures from Media Store
|
|
- `file:"filename"` - Files from Media Store
|
|
- **parse**: Optional. Controls FirstSpirit expression processing
|
|
- `true`: Expressions are replaced
|
|
- `false`: Expressions remain unchanged
|
|
- Default: Uses file's Media Store setting
|
|
- **encoding**: Optional. Character encoding for output
|
|
- Accepts any Java-supported charset
|
|
- Default: Uses file's Media Store setting
|
|
- **lang/language**: Optional. Project language version
|
|
- Accepts language abbreviation in quotes (e.g., `"DE"`, `"EN"`)
|
|
- Alternative: Pass language instance like `#global.project.masterLanguage`
|
|
- Useful for language-dependent media
|
|
|
|
### Key Behavioral Differences
|
|
|
|
**Parsed (parse:true):**
|
|
Variable references within included files get evaluated and replaced with actual values.
|
|
|
|
**Unparsed (parse:false):**
|
|
FirstSpirit expressions remain as literal text in output.
|
|
|
|
### Examples
|
|
|
|
**Basic File Inclusion:**
|
|
```
|
|
$CMS_INCLUDE(media:"header.html")$
|
|
```
|
|
|
|
**With Parsing Enabled:**
|
|
```
|
|
$CMS_INCLUDE(media:"template-fragment.html", parse:true)$
|
|
```
|
|
|
|
**Specific Encoding:**
|
|
```
|
|
$CMS_INCLUDE(file:"content.txt", encoding:"UTF-8")$
|
|
```
|
|
|
|
**Language-Specific Media:**
|
|
```
|
|
$CMS_INCLUDE(
|
|
media:"welcome-message.html",
|
|
language:"DE",
|
|
parse:true
|
|
)$
|
|
```
|
|
|
|
**Using Variable Reference:**
|
|
```
|
|
$CMS_SET(includedFile, mediaReference)$
|
|
$CMS_INCLUDE(includedFile, parse:false)$
|
|
```
|
|
|
|
**Master Language Content:**
|
|
```
|
|
$CMS_INCLUDE(
|
|
media:"global-footer.html",
|
|
language:#global.project.masterLanguage,
|
|
parse:true
|
|
)$
|
|
```
|
|
|
|
---
|
|
|
|
## $CMS_REF
|
|
|
|
### Purpose
|
|
|
|
Resolves references to objects stored across FirstSpirit's separate stores (Page Store, Media Store, Site Store, Template Store) into usable paths for browsers and processors.
|
|
|
|
### Syntax
|
|
|
|
```
|
|
$CMS_REF(
|
|
IDENTIFIER,
|
|
abs:VALUE,
|
|
contentId:VALUE,
|
|
index:VALUE,
|
|
lang:"LANGUAGE",
|
|
postfix:IDENTIFIER,
|
|
remote:IDENTIFIER,
|
|
res:"RESOLUTION",
|
|
template:IDENTIFIER,
|
|
templateSet:"CHANNEL",
|
|
version:NUMBER
|
|
)$
|
|
```
|
|
|
|
Only IDENTIFIER is mandatory; all other parameters are optional.
|
|
|
|
### Parameters
|
|
|
|
**IDENTIFIER (Required):**
|
|
References objects by type and name:
|
|
- `media:"filename"` - Media Store files/pictures
|
|
- `pageref:"name"` - Site Store pages/document groups
|
|
- `pagefolder:"name"` - Site Store menu levels
|
|
- Supports variable names and method invocations
|
|
|
|
**abs (Path Control):**
|
|
- `abs:0` - Relative paths (default)
|
|
- `abs:1` - Absolute with prefix
|
|
- `abs:2` - Absolute without prefix
|
|
- `abs:3` - Internal processor URLs
|
|
- `abs:4` - External processor URLs
|
|
|
|
**lang/language:**
|
|
Specifies project language (e.g., `"DE"`, `"EN"`)
|
|
|
|
**res/resolution:**
|
|
Designates image resolution other than original (e.g., `"SCALED"`, `"100_HOCH"`)
|
|
|
|
**contentId:**
|
|
Retrieves URL for specific dataset by ID in content projections
|
|
|
|
**index:**
|
|
Determines URL for specific sub-page in multi-page projections
|
|
|
|
**postfix:**
|
|
Attempts reference with suffix first, then falls back to unsuffixed version
|
|
|
|
**remote:**
|
|
Links to Remote project objects via symbolic name
|
|
|
|
**template:**
|
|
Restricts contentId search to specific table template UID
|
|
|
|
**templateSet/version:**
|
|
Switches between presentation channels (print versions, etc.)
|
|
|
|
### Important Constraints
|
|
|
|
- Do not nest `$CMS_REF(...)$` and `$CMS_VALUE(...)$` instructions
|
|
- Avoid numerical suffixes for postfix parameters to prevent reference name conflicts
|
|
- Remote media access requires valid licensing
|
|
- Different remote/target projects may have resolutions with identical names requiring careful specification
|
|
|
|
### Examples
|
|
|
|
**Basic Media Reference:**
|
|
```
|
|
<img src="$CMS_REF(media:"logo.png")$" alt="Logo">
|
|
```
|
|
|
|
**Page Reference:**
|
|
```
|
|
<a href="$CMS_REF(pageref:"about-us")$">About Us</a>
|
|
```
|
|
|
|
**Absolute Path:**
|
|
```
|
|
$CMS_REF(media:"stylesheet.css", abs:1)$
|
|
```
|
|
|
|
**Image with Resolution:**
|
|
```
|
|
<img src="$CMS_REF(media:"hero-image", res:"100_HOCH")$" alt="Hero">
|
|
```
|
|
|
|
**Language-Specific Reference:**
|
|
```
|
|
$CMS_REF(pageref:"homepage", lang:"DE")$
|
|
```
|
|
|
|
**Print Version:**
|
|
```
|
|
<a href="$CMS_REF(#global.node, templateSet:"print")$">Print Version</a>
|
|
```
|
|
|
|
**Dataset Reference:**
|
|
```
|
|
$CMS_REF(pageref:"products", contentId:374)$
|
|
```
|
|
|
|
**Remote Project Reference:**
|
|
```
|
|
$CMS_REF(media:"shared-asset", remote:"corporate-assets")$
|
|
```
|
|
|
|
**Current Page in Different Channel:**
|
|
```
|
|
$CMS_REF(#global.node, templateSet:"mobile")$
|
|
```
|
|
|
|
**Page Folder Navigation:**
|
|
```
|
|
$CMS_FOR(child, #global.node.parent.children)$
|
|
<a href="$CMS_REF(child)$">$CMS_VALUE(child.displayName)$</a>
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
---
|
|
|
|
## Control Flow and Logic Operations
|
|
|
|
### Conditional Logic Patterns
|
|
|
|
FirstSpirit provides multiple approaches for conditional logic:
|
|
|
|
**Simple Conditions:**
|
|
Use `$CMS_IF` for basic true/false decisions:
|
|
```
|
|
$CMS_IF(condition)$
|
|
Execute when true
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**Binary Choices:**
|
|
Use `$CMS_IF` with `$CMS_ELSE` for either/or scenarios:
|
|
```
|
|
$CMS_IF(condition)$
|
|
Option A
|
|
$CMS_ELSE$
|
|
Option B
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**Multiple Conditions:**
|
|
Use `$CMS_IF` with `$CMS_ELSIF` for sequential condition checking:
|
|
```
|
|
$CMS_IF(condition1)$
|
|
Result 1
|
|
$CMS_ELSIF(condition2)$
|
|
Result 2
|
|
$CMS_ELSIF(condition3)$
|
|
Result 3
|
|
$CMS_ELSE$
|
|
Default result
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**Multi-Case Branching:**
|
|
Use `$CMS_SWITCH` when checking a single value against multiple possibilities:
|
|
```
|
|
$CMS_SWITCH(value)$
|
|
Default case
|
|
$CMS_CASE(option1)$
|
|
Handle option 1
|
|
$CMS_CASE(option2)$
|
|
Handle option 2
|
|
$CMS_END_SWITCH$
|
|
```
|
|
|
|
### Loop Patterns
|
|
|
|
**Iterating Collections:**
|
|
```
|
|
$CMS_FOR(item, collection)$
|
|
Process $CMS_VALUE(item)$
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
**Number Ranges:**
|
|
```
|
|
$CMS_FOR(i, [1 .. 10])$
|
|
Iteration $CMS_VALUE(i)$
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
**Map Iteration:**
|
|
```
|
|
$CMS_FOR(entry, mapObject)$
|
|
Key: $CMS_VALUE(entry.key)$
|
|
Value: $CMS_VALUE(entry.value)$
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
**Conditional Loops:**
|
|
Combine loops with conditions:
|
|
```
|
|
$CMS_FOR(page, pages)$
|
|
$CMS_IF(!page.isNull && page.isReleased)$
|
|
<a href="$CMS_REF(page)$">$CMS_VALUE(page.displayName)$</a>
|
|
$CMS_END_IF$
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
### Variable Scope and Context
|
|
|
|
**Local Variables:**
|
|
Variables defined with `$CMS_SET` have local scope within their template context:
|
|
```
|
|
$CMS_SET(localVar, "value")$
|
|
```
|
|
|
|
**Template Fragments:**
|
|
Deferred execution for dynamic content:
|
|
```
|
|
$CMS_SET(fragment)$
|
|
Content with $CMS_VALUE(#global.now)$
|
|
$CMS_END_SET$
|
|
```
|
|
|
|
**Isolated Contexts:**
|
|
`$CMS_RENDER` creates isolated variable contexts preventing overwrites:
|
|
```
|
|
$CMS_RENDER(template:"subtemplate", param1:value1)$
|
|
```
|
|
|
|
### Common Patterns
|
|
|
|
**Null-Safe Output:**
|
|
```
|
|
$CMS_IF(!variable.isNull)$
|
|
$CMS_VALUE(variable)$
|
|
$CMS_ELSE$
|
|
Default content
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
**List Processing:**
|
|
```
|
|
$CMS_SET(items, [])$
|
|
$CMS_FOR(item, sourceList)$
|
|
$CMS_IF(item.isActive)$
|
|
$CMS_SET(items, items + [item])$
|
|
$CMS_END_IF$
|
|
$CMS_END_FOR$
|
|
```
|
|
|
|
**Language-Dependent Content:**
|
|
```
|
|
$CMS_SWITCH(#global.language.abbreviation)$
|
|
English content
|
|
$CMS_CASE("de")$
|
|
German content
|
|
$CMS_CASE("fr")$
|
|
French content
|
|
$CMS_END_SWITCH$
|
|
```
|
|
|
|
---
|
|
|
|
## Best Practices Summary
|
|
|
|
### Error Prevention
|
|
|
|
1. **Always check for null/empty values** before output
|
|
2. **Use conditional wrappers** around `$CMS_VALUE` calls
|
|
3. **Test expressions** with `.isNull()` and `.isEmpty()` methods
|
|
4. **Avoid `$CMS_VALUE` in `CMS_HEADER`** tags (expressions won't resolve)
|
|
|
|
### Variable Management
|
|
|
|
1. **Use descriptive identifiers** following naming conventions
|
|
2. **Avoid circular references** in template fragments
|
|
3. **Apply `.toString` method** to resolve expressions immediately when needed
|
|
4. **Create isolated contexts** with `$CMS_RENDER` to prevent variable conflicts
|
|
|
|
### Performance
|
|
|
|
1. **Prefer `$CMS_SWITCH`** over multiple nested `$CMS_IF` statements for multi-case logic
|
|
2. **Use template fragments** for deferred execution when appropriate
|
|
3. **Minimize nested instructions** where possible
|
|
4. **Cache complex expressions** in variables using `$CMS_SET`
|
|
|
|
### Code Organization
|
|
|
|
1. **Use meaningful parameter names** in `$CMS_RENDER` calls
|
|
2. **Break complex logic** into separate format templates
|
|
3. **Document template fragments** with comments
|
|
4. **Follow consistent indentation** for readability
|
|
|
|
### Reference Handling
|
|
|
|
1. **Don't nest `$CMS_REF` and `$CMS_VALUE`** instructions
|
|
2. **Use appropriate path modes** (abs parameter) for context
|
|
3. **Specify language explicitly** for multilingual sites
|
|
4. **Test remote references** with proper licensing
|
|
|
|
---
|
|
|
|
## Troubleshooting Common Issues
|
|
|
|
### Expressions Not Resolving
|
|
|
|
**Problem**: Variables show as literal text instead of values.
|
|
**Solution**: Ensure expressions are outside `<CMS_HEADER>` tags and use proper syntax.
|
|
|
|
### Infinite Loops
|
|
|
|
**Problem**: Template hangs during generation.
|
|
**Solution**: Check for self-referencing identifiers in template fragment bodies.
|
|
|
|
### Null Pointer Errors
|
|
|
|
**Problem**: Generation fails with null reference errors.
|
|
**Solution**: Add null checks before accessing object properties:
|
|
```
|
|
$CMS_IF(!object.isNull)$
|
|
$CMS_VALUE(object.property)$
|
|
$CMS_END_IF$
|
|
```
|
|
|
|
### Incorrect Context in Nested Templates
|
|
|
|
**Problem**: Variables from parent template overwrite child template variables.
|
|
**Solution**: Use `$CMS_RENDER` instead of `$CMS_INCLUDE` for proper context isolation.
|
|
|
|
### Reference Resolution Failures
|
|
|
|
**Problem**: `$CMS_REF` returns empty or incorrect paths.
|
|
**Solution**: Verify object exists, check store type matches reference type, ensure proper language/resolution parameters.
|