diff --git a/bin/pest-tia-vite-deps.mjs b/bin/pest-tia-vite-deps.mjs
index f39af3955..bcc941cac 100644
--- a/bin/pest-tia-vite-deps.mjs
+++ b/bin/pest-tia-vite-deps.mjs
@@ -172,6 +172,46 @@ export async function loadAliasFromViteConfig(projectRoot = PROJECT_ROOT) {
return alias
}
+const SFC_RE = /\.(vue|svelte)$/i
+const SCRIPT_BLOCK_RE = /
+ VUE,
+ 'js',
+ ["import Layout from '@/Layouts/AppLayout.vue'", 'export default null'],
+ [''],
+ 1,
+ ],
+ 'script-setup-typescript' => [
+ <<<'VUE'
+
+
+ VUE,
+ 'ts',
+ ["import Card from './Card.vue'", 'export default null'],
+ [],
+ 1,
+ ],
+ 'render-function-jsx' => [
+ <<<'VUE'
+
+ VUE,
+ 'tsx',
+ ["import Button from './Button.vue'", ''],
+ ['export default null'],
+ 1,
+ ],
+ 'options-api-keeps-its-own-default' => [
+ <<<'VUE'
+
+
+ VUE,
+ 'js',
+ ["import Card from './Card.vue'", 'export default { components: { Card } }'],
+ ['export default null'],
+ 1,
+ ],
+ 'both-script-blocks' => [
+ <<<'VUE'
+
+
+ VUE,
+ 'js',
+ ["import Base from './Base.vue'", "import Icon from './Icon.vue'"],
+ ['export default null'],
+ 1,
+ ],
+ 'external-script-src' => [
+ <<<'VUE'
+
+
+ VUE,
+ 'js',
+ ['import "./external.js"', 'export default null'],
+ [],
+ 1,
+ ],
+ 'leading-html-comment' => [
+ <<<'VUE'
+
+
+
+ VUE,
+ 'js',
+ ["import Card from './Card.vue'"],
+ ['
+
+
+ VUE);
+
+ file_put_contents($pages.'/Register.vue', <<<'VUE'
+
+
+ VUE);
+
+ file_put_contents($pages.'/Widget.vue', <<<'VUE'
+
+ VUE);
+
+ $process = new Process(['node', tiaViteHelperPath(), $root], $root);
+ $process->run();
+
+ $output = $process->getOutput();
+
+ return $cache = [
+ 'root' => $root,
+ 'exitCode' => $process->getExitCode(),
+ 'errorOutput' => $process->getErrorOutput(),
+ 'map' => $output === '' ? null : json_decode($output, true),
+ ];
+}
+
+it('extracts the script blocks of a single-file component', function (string $name): void {
+ [, $moduleType, $contains, $missing, $defaults] = tiaSfcFixtures()[$name];
+ $result = tiaSfcResults()[$name];
+
+ expect($result['moduleType'])->toBe($moduleType);
+
+ foreach ($contains as $needle) {
+ expect($result['code'])->toContain($needle);
+ }
+
+ foreach ($missing as $needle) {
+ expect($result['code'])->not->toContain($needle);
+ }
+
+ expect(substr_count($result['code'], 'export default'))->toBe($defaults);
+})->with(array_keys(tiaSfcFixtures()));
+
+it('bundles a single-file component tree without a framework plugin', function (): void {
+ $result = tiaSfcBundleResult();
+
+ $probe = new Process(['node', '-e', "require.resolve('rolldown')"], $result['root']);
+ $probe->run();
+
+ if (! $probe->isSuccessful()) {
+ $this->markTestSkipped('rolldown is not installed.');
+ }
+
+ $pages = ['Auth/Login', 'Auth/Register'];
+
+ expect($result['exitCode'])->toBe(0, $result['errorOutput'])
+ ->and($result['map'])->toHaveKeys([
+ 'resources/js/Layouts/GuestLayout.vue',
+ 'resources/js/Layouts/Button.vue',
+ 'resources/js/Layouts/layout.css',
+ ])
+ ->and($result['map']['resources/js/Layouts/GuestLayout.vue'])->toBe($pages)
+ ->and($result['map']['resources/js/Layouts/Button.vue'])->toBe([...$pages, 'Auth/Widget'])
+ ->and($result['map']['resources/js/Layouts/layout.css'])->toBe($pages);
+});