Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Exclude from release archives
/.github export-ignore
/Tests export-ignore
.gitattributes export-ignore
.gitignore export-ignore
grumphp.yml export-ignore
Makefile export-ignore
phpstan.neon export-ignore
phpstan-baseline.neon export-ignore
phpunit.xml export-ignore
rector.php export-ignore
25 changes: 10 additions & 15 deletions .github/workflows/tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,20 @@ jobs:
strategy:
fail-fast: false
matrix:
php: [ '8.1', '8.2', '8.3', '8.4' ]
typo3: [ '11', '12', '13' ]
exclude:
- php: '8.1'
typo3: '13'
- php: '8.4'
typo3: '11'
php: [ '82', '83', '84' ]
typo3: [ '12', '13' ]
container:
image: ghcr.io/typo3/core-testing-php${{ matrix.php }}:latest
steps:
- name: Setup PHP with PECL extension
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- name: Install dependencies
run: apk add --no-cache nodejs
- uses: actions/checkout@v5
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ~/.composer/cache/files
key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.php }}-composer-
- run: composer require typo3/minimal="^${{ matrix.typo3 }}" --dev
- run: composer install --no-interaction --no-progress
- run: ./vendor/bin/grumphp run --ansi
- run: composer switchto${{ matrix.typo3 }}
- run: ./vendor/bin/grumphp run --ansi --no-interaction
- run: composer test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ vendor
public
composer.lock
var/
.phpunit.result.cache
2 changes: 2 additions & 0 deletions Classes/EventListener/RenderedEventListener.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Pluswerk\PlusMinify\EventListener;

use AUS\SsiInclude\Event\RenderedEvent;
Expand Down
2 changes: 2 additions & 0 deletions Configuration/RequestMiddlewares.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

use Pluswerk\PlusMinify\Middleware\MinifyMiddleware;

