diff --git a/CHANGELOG.md b/CHANGELOG.md index a270a05..fbd135e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,3 +9,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: added a framework-agnostic Vite facade with explicit development and production configuration. - docs: add class-level PHPDoc for the framework-neutral Vite APIs. +- refactor: remove unreachable renderer and manifest resolver branches, retain filesystem race protection, and reach `100%` code coverage without reflection-based tests. diff --git a/composer.json b/composer.json index 0d4470e..b6c6671 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,8 @@ "phpstan/phpstan": "^2.2", "phpstan/phpstan-phpunit": "^2.0", "phpstan/phpstan-strict-rules": "^2.0.3", - "phpunit/phpunit": "^12.5" + "phpunit/phpunit": "^12.5", + "xepozz/internal-mocker": "^1.4" }, "autoload": { "psr-4": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4d399f6..9e06a44 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,6 +10,10 @@ failOnWarning="true" stopOnFailure="false" > + + + + tests diff --git a/src/Asset/AssetCollection.php b/src/Asset/AssetCollection.php index abde8a2..4117ef1 100644 --- a/src/Asset/AssetCollection.php +++ b/src/Asset/AssetCollection.php @@ -16,17 +16,18 @@ /** * Immutable, insertion-ordered collection of deduplicated neutral assets. * - * @implements IteratorAggregate + * @implements IteratorAggregate */ final readonly class AssetCollection implements Countable, IteratorAggregate { /** - * @var list Accepted assets in insertion order, with per-type duplicates removed. + * @var list Accepted assets in insertion order, with per-type + * duplicates removed. */ private array $assets; /** - * @param iterable $assets Assets to collect. + * @param iterable $assets Assets to validate and collect. * * @throws ConfigurationException if a value does not implement {@see AssetInterface}, or implements it without * being one of the four supported asset types. @@ -57,7 +58,7 @@ public function __construct(iterable $assets = []) /** * Returns every collected asset in insertion order, regardless of type. * - * @return list The collected assets. + * @return list The collected assets. */ public function all(): array { @@ -93,7 +94,7 @@ public function count(): int /** * Iterates over the collected assets in insertion order. * - * @return Traversable Iterator over the collected assets. + * @return Traversable Iterator over the collected assets. */ public function getIterator(): Traversable { @@ -198,7 +199,7 @@ public function stylesheets(): array * * @return InlineModule|ModulePreload|ModuleScript|Stylesheet The narrowed asset. */ - private function requireAsset(mixed $asset): AssetInterface + private function requireAsset(mixed $asset): InlineModule|ModulePreload|ModuleScript|Stylesheet { if (!$asset instanceof AssetInterface) { throw new ConfigurationException( diff --git a/src/Configuration/DevelopmentConfiguration.php b/src/Configuration/DevelopmentConfiguration.php index 622dc8c..bd5d749 100644 --- a/src/Configuration/DevelopmentConfiguration.php +++ b/src/Configuration/DevelopmentConfiguration.php @@ -26,8 +26,8 @@ /** * @param string $devServerUrl Absolute HTTP(S) URL of the running Vite development server. * @param bool $includeViteClient Whether the `@vite/client` module script is emitted. - * @param list $inlineModuleProviders Providers of application-owned inline - * modules that must run before the Vite client. + * @param list $inlineModuleProviders Providers of application-owned inline modules to validate and emit + * before the Vite client. * * @throws ConfigurationException if the development-server URL is not an absolute HTTP(S) URL, or if a provider * does not implement {@see InlineModuleProviderInterface}. diff --git a/src/Exception/Message.php b/src/Exception/Message.php index a305d5f..06d1bac 100644 --- a/src/Exception/Message.php +++ b/src/Exception/Message.php @@ -168,13 +168,6 @@ enum Message: string */ case HTML_ATTRIBUTE_VALUE_INVALID = 'The HTML attribute "%s" has an unsupported value.'; - /** - * An inline module cannot be rendered safely. - * - * Format: "Unable to render the inline module source." - */ - case INLINE_MODULE_RENDER_FAILED = 'Unable to render the inline module source.'; - /** * An inline module has no source. * @@ -273,13 +266,6 @@ enum Message: string */ case MANIFEST_REFERENCE_MISSING = 'The Vite manifest entry "%s" in "%s" references missing "%s" chunk "%s".'; - /** - * A resolved manifest import is missing unexpectedly. - * - * Format: "The Vite manifest entry \"%s\" in \"%s\" references missing chunk \"%s\"." - */ - case MANIFEST_RESOLVER_REFERENCE_MISSING = 'The Vite manifest entry "%s" in "%s" references missing chunk "%s".'; - /** * A manifest root is not a JSON object. * diff --git a/src/Html/HtmlRenderOptions.php b/src/Html/HtmlRenderOptions.php index 3f69a3f..a311b5f 100644 --- a/src/Html/HtmlRenderOptions.php +++ b/src/Html/HtmlRenderOptions.php @@ -18,19 +18,19 @@ final readonly class HtmlRenderOptions { /** - * @var (Closure(AssetInterface): array)|null Per-asset attribute callback, - * or `null` when only the static per-type attributes apply. + * @var (Closure(AssetInterface): mixed)|null Per-asset attribute callback, or `null` when only the static per-type + * attributes apply. */ private Closure|null $attributeProvider; /** * @param string|null $nonce CSP nonce applied to every generated tag, or `null` to emit none. - * @param array $moduleScriptAttributes Extra attributes for module scripts. - * @param array $stylesheetAttributes Extra attributes for stylesheets. - * @param array $modulePreloadAttributes Extra attributes for preload hints. - * @param array $inlineModuleAttributes Extra attributes for inline modules. - * @param (callable(AssetInterface): array)|null $attributeProvider Callback - * returning per-asset attributes that override the per-type ones, or `null` to apply none. + * @param array $moduleScriptAttributes Extra attributes for module scripts. + * @param array $stylesheetAttributes Extra attributes for stylesheets. + * @param array $modulePreloadAttributes Extra attributes for preload hints. + * @param array $inlineModuleAttributes Extra attributes for inline modules. + * @param (callable(AssetInterface): mixed)|null $attributeProvider Callback returning per-asset attributes that + * override the per-type ones, or `null` to apply none. * @param string $separator String inserted between two rendered tags. * * @throws HtmlRenderingException if the nonce is not a non-empty base64 or base64url value. @@ -95,10 +95,9 @@ public function attributesFor(AssetInterface $asset): array /** * Invokes the attribute provider without narrowing its result. * - * The return type stays `mixed` so the caller can reject a provider that breaks its declared contract at - * runtime, which static analysis alone cannot guarantee. + * The return type stays `mixed` so the caller can validate the provider result at runtime. * - * @param Closure(AssetInterface): array $provider Configured callback. + * @param Closure(AssetInterface): mixed $provider Configured callback. * @param AssetInterface $asset Asset passed to the callback. * * @return mixed Whatever the provider returned. diff --git a/src/Html/HtmlRenderer.php b/src/Html/HtmlRenderer.php index b9e96b7..4b10ffc 100644 --- a/src/Html/HtmlRenderer.php +++ b/src/Html/HtmlRenderer.php @@ -15,7 +15,7 @@ use function is_int; use function is_string; use function preg_match; -use function preg_replace; +use function str_ireplace; use function str_starts_with; use function strtolower; @@ -47,8 +47,8 @@ final class HtmlRenderer * @param AssetCollection $assets Resolved assets to render. * @param HtmlRenderOptions|null $options Per-render policy, or `null` to apply the defaults. * - * @throws HtmlRenderingException if an asset type is unsupported, an inline module cannot be neutralized, or a - * custom attribute is malformed, reserved, duplicated, or carries an unsupported value. + * @throws HtmlRenderingException if a custom attribute is malformed, reserved, duplicated, or carries an + * unsupported value. * * @return string The rendered tags joined by the configured separator. */ @@ -110,58 +110,39 @@ private function attributesFor(AssetInterface $asset, HtmlRenderOptions $options * Module scripts and inline modules become `