From 954eb9379a5a1efa7673ddc2bb6accc11aa425af Mon Sep 17 00:00:00 2001 From: David Steeb Date: Wed, 29 Jul 2026 19:28:05 +0200 Subject: [PATCH 1/5] [FEATURE] Add "P" and "span" as header type options Editors sometimes need a header that is visually styled but must not appear in the document heading outline, for example a large intro line that should stay a plain paragraph for accessibility and SEO. Adds the values 7 (p) and 8 (span) to both the header type and the subheader type field. The matching labels already existed in the language file and are now actually used. --- Configuration/TCA/Overrides/tt_content.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php index da5630c..0b0a04b 100644 --- a/Configuration/TCA/Overrides/tt_content.php +++ b/Configuration/TCA/Overrides/tt_content.php @@ -37,6 +37,14 @@ 'label' => 'LLL:EXT:headertypes/Resources/Private/Language/locallang.xlf:type.I.h6', 'value' => 6, ], + [ + 'label' => 'LLL:EXT:headertypes/Resources/Private/Language/locallang.xlf:type.I.p', + 'value' => 7, + ], + [ + 'label' => 'LLL:EXT:headertypes/Resources/Private/Language/locallang.xlf:type.I.span', + 'value' => 8, + ], ], ], ], @@ -75,6 +83,14 @@ 'label' => 'LLL:EXT:headertypes/Resources/Private/Language/locallang.xlf:type.I.h6', 'value' => 6, ], + [ + 'label' => 'LLL:EXT:headertypes/Resources/Private/Language/locallang.xlf:type.I.p', + 'value' => 7, + ], + [ + 'label' => 'LLL:EXT:headertypes/Resources/Private/Language/locallang.xlf:type.I.span', + 'value' => 8, + ], ], ], ], From 60e5d0fb613d661e7c51c1a3f80f91e7dbfd7faf Mon Sep 17 00:00:00 2001 From: David Steeb Date: Wed, 29 Jul 2026 19:28:05 +0200 Subject: [PATCH 2/5] [TASK] Clean up XLIFF language file Fixes the invalid file date (an impossible "+13:13" timezone offset), adds the standard XLIFF file attributes and aligns the indentation and ordering of the trans-units. --- Resources/Private/Language/locallang.xlf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 88be125..1380287 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -1,6 +1,6 @@ - + Header Type @@ -11,6 +11,9 @@ Layout + + Default + H1 @@ -29,14 +32,11 @@ H6 - - P - - - Span - - - Default + + P + + + Span From e7af6e2a08da516a18979560a95016e814757d50 Mon Sep 17 00:00:00 2001 From: David Steeb Date: Wed, 29 Jul 2026 19:28:05 +0200 Subject: [PATCH 3/5] [DOCS] Rewrite README in b13 style The README only contained a credits note and did not explain what the extension does or that it is backend-only: without a template override in the site package nothing is rendered in the frontend. Rewrites it following the structure of our other b13 extension READMEs (container, picture) with features, rationale, installation, a field reference and a Fluid rendering example. --- README.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f77bf7d..39752bf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,96 @@ -# EXT:headertypes +![CI](https://github.com/b13/headertypes/actions/workflows/ci.yml/badge.svg) + +# EXT:headertypes - Separate the semantic header type from the header layout + +## Features + +- Adds a dedicated **Header Type** field to content elements to control the semantic HTML tag (`

`–`

`) of a header +- Adds a matching **Subheader Type** field for the subheader +- Decouples the *semantics* of a heading from its *visual appearance* +- Renames the TYPO3 Core "Header Layout" field to the clearer label **Layout** so editors understand it only affects styling +- Ships as a lightweight, backend-only extension: it adds the fields, your site package renders them +- Supports TYPO3 v12.4, v13 and v14 from a single extension version + +## Why did we create this extension? + +TYPO3 Core ships a single `header_layout` field for content headers. That one field is used for two very +different things at once: it decides both *how a header looks* and *which HTML tag* is rendered (`

` … `

`). + +In real projects those two concerns pull apart: + +- A header that should look like a large "H2" for design reasons might still need to be an `

` for a correct + document outline. +- Accessibility and SEO depend on a clean, hierarchical heading structure that editors should not be forced to + break just to achieve a certain look. +- Designers want freedom over typography without side effects on the semantic structure of the page. + +EXT:headertypes solves this by splitting the concern in two: + +- **Layout** (the existing `header_layout` field, relabeled) keeps controlling the *visual* appearance. +- **Header Type** / **Subheader Type** (the new fields) control the *semantic* HTML tag. + +This lets editors pick, for example, "looks like a Layout 2 heading, but is semantically an `

