Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,54 @@ name: publish

on:
push:
tag:
tags:
- '*'

jobs:
publish:
name: Publish new version to TER
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
env:
TYPO3_EXTENSION_KEY: ${{ secrets.TYPO3_EXTENSION_KEY }}
TYPO3_API_TOKEN: ${{ secrets.TYPO3_API_TOKEN }}

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Check tag
run: |
if ! [[ ${{ github.ref }} =~ ^refs/tags/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then
if ! [[ ${{ github.ref }} =~ ^refs/tags/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
exit 1
fi

- name: Get version
id: get-version
run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//}
run: echo "version=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"

- name: Get comment
id: get-comment
run: |
readonly local comment=$(git tag -n10 -l ${{ steps.get-version.outputs.version }} | sed "s/^[0-9.]*[ ]*//g")
comment=$(git tag -n10 -l "${{ steps.get-version.outputs.version }}" | sed "s/^[0-9.]*[ ]*//g")
if [[ -z "${comment// }" ]]; then
echo ::set-output name=comment::Released version ${{ steps.get-version.outputs.version }} of ${{ env.TYPO3_EXTENSION_KEY }}
else
echo ::set-output name=comment::$comment
comment="Released version ${{ steps.get-version.outputs.version }} of ${{ env.TYPO3_EXTENSION_KEY }}"
fi
{
echo "comment<<EOF"
echo "$comment"
echo "EOF"
} >> "$GITHUB_OUTPUT"

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
php-version: '8.2'
extensions: intl, mbstring, json, zip, curl
tools: composer:v2

- name: Install tailor
run: composer global require typo3/tailor --prefer-dist --no-progress --no-suggest
run: composer global require typo3/tailor --prefer-dist --no-progress

- name: Publish to TER
run: php ~/.composer/vendor/bin/tailor ter:publish --comment "${{ steps.get-comment.outputs.comment }}" ${{ steps.get-version.outputs.version }}
run: php ~/.composer/vendor/bin/tailor ter:publish --comment "${{ steps.get-comment.outputs.comment }}" "${{ steps.get-version.outputs.version }}"
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Changelog

## 3.0.0 — Cleanup release for TYPO3 v13 and v14

### Breaking

- **Drops support for TYPO3 10, 11, and 12.** Minimum is now TYPO3 13.4.
- **Requires PHP 8.2 or newer.**
- **Delivery is now a Site Set.** Assign `b13/codeblock` to your site
(Sites module → tab *Sets for this Site*) instead of `@import`-ing
`EXT:codeblock/Configuration/TypoScript/setup.typoscript` and
`EXT:codeblock/Configuration/PageTs/PageTs.tsconfig`. The legacy file
paths no longer exist.

### Removed

- `ext_tables.sql` — the `code_language` column is now auto-created from
the TCA definition (TYPO3 v13+ feature).
- `ext_localconf.php` — the pre-v12 `tt_content_drawItem` hook and the
manual `IconRegistry` registration are gone. The icon is registered via
`Configuration/Icons.php`.
- `Classes/Hooks/CodeblockPreviewRenderer.php` — relied on the
`PageLayoutViewDrawItemHookInterface`, which was removed in TYPO3 v12.
- `Classes/Listener/PageContentPreviewRendering.php` — preview truncation
now happens inside `ContentPreviewRenderer::renderPageModulePreviewContent()`,
so the separate event listener is no longer needed.
- `Configuration/PageTs/PageTs.tsconfig` and
`Configuration/TypoScript/setup.typoscript` — moved into the Site Set.

### Changed

- `HighlightProcessor` and `CodeLanguages` now get their `Highlighter`
instance via constructor injection (autowired through `Services.yaml`).
- `HighlightProcessor` fixes the auto-detect default for the
`code_language` field. The previous `?? true` default unintentionally
skipped auto-detection when the field was unset.
- `ContentPreviewRenderer` truncates the bodytext for the page-module
preview with `mb_strimwidth()` instead of the deprecated
`GeneralUtility::fixed_lgd_cs()`.
- TCA `CType` registration now includes a `description` and `group`, so
the New Content Element Wizard picks it up correctly under the
*default* group on TYPO3 13 and 14.
- GitHub Actions workflow refreshed: `ubuntu-latest`, `actions/checkout@v4`,
PHP 8.2, `$GITHUB_OUTPUT` syntax.

## 2.1.0 and earlier

See git history.
22 changes: 18 additions & 4 deletions Classes/Backend/Preview/ContentPreviewRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,34 @@
* of the License, or any later version.
*/

use TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer;
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
use TYPO3\CMS\Core\Domain\RecordInterface;

class ContentPreviewRenderer extends \TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer
/**
* Renders a preview of the "codeblock" content element for the page module.
*
* Shows a truncated version of the entered code (rather than the default
* "no preview available" placeholder) so editors can recognize the element
* at a glance.
*/
final class ContentPreviewRenderer extends StandardContentPreviewRenderer
{
private const PREVIEW_MAX_LENGTH = 1000;

public function renderPageModulePreviewContent(GridColumnItem $item): string
{
$record = $item->getRecord();
$bodytext = $record instanceof RecordInterface
? (string)($record->get('bodytext') ?? '')
: (string)($record['bodytext'] ?? '');
if (trim($bodytext) !== '') {
return $this->linkEditContent(nl2br(htmlentities($bodytext)), $record) . '<br />';

if (trim($bodytext) === '') {
return parent::renderPageModulePreviewContent($item);
}
return parent::renderPageModulePreviewContent($item);

$bodytext = mb_strimwidth($bodytext, 0, self::PREVIEW_MAX_LENGTH, '…');

return $this->linkEditContent(nl2br(htmlentities($bodytext)), $record) . '<br />';
}
}
63 changes: 29 additions & 34 deletions Classes/DataProcessing/HighlightProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,51 +13,46 @@
*/

use Highlight\Highlighter;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentDataProcessor;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;

/**
* This processor passes the given text through highlight.php.
* Runs the configured field's value through highlight.php and returns
* the rendered HTML plus the detected language for use in Fluid.
*/
class HighlightProcessor implements DataProcessorInterface
final class HighlightProcessor implements DataProcessorInterface
{
protected ContentDataProcessor $contentDataProcessor;

public function __construct(ContentDataProcessor $contentDataProcessor)
{
$this->contentDataProcessor = $contentDataProcessor;
public function __construct(
private readonly Highlighter $highlighter
) {
}

/**
* Fetches records from the database as an array
*
* @param ContentObjectRenderer $cObj The data of the content element or page
* @param array $contentObjectConfiguration The configuration of Content Object
* @param array $processorConfiguration The configuration of this processor
* @param array $processedData Key/value store of processed data (e.g. to be passed to a Fluid View)
*
* @return array the processed data as key/value store
*/
public function process(ContentObjectRenderer $cObj, array $contentObjectConfiguration, array $processorConfiguration, array $processedData)
{
$fieldName = $processorConfiguration['field'];
$targetVariableName = $cObj->stdWrapValue('as', $processorConfiguration, 'bodytext_formatted');
$highlight = GeneralUtility::makeInstance(Highlighter::class);

// Let highlight.php decide which code language to use from all registered if "detect automatically" is selected.
if (!($processedData['data']['code_language'] ?? true)) {
$languages = $highlight->listLanguages();
$highlight->setAutodetectLanguages($languages);
$highlighted = $highlight->highlightAuto($processedData['data'][$fieldName]);
public function process(
ContentObjectRenderer $cObj,
array $contentObjectConfiguration,
array $processorConfiguration,
array $processedData
): array {
$fieldName = (string)($processorConfiguration['field'] ?? 'bodytext');
$targetVariableName = (string)$cObj->stdWrapValue('as', $processorConfiguration, 'bodytext_formatted');

$source = (string)($processedData['data'][$fieldName] ?? '');
$language = (string)($processedData['data']['code_language'] ?? '');

if ($language === '') {
// Let highlight.php pick the language from all registered ones.
$this->highlighter->setAutodetectLanguages($this->highlighter->listLanguages());
$highlighted = $this->highlighter->highlightAuto($source);
} else {
$highlighted = $highlight->highlight($processedData['data']['code_language'], $processedData['data'][$fieldName]);
$highlighted = $this->highlighter->highlight($language, $source);
}

$processedData[$targetVariableName]['code'] = $highlighted->value;
$processedData[$targetVariableName]['language'] = $highlighted->language;
$processedData[$targetVariableName]['lines'] = preg_split('/\r\n|\r|\n/', $highlighted->value);
$processedData[$targetVariableName] = [
'code' => $highlighted->value,
'language' => $highlighted->language,
'lines' => preg_split('/\r\n|\r|\n/', $highlighted->value) ?: [],
];

return $processedData;
}
}
38 changes: 20 additions & 18 deletions Classes/DataProvider/CodeLanguages.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,33 @@
*/

use Highlight\Highlighter;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* Class which provides a function to get all languages known by highlight.php.
* Populates the "code_language" select field with all languages
* known to highlight.php plus an "auto detect" entry.
*/
class CodeLanguages
final class CodeLanguages
{
public function __construct(
private readonly Highlighter $highlighter
) {
}

/**
* @param array $config
* @return array
* itemsProcFunc callback for the "code_language" TCA select field.
*/
public function getAll($config): array
public function getAll(array &$config): void
{
// Get all languages from highlight.php.
$highlight = GeneralUtility::makeInstance(Highlighter::class);
$languages = $highlight->listLanguages();

// Add default to items as the highlight processor can handle the automatic detection of the language.
$config['items'][] = ['LLL:EXT:codeblock/Resources/Private/Language/locallang_db.xlf:tt_content.code_language.detect_automatically', ''];

// Add all languages to dropdown.
foreach ($languages as $language) {
$config['items'][] = [$language, $language];
$config['items'][] = [
'label' => 'LLL:EXT:codeblock/Resources/Private/Language/locallang_db.xlf:tt_content.code_language.detect_automatically',
'value' => '',
];

foreach ($this->highlighter->listLanguages() as $language) {
$config['items'][] = [
'label' => $language,
'value' => $language,
];
}

return $config;
}
}
50 changes: 0 additions & 50 deletions Classes/Hooks/CodeblockPreviewRenderer.php

This file was deleted.

31 changes: 0 additions & 31 deletions Classes/Listener/PageContentPreviewRendering.php

This file was deleted.

11 changes: 0 additions & 11 deletions Configuration/PageTs/PageTs.tsconfig

This file was deleted.

9 changes: 5 additions & 4 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ services:
B13\Codeblock\:
resource: '../Classes/*'

# DataProcessors are resolved via TypoScript and instantiated by core, so they need public visibility.
B13\Codeblock\DataProcessing\HighlightProcessor:
public: true
B13\Codeblock\Listener\PageContentPreviewRendering:
tags:
- name: event.listener
identifier: 'b13/codeblock/page-content-preview-rendering'

# itemsProcFunc callbacks are resolved by class name and need public visibility, too.
B13\Codeblock\DataProvider\CodeLanguages:
public: true
Loading