return [
Expand Down
3 changes: 3 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ services:
autoconfigure: true
public: false

Pluswerk\PlusMinify\:
resource: '../Classes/*'

Pluswerk\PlusMinify\EventListener\RenderedEventListener:
tags:
- name: event.listener
Expand Down
41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
ACT_IMAGE ?= efrecon/act:v0.2.80
WORKDIR ?= /work
UID_GID := $(shell id -u):$(shell id -g)
DOCKER_GID := $(shell stat -c '%g' /var/run/docker.sock)

PLATFORM ?= -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:act-24.04

# Secrets-File in ENV format
SECRETS ?= --secret-file .secrets

ACT_ARGS ?= \
--artifact-server-path /home/act/.cache/artifacts

define DOCKER_RUN
docker run --rm -it \
-u $(UID_GID) \
--group-add $(DOCKER_GID) \
-e HOME=/home/act \
-e XDG_CACHE_HOME=/home/act/.cache \
-e ACT_CACHE_DIR=/home/act/.cache/actcache \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(PWD):$(WORKDIR) -w $(WORKDIR) \
-v $$HOME/.cache:/home/act/.cache \
$(ACT_IMAGE)
endef

# ---- Targets ----
.PHONY: all ci clean

all: ci clean

ci: ## Standard-Event "push"
$(DOCKER_RUN) $(PLATFORM) $(SECRETS) $(ACT_ARGS) 2>&1 | tee /tmp/act-output.log; \
echo ""; \
echo "=== 🏁 Summary ==="; \
grep "🏁" /tmp/act-output.log || true


clean:
docker rm -f $$(docker ps -aq --filter "name=act-") 2>/dev/null || true

141 changes: 141 additions & 0 deletions Tests/Unit/Service/MinifyServiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

declare(strict_types=1);

namespace Pluswerk\PlusMinify\Tests\Unit\Service;

use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Pluswerk\PlusMinify\Service\MinifyService;

class MinifyServiceTest extends TestCase
{
private MinifyService $subject;

protected function setUp(): void
{
parent::setUp();

// Reset all minify feature flags — everything disabled by default
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify'] = [];

$this->subject = new MinifyService();
}

// -------------------------------------------------------------------------
// All features off (default)
// -------------------------------------------------------------------------

#[Test]
public function minifyKeepsHtmlCommentsWhenNoFeaturesAreEnabled(): void
{
$html = '<html><head><meta charset="utf-8"><!-- a comment --></head><body><p>Hello</p></body></html>';

$result = $this->subject->minify($html);

self::assertStringContainsString('<!-- a comment -->', $result);
}

#[Test]
public function minifyKeepsTypo3CommentWhenNoFeaturesAreEnabled(): void
{
$html = '<html><head><meta charset="utf-8"><!-- TYPO3 page info --></head><body><p>Hello</p></body></html>';

$result = $this->subject->minify($html);

self::assertStringContainsString('<!-- TYPO3 page info -->', $result);
}

// -------------------------------------------------------------------------
// remove_comments alone — comment removal needs the DOM parser too,
// so the output stays unchanged when only remove_comments is set.
// -------------------------------------------------------------------------

#[Test]
public function minifyDoesNotRemoveCommentsWithOnlyRemoveCommentsFlagEnabled(): void
{
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['remove_comments'] = '1';

$html = '<html><head><meta charset="utf-8"></head><body><!-- just a comment --><p>Hello</p></body></html>';

$result = $this->subject->minify($html);

// Without the DOM parser the minifier cannot parse the tree,
// so the comment is left in the output.
self::assertStringContainsString('<!-- just a comment -->', $result);
}

// -------------------------------------------------------------------------
// remove_comments + optimize_via_html_dom_parser (the realistic combination)
// -------------------------------------------------------------------------

#[Test]
public function minifyRemovesRegularCommentsWhenRemoveCommentsAndDomParserAreEnabled(): void
{
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['remove_comments'] = '1';
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['optimize_via_html_dom_parser'] = '1';

$html = '<html><head><meta charset="utf-8"></head><body><!-- just a comment --><p>Hello</p></body></html>';

$result = $this->subject->minify($html);

self::assertStringNotContainsString('<!-- just a comment -->', $result);
self::assertStringContainsString('<p>Hello</p>', $result);
}

#[Test]
public function minifyPreservesTypo3CommentWhenRemoveCommentsAndDomParserAreEnabled(): void
{
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['remove_comments'] = '1';
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['optimize_via_html_dom_parser'] = '1';

$html = '<html><head><meta charset="utf-8"><!-- TYPO3CMS id=1 --></head><body><p>Hello</p></body></html>';

$result = $this->subject->minify($html);

self::assertStringContainsString('<!-- TYPO3CMS id=1 -->', $result);
}

#[Test]
public function minifyRemovesRegularCommentButKeepsTypo3CommentWhenBothFlagsAreEnabled(): void
{
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['remove_comments'] = '1';
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['optimize_via_html_dom_parser'] = '1';

$html = '<html><head><meta charset="utf-8"><!-- TYPO3 page --></head><body><!-- drop me --><p>Hello</p></body></html>';

$result = $this->subject->minify($html);

self::assertStringContainsString('<!-- TYPO3 page -->', $result);
self::assertStringNotContainsString('<!-- drop me -->', $result);
}

// -------------------------------------------------------------------------
// Output integrity
// -------------------------------------------------------------------------

#[Test]
public function minifyReturnsFallbackHtmlWhenMinifierProducesEmptyString(): void
{
// An empty string causes the minifier to return '' which triggers
// the $originalHtml fallback — the method must not crash.
$result = $this->subject->minify('');

self::assertSame('', $result);
}

#[Test]
public function minifyAppendsClosingBodyTagWhenAbsentFromMinifiedOutput(): void
{
// Enable features that actually cause HtmlMin to strip closing tags.
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['remove_comments'] = '1';
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['optimize_via_html_dom_parser'] = '1';
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['minify']['remove_omitted_html_tags'] = '1';

$html = '<html><head><meta charset="utf-8"></head><body><p>Hello</p></body></html>';

$result = $this->subject->minify($html);

self::assertStringEndsWith('</body>', $result);
}
}
27 changes: 22 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,28 @@
"source": "https://github.com/pluswerk/minify"
},
"require": {
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"composer-runtime-api": "^2",
"typo3/cms-core": "^11.5 || ^12.4 || ^13.4",
"voku/html-min": "^4.5.1"
"typo3/cms-core": "^12.4 || ^13.4",
"voku/html-min": "^5.0.0"
},
"require-dev": {
"andersundsehr/ssi-include": "^1.1.0 || ^2.2.0",
"pluswerk/grumphp-config": "^7 || ^10",
"saschaegerer/phpstan-typo3": "^1.10.0 || ^2.1.1",
"ssch/typo3-rector": "^2.5.0 || ^3.6.2"
"saschaegerer/phpstan-typo3": "^1.10.2 || ^2.1.1",
"ssch/typo3-rector": "^2.15.2 || ^3.14.1",
"typo3/testing-framework": "^8.2 || ^9.4"
},
"autoload": {
"psr-4": {
"Pluswerk\\PlusMinify\\": "Classes/"
}
},
"autoload-dev": {
"psr-4": {
"Pluswerk\\PlusMinify\\Tests\\": "Tests/"
}
},
"config": {
"allow-plugins": {
"ergebnis/composer-normalize": true,
Expand All @@ -39,5 +45,16 @@
"typo3/cms": {
"extension-key": "minify"
}
},
"scripts": {
"switchto12": [
"rm -rf composer.lock vendor/composer/installed.json",
"@composer req typo3/minimal:^12 --dev --no-interaction --no-progress"
],
"switchto13": [
"rm -rf composer.lock vendor/composer/installed.json",
"@composer req typo3/minimal:^13 --dev --no-interaction --no-progress"
],
"test": "@php ./vendor/bin/phpunit --testdox --stderr"
}
}
2 changes: 2 additions & 0 deletions ext_emconf.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);
Comment thread
Kanti marked this conversation as resolved.
Outdated

use Composer\InstalledVersions;

/** @var string $_EXTKEY */
Expand Down
14 changes: 14 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd" bootstrap="vendor/autoload.php" executionOrder="depends,defects" beStrictAboutOutputDuringTests="true" failOnRisky="true" failOnWarning="true">
<testsuites>
<testsuite name="default">
<directory>Tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">Classes</directory>
</include>
</source>
</phpunit>
Loading