Skip to content

Commit

Permalink
Task/svgiconprovider (#16)
Browse files Browse the repository at this point in the history
* [TASK] Add custom IconProvider for vite.

* [TASK] Update icon provider according to the review

Set SvgIconProvider to public instead of all classes

* [TASK] Set icon provider to public

* [TASK] Add test for SvgIconProvider

* [TASK] Make CGL Happy

* [TASK] Add test for inline svg

* [TASK] Make CGL happy

* [TASK] Fix tests for v11

* [TASK] Extend docs, use getManifest() to retrieve the manifest
  • Loading branch information
ochorocho authored Oct 5, 2023
1 parent d0d7cf8 commit 11dd0f3
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 0 deletions.
75 changes: 75 additions & 0 deletions Classes/IconProvider/SvgIconProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace Praetorius\ViteAssetCollector\IconProvider;

use Praetorius\ViteAssetCollector\Exception\ViteException;
use Praetorius\ViteAssetCollector\Service\ViteService;
use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException;
use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconProvider\AbstractSvgIconProvider;

class SvgIconProvider extends AbstractSvgIconProvider
{
public function __construct(
private readonly ViteService $viteService,
private readonly ExtensionConfiguration $extensionConfiguration
) {}

/**
* @throws \InvalidArgumentException|ViteException
*/
protected function generateMarkup(Icon $icon, array $options): string
{
if (empty($options['source'])) {
throw new \InvalidArgumentException('[' . $icon->getIdentifier() . '] The option "source" is required and must not be empty', 1460976566);
}

$source = $this->viteService->getAssetPathFromManifest(
$this->getManifest($options['manifest'] ?? ''),
$options['source']
);

return '<img src="' . htmlspecialchars($this->getPublicPath($source)) . '" width="' . $icon->getDimension()->getWidth() . '" height="' . $icon->getDimension()->getHeight() . '" alt="" />';
}

private function getManifest(string $manifest): string
{
if ($manifest === '') {
$manifest = $this->extensionConfiguration->get('vite_asset_collector', 'defaultManifest');
}

if (!is_string($manifest) || $manifest === '') {
throw new ViteException(
sprintf(
'Unable to determine vite manifest from specified argument and default manifest: %s',
$manifest
),
1684528724
);
}

return $manifest;
}

/**
* @throws \InvalidArgumentException|ViteException|ExtensionConfigurationExtensionNotConfiguredException|ExtensionConfigurationPathDoesNotExistException
*/
protected function generateInlineMarkup(array $options): string
{
if (empty($options['source'])) {
throw new \InvalidArgumentException('The option "source" is required and must not be empty', 1690831431);
}

$source = $this->viteService->getAssetPathFromManifest(
$this->getManifest($options['manifest'] ?? ''),
$options['source'],
false
);

return $this->getInlineSvg($source);
}
}
3 changes: 3 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ services:

Praetorius\ViteAssetCollector\Configuration\VitePlaceholderProcessor:
public: true

Praetorius\ViteAssetCollector\IconProvider\SvgIconProvider:
public: true
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,20 @@ editor:
# Using another manifest.json
- "%vite('EXT:sitepackage/Resources/Private/Css/Rte.css', 'path/to/manifest.json')%"
```
### IconProvider
Use the `SvgIconProvider` for icons processed by Vite. It works in Frontend and Backend.
For more details about the TYPO3 Icon API see the [documentation](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Icon/Index.html)

To use an icon along with `core:icon` ViewHelper, add the following to the `Configuration/Icons.php` file:

```php
return [
'site-logo' => [
'provider' => \Praetorius\ViteAssetCollector\IconProvider\SvgIconProvider::class,
'source' => 'assets/Image/Icon/typo3.svg',
'manifest' => 'EXT:sitepackage/Resources/Public/manifest.json', // optional, defaults to defaultManifest
],
];
```
5 changes: 5 additions & 0 deletions Tests/Fixtures/DefaultManifest/assets/typo3-57f5650e.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions Tests/Fixtures/DefaultManifest/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@
"file": "assets/Default-4483b920.js",
"isEntry": true,
"src": "Default.js"
},
"typo3.svg": {
"file": "assets/typo3-57f5650e.svg",
"src": "assets/typo3.svg"
}
}
5 changes: 5 additions & 0 deletions Tests/Fixtures/SvgIconProvider/typo3.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
106 changes: 106 additions & 0 deletions Tests/Functional/Imaging/SvgIconProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

declare(strict_types=1);

namespace Praetorius\ViteAssetCollector\Tests\Functional\Imaging;

use Praetorius\ViteAssetCollector\IconProvider\SvgIconProvider;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Imaging\IconRegistry;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;

final class SvgIconProviderTest extends FunctionalTestCase
{
protected IconFactory $subject;
protected SvgIconProvider $svgIconProvider;
protected Icon $icon;
protected string $registeredIconIdentifier = 'typo3-logo';

protected array $testExtensionsToLoad = [
'typo3conf/ext/vite_asset_collector',
];

protected array $pathsToProvideInTestInstance = [
'typo3conf/ext/vite_asset_collector/Tests/Fixtures' => 'fileadmin/Fixtures/',
];

protected array $configurationToUseInTestInstance = [
'EXTENSIONS' => [
'vite_asset_collector' => [
'defaultManifest' => 'EXT:vite_asset_collector/Tests/Fixtures/DefaultManifest/manifest.json',
],
],
];

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

$this->subject = $this->get(IconFactory::class);

$iconRegistry = $this->get(IconRegistry::class);
$iconRegistry->registerIcon(
$this->registeredIconIdentifier,
SvgIconProvider::class,
[
'source' => 'typo3.svg',
]
);

$this->svgIconProvider = $this->get(SvgIconProvider::class);
$this->icon = GeneralUtility::makeInstance(Icon::class);
$this->icon->setIdentifier('typo3-logo');
$this->icon->setSize(Icon::SIZE_SMALL);
}

/**
* @test
*/
public function getLogoIconMarkup(): void
{
$this->svgIconProvider->prepareIconMarkup($this->icon, ['source' => 'typo3.svg']);
self::assertEquals(
'<img src="typo3conf/ext/vite_asset_collector/Tests/Fixtures/DefaultManifest/assets/typo3-57f5650e.svg" width="16" height="16" alt="" />',
$this->icon->getMarkup()
);
}

/**
* @test
*/
public function getLogoIconMarkupInline(): void
{
$this->svgIconProvider->prepareIconMarkup($this->icon, ['source' => 'typo3.svg']);
$expectedSvgMarkup = <<<SVG_MARKUP
<svg xmlns="http://www.w3.org/2000/svg" width="180" height="180">
<g fill="#f49700">
<path d="M122.254 114.079c-1.888.558-3.391.766-5.365.766-16.171 0-39.915-56.51-39.915-75.317 0-6.922 1.638-9.233 3.951-11.216-19.792 2.31-43.539 9.572-51.134 18.805-1.641 2.314-2.637 5.938-2.637 10.56 0 29.362 31.339 95.984 53.445 95.984 10.226-.001 27.467-16.813 41.655-39.582M111.931 26.34c20.449 0 40.915 3.298 40.915 14.84 0 23.42-14.854 51.802-22.433 51.802-13.527 0-30.352-37.614-30.352-56.422 0-8.576 3.298-10.22 11.87-10.22"/>
</g>
</svg>
SVG_MARKUP;

self::assertEquals(
$expectedSvgMarkup,
$this->subject->getIcon($this->registeredIconIdentifier)->getAlternativeMarkup(SvgIconProvider::MARKUP_IDENTIFIER_INLINE)
);
}

/**
* @test
*/
public function getIconReturnsCorrectMarkupIfIconIsRegisteredAsLogoIcon(): void
{
$iconMarkup = $this->subject->getIcon($this->registeredIconIdentifier)->render();
self::assertMatchesRegularExpression(
'<span class="t3js-icon icon icon-size-([a-z]*) icon-state-default icon-typo3-logo" data-identifier="typo3-logo"(.*)>',
$iconMarkup
);

self::assertStringContainsString(
'<img src="typo3conf/ext/vite_asset_collector/Tests/Fixtures/DefaultManifest/assets/typo3-57f5650e.svg" width="32" height="32" alt="" />',
$iconMarkup
);
}
}

0 comments on commit 11dd0f3

Please sign in to comment.