diff --git a/composer.json b/composer.json index 931239a..95deb56 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,8 @@ "symfony/ux-live-component": "^2.16", "symfony/ux-twig-component": "2.16", "symfonycasts/sass-bundle": "^0.5.1", - "symfonycasts/tailwind-bundle": "^0.5.0" + "symfonycasts/tailwind-bundle": "^0.5.0", + "symfony/maker-bundle": "^1.60" }, "conflict": { "symfony/ux-twig-component": "2.17" diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 4ce02e0..0bc0b1b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -5,6 +5,8 @@ parameters: - tests bootstrapFiles: - vendor/bin/.phpunit/phpunit/vendor/autoload.php + excludePaths: + - src/Resources/skeleton ignoreErrors: - message: '#^Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface\:\:arrayNode\(\)\.$#' diff --git a/src/DependencyInjection/StorybookExtension.php b/src/DependencyInjection/StorybookExtension.php index 7cc117a..16b095f 100644 --- a/src/DependencyInjection/StorybookExtension.php +++ b/src/DependencyInjection/StorybookExtension.php @@ -12,6 +12,7 @@ use Storybook\EventListener\ComponentMockSubscriber; use Storybook\EventListener\ProxyRequestListener; use Storybook\Exception\UnauthorizedStoryException; +use Storybook\Maker\MakeStory; use Storybook\Mock\ComponentProxyFactory; use Storybook\StoryRenderer; use Storybook\Twig\StorybookEnvironmentConfigurator; @@ -139,6 +140,17 @@ static function (ChildDefinition $definition, AsComponentMock $attributeInstance $container->register('storybook.component_mock_subscriber', ComponentMockSubscriber::class) ->setArgument(0, new Reference('storybook.component_proxy_factory')) ->addTag('kernel.event_subscriber'); + + // Maker + $container->register('storybook.maker.story_renderer', \Storybook\Maker\StoryRenderer::class) + ->setArgument(0, new Reference('maker.generator')) + ->setArgument(1, new Reference('ux.twig_component.component_factory')) + ->setArgument(2, '%kernel.project_dir%/stories'); + + $container->register('storybook.maker.story_maker', MakeStory::class) + ->setArgument(0, new Reference('storybook.maker.story_renderer')) + ->addTag('maker.command') + ; } public function getConfigTreeBuilder(): TreeBuilder diff --git a/src/Maker/MakeStory.php b/src/Maker/MakeStory.php new file mode 100644 index 0000000..ef08534 --- /dev/null +++ b/src/Maker/MakeStory.php @@ -0,0 +1,62 @@ +addArgument('component', InputArgument::OPTIONAL, 'The name of the component you want a story for') + ; + } + + public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void + { + if (null === $input->getArgument('component')) { + $question = new Question('What is the name of the component?'); + $question->setValidator(fn ($value) => null !== $value); + $question->setMaxAttempts(3); + $input->setArgument('component', $io->askQuestion($question)); + } + } + + public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator) + { + $componentName = $input->getArgument('component'); + + $this->storyRenderer->render($componentName); + } + + public function configureDependencies(DependencyBuilder $dependencies) + { + } +} diff --git a/src/Maker/StoryRenderer.php b/src/Maker/StoryRenderer.php new file mode 100644 index 0000000..309046e --- /dev/null +++ b/src/Maker/StoryRenderer.php @@ -0,0 +1,28 @@ +componentFactory->metadataFor($componentName); + + $this->generator->generateFile($this->storiesPath.'/'.$componentName.'.stories.js', __DIR__.'/../Resources/skeleton/Story.tpl.php', [ + 'componentName' => $componentName, + 'template' => $componentMetadata->getTemplate(), + ]); + + $this->generator->writeChanges(); + } +} diff --git a/src/Resources/skeleton/Story.tpl.php b/src/Resources/skeleton/Story.tpl.php new file mode 100644 index 0000000..28903d7 --- /dev/null +++ b/src/Resources/skeleton/Story.tpl.php @@ -0,0 +1,12 @@ +import from "../templates/"; +import { twig } from '@sensiolabs/storybook-symfony-webpack5'; + +export default { + component: (args) => ({ + component: {}, + template: twig` + /> + `, + }) +} +