---
title: "Feature: Core content elements"
manual: "Frontend Theme for Extension Development"
version: "main"
source: "Changelog/2.0/Feature-CoreContentElements.rst"
modified: "2026-09-17T04:52:50+00:00"
---

# Feature: Core content elements

## Description

The theme now renders the rest of the classic content element set:

| Content element | Rendered |
| --- | --- |
| **Text & Images** | **Images**, positioned beside **Text**. |
| **Text & Media** | The same, from the **Media** field, which is not restricted to images. |
| **Bullet List** | **Text** as a list, unordered, ordered or a definition list, per **Type of list**. |
| **Table** | **Text** as a table, honouring caption, delimiter, enclosure, header position and footer. |
| **File Links** | The **Files** and **Collections** fields as a file list - name, optional size, optional thumbnail. |
| **Insert Records** | The referenced records, rendered exactly as they render on their own. |
| **Divider** | A horizontal rule. |
| **HTML** | **Text**, unescaped. |

Together with **Header**, **Text** and **Images**
([Feature: Content element rendering](Feature-ContentElementRendering.html#feature-content-element-rendering),
[Feature: Rendering of the Images element](Feature-ImageContentElementRendering.html#feature-image-content-element-rendering)), every classic content
element `EXT:frontend` registers now renders, except the eleven menu
elements - tracked separately, they need a `MenuProcessor` configured
per menu type rather than only a template.

No TCA of this extension's own is added for any of them. Every one of these
elements was already creatable in the backend before this change - their TCA
comes from `EXT:frontend`, on TYPO3 v13.4 and v14 alike, and
`fluid_styled_content` is not a dependency of this theme on either version
\- so what changes is only that they now render instead of TYPO3's own "no
rendering definition" notice.

## Two elements needed a decision

### **Table**

**Text** for **Table** is delimited text, and the delimiter
and enclosure fields are stored as TCA character **codes**, not characters.
Neither core data processor is enough on its own: `SplitProcessor`
splits on one delimiter into a flat list, with no nesting and no quoting;
`CommaSeparatedValueProcessor` is built for exactly this field but has
no stdWrap property that turns a numeric code into a character, and does not
shape a header row, a header column or a footer row.

`SBUERKThemeExtensionDevelopmentDataProcessingTableProcessor` does
the decode and the shaping. One PHP detail is worth knowing if this class is
ever touched: the enclosure field's own **default** is "None" (code `0`),
and PHP's `fgetcsv()` throws a `ValueError` when handed an empty
enclosure string - which is what the TYPO3 backend's own table wizard falls
back to for that same "None" option. `chr(0)` is used instead, so the
field's default configuration does not throw.

### **Insert Records**

**Insert Records** renders other content elements, through the
core's `RECORDS` cObject configured with
`conf.tt_content =< tt_content` \- a referenced record renders
through the very same object this theme builds for every content element,
including, if it is itself an **Insert Records** element, going
through this same branch again.

> [!WARNING]
> Whether that recursion is guarded depends on the TYPO3 version. On
> v13.4, the core's own `TypoScriptFrontendController->recordRegister`
> skips a record that is already being rendered - a self-reference or an
> indirect cycle is caught, and the offending reference alone is silently
> dropped, not the rest of the element. On v14, that guard is gone:
> `TypoScriptFrontendController` (and the property with it) was
> removed entirely in v14.0. No guard of this extension's own was added,
> which means a self-referencing or cyclically referencing
> **Insert Records** element is unguarded on v14 and will recurse
> until PHP's own nesting limit ends the request with a fatal error. See
> `docs/architecture/content-elements.md` for the verification
> against both installed core versions.

## Escaping

Table cells, bullet items, the table caption and file names/descriptions are
plain Fluid interpolation, HTML-escaped. **Text & Images** and
**Text & Media** run their **Text** field through
`f:format.html` (the RTE parse), the same as the existing **Text**
element. **HTML** is the one deliberate exception: `f:format.raw`,
completely unescaped - not `f:format.html`, which would parse it and
change it. Access to **HTML** is restricted the same way as every
`CType`: the field carries `authMode = explicitAllow`, and it is a site
administration decision, not something this theme enforces, which backend
groups are actually granted it.

## Impact

An installation using the theme no longer renders the TYPO3 "no rendering
definition" notice for any of the elements listed above.
`Tests/Functional/CoreContentElementRenderingTest.php` sweeps every
covered `CType` and fails if any of them regresses to the notice.

The markup is generated from the templates below
`Resources/Private/Templates/ContentElements/`, redirected together
with every other template through the Fluid path constants under
`theme.` \- see [Configuration](../../Configuration/Index.html#configuration). See
`docs/architecture/content-elements.md` in the developer documentation
for the full coverage table, the
`bullets_type`/`table_*`/`uploads_type` field-by-field reasoning, and
the recursion finding above.