`" — cleanly and +without templating hacks. + +## Installation + +Install this extension via `composer req b13/headertypes` or download it from the +[TYPO3 Extension Repository](https://extensions.typo3.org/extension/headertypes/) and activate the extension in the +Extension Manager of your TYPO3 installation. + +## How it works + +The extension adds two select fields to the `tt_content` table: + +| Field | Purpose | Values | +|--------------------------------|-------------------------------|------------------------------------------------------------------------| +| `tx_headertypes_headertype` | Semantic tag of the header | `0` = Default, `1`–`6` = `h1`–`h6`, `7` = `p`, `8` = `span` | +| `tx_headertypes_subheadertype` | Semantic tag of the subheader | `0` = Default, `1`–`6` = `h1`–`h6`, `7` = `p`, `8` = `span` | + +Both fields are added to the Core `header` and `headers` palettes, so they appear directly next to the header input +in the backend for every content element that uses those palettes. The value `0` ("Default") means "do not override" — +your template should fall back to its normal header rendering in that case. + +The extension does **not** render anything in the frontend on its own. Rendering the chosen tag is the job of your +site package or theme, which keeps the extension unopinionated and compatible across TYPO3 versions. + +## Frontend rendering + +To make the new fields take effect, override the header partial in your site package (for +`fluid_styled_content` this is `Resources/Private/Partials/Header/Header.html`) and use +`tx_headertypes_headertype` to choose the tag, while keeping `header_layout` for the visual class. + +```html +EXT:my_sitepackage/Resources/Private/Partials/Header/Header.html + + +

{data.header}

+

{data.header}

+

{data.header}

+

{data.header}

+
{data.header}
+
{data.header}
+

{data.header}

+ {data.header} + + Header Type "Default" (0): fall back to your regular header_layout based rendering. + +
+
+``` + +The same principle applies to the subheader via `{data.tx_headertypes_subheadertype}`. + +## Compatibility + +| Extension version | TYPO3 versions | +|-------------------|-----------------------------| +| 1.x | v12.4, v13, v14 | ## Credits This extension was created by David Steeb in 2020 for [b13 GmbH, Stuttgart](https://b13.com). -[Find more TYPO3 extensions we have developed](https://b13.com/useful-typo3-extensions-from-b13-to-you) that help us deliver value in client projects. As part of the way we work, we focus on testing and best practices to ensure long-term performance, reliability, and results in all our code. +[Find more TYPO3 extensions we have developed](https://b13.com/useful-typo3-extensions-from-b13-to-you) that help us +deliver value in client projects. As part of the way we work, we focus on testing and best practices to ensure +long-term performance, reliability, and results in all our code. From e4f7cbfbd43f6be86ccf94b8d695919285723a44 Mon Sep 17 00:00:00 2001 From: David Steeb Date: Wed, 29 Jul 2026 19:28:05 +0200 Subject: [PATCH 4/5] [TASK] Add composer metadata and .gitattributes Adds the PHP requirement, authors, support links, keywords and package sorting to composer.json and excludes development files from the distribution archive via .gitattributes. --- .gitattributes | 3 +++ composer.json | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5e9e6fe --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +/.github export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/composer.json b/composer.json index b0f5c1f..41c3275 100644 --- a/composer.json +++ b/composer.json @@ -3,9 +3,26 @@ "type": "typo3-cms-extension", "description": "Add a separate header type field to tt_content for headers and subheaders", "license": ["GPL-2.0-or-later"], + "keywords": ["TYPO3 CMS", "header", "heading", "accessibility", "seo"], + "homepage": "https://b13.com", + "authors": [ + { + "name": "David Steeb", + "email": "typo3@b13.com", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/b13/headertypes/issues", + "source": "https://github.com/b13/headertypes" + }, "require": { + "php": "^8.1", "typo3/cms-core": "^12.4 || ^13.0 || ^14.0" }, + "config": { + "sort-packages": true + }, "extra": { "typo3/cms": { "extension-key": "headertypes" From 128abe62f6772177710a2dcfb9c06f5342ceff83 Mon Sep 17 00:00:00 2001 From: David Steeb Date: Wed, 29 Jul 2026 19:28:05 +0200 Subject: [PATCH 5/5] [TASK] Add GitHub Actions CI workflow Adds a lightweight CI pipeline that validates composer.json, lints all PHP files against PHP 8.1 to 8.3 and validates the XLIFF files, so the status badge in the README reflects a real workflow. --- .github/workflows/ci.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9093532 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + +jobs: + checks: + name: Checks (PHP ${{ matrix.php }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['8.1', '8.2', '8.3'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer:v2 + coverage: none + + - name: Validate composer.json + run: composer validate --strict + + - name: Lint PHP files + run: find . -name '*.php' -path './.git' -prune -o -name '*.php' -print0 | xargs -0 -n1 -P4 php -l + + - name: Lint XLIFF files + run: | + sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libxml2-utils + find . -name '*.xlf' -print0 | xargs -0 -r -n1 xmllint --noout