From b5c02750bc3fce459e0609bda9775c2075131129 Mon Sep 17 00:00:00 2001 From: Jaapio Date: Tue, 26 Nov 2024 21:29:02 +0100 Subject: [PATCH 01/11] [TASK] Add init command to setup documentation First version of an init command that will setup the Documentation directory. This includes a very basic guides.xml. Therefor the user has to answer a number of questions that will fill in the defaults. --- .../resources/config/typo3-docs-theme.php | 2 +- .../src/Nodes/Inline/ComposerInlineNode.php | 2 +- .../src/TextRoles/ComposerTextRole.php | 2 +- packages/typo3-guides-cli/bin/typo3-guides | 2 + .../src/Command/InitCommand.php | 191 ++++++++++++++++++ .../src/Packagist/ComposerPackage.php | 2 +- .../src/Packagist/PackagistService.php | 3 +- phpstan-baseline.neon | 6 +- 8 files changed, 202 insertions(+), 8 deletions(-) create mode 100644 packages/typo3-guides-cli/src/Command/InitCommand.php rename packages/{typo3-docs-theme => typo3-guides-cli}/src/Packagist/ComposerPackage.php (97%) rename packages/{typo3-docs-theme => typo3-guides-cli}/src/Packagist/PackagistService.php (98%) diff --git a/packages/typo3-docs-theme/resources/config/typo3-docs-theme.php b/packages/typo3-docs-theme/resources/config/typo3-docs-theme.php index c13a4582a..37ac86c92 100644 --- a/packages/typo3-docs-theme/resources/config/typo3-docs-theme.php +++ b/packages/typo3-docs-theme/resources/config/typo3-docs-theme.php @@ -17,6 +17,7 @@ use phpDocumentor\Guides\RestructuredText\Parser\Productions\DirectiveContentRule; use phpDocumentor\Guides\RestructuredText\Parser\Productions\DocumentRule; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use T3Docs\GuidesCli\Packagist\PackagistService; use T3Docs\Typo3DocsTheme\Api\Typo3ApiService; use T3Docs\Typo3DocsTheme\Compiler\NodeTransformers\CollectPrefixLinkTargetsTransformer; use T3Docs\Typo3DocsTheme\Compiler\NodeTransformers\ConfvalMenuNodeTransformer; @@ -41,7 +42,6 @@ use T3Docs\Typo3DocsTheme\EventListeners\OriginalFileNameSetter; use T3Docs\Typo3DocsTheme\EventListeners\TestingModeActivator; use T3Docs\Typo3DocsTheme\Inventory\Typo3InventoryRepository; -use T3Docs\Typo3DocsTheme\Packagist\PackagistService; use T3Docs\Typo3DocsTheme\Inventory\Typo3VersionService; use T3Docs\Typo3DocsTheme\Parser\ExtendedInterlinkParser; use T3Docs\Typo3DocsTheme\Parser\Productions\FieldList\EditOnGitHubFieldListItemRule; diff --git a/packages/typo3-docs-theme/src/Nodes/Inline/ComposerInlineNode.php b/packages/typo3-docs-theme/src/Nodes/Inline/ComposerInlineNode.php index bfba2ea98..0dd35cc7b 100644 --- a/packages/typo3-docs-theme/src/Nodes/Inline/ComposerInlineNode.php +++ b/packages/typo3-docs-theme/src/Nodes/Inline/ComposerInlineNode.php @@ -3,7 +3,7 @@ namespace T3Docs\Typo3DocsTheme\Nodes\Inline; use phpDocumentor\Guides\Nodes\Inline\InlineNode; -use T3Docs\Typo3DocsTheme\Packagist\ComposerPackage; +use T3Docs\GuidesCli\Packagist\ComposerPackage; final class ComposerInlineNode extends InlineNode { diff --git a/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php b/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php index f05251794..bf3cc71c9 100644 --- a/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php +++ b/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php @@ -7,8 +7,8 @@ use phpDocumentor\Guides\RestructuredText\Parser\DocumentParserContext; use phpDocumentor\Guides\RestructuredText\TextRoles\TextRole; use Psr\Log\LoggerInterface; +use T3Docs\GuidesCli\Packagist\PackagistService; use T3Docs\Typo3DocsTheme\Nodes\Inline\ComposerInlineNode; -use T3Docs\Typo3DocsTheme\Packagist\PackagistService; final class ComposerTextRole implements TextRole { diff --git a/packages/typo3-guides-cli/bin/typo3-guides b/packages/typo3-guides-cli/bin/typo3-guides index 920560d93..79f83012e 100755 --- a/packages/typo3-guides-cli/bin/typo3-guides +++ b/packages/typo3-guides-cli/bin/typo3-guides @@ -5,6 +5,7 @@ declare(strict_types=1); namespace T3Docs\GuidesCli; +use T3Docs\GuidesCli\Command\InitCommand; use T3Docs\GuidesCli\Command\MigrateSettingsCommand; use T3Docs\GuidesCli\Command\ConfigureCommand; use T3Docs\GuidesCli\Command\LintGuidesXmlCommand; @@ -35,6 +36,7 @@ if (file_exists($autoloadDirectory)){ $application = new Application('typo3-guides'); $application->add(new MigrateSettingsCommand()); +$application->add(new InitCommand()); $application->add(new ConfigureCommand()); $application->add(new LintGuidesXmlCommand()); diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php new file mode 100644 index 000000000..30574b86a --- /dev/null +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -0,0 +1,191 @@ +setDescription('Initialize a new documentation project'); + $this->addOption('working-dir', 'w', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'); + $this->setHelp( + <<<'HELP' + This interactive command will help you to setup your project documentation. + To do so, it will ask you a few questions about your project and then + create a new documentation project in the current directory. + + For more information, see: + https://docs.typo3.org/permalink/h2document:basic-principles + HELP + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + if ($input->getOption('working-dir')) { + $workdir = $input->getOption('working-dir'); + assert(is_string($workdir)); + + if (chdir($workdir)) { + $output->writeln('Changed working directory to ' . getcwd() . ''); + } else { + $output->writeln('Could not change working directory to ' . $workdir . ''); + return Command::INVALID; + } + } + + if ($input->getOption('quiet')) { + echo 'This command is interactive and requires user input.' . PHP_EOL; + return Command::INVALID; + } + + if (file_exists('Documentation/guides.xml')) { + $output->writeln('A Documentation directory already exists in this directory'); + return Command::INVALID; + } + + $output->writeln('Welcome to the TYPO3 documentation project setup wizard'); + $output->writeln('This wizard will help you to create a new documentation project in the current directory.'); + $output->writeln(''); + + $composerInfo = $this->getComposerInfo($output); + + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + + $projectName = $helper->ask($input, $output, new Question(sprintf('What is the name of your project? [%s]: ', $composerInfo?->getComposerName()), $composerInfo?->getComposerName())); + + $homepageQuestion = new Question(sprintf('What is the URL of your project\'s homepage? [%s]: ', $composerInfo?->getHomepage()), $composerInfo?->getHomepage()); + $homepageQuestion->setAutocompleterValues([ + 'https://extensions.typo3.org/extension/' . $composerInfo?->getComposerName(), + 'https://extensions.typo3.org/package/' . $composerInfo?->getComposerName(), + $composerInfo?->getHomepage(), + ]); + + $homepageQuestion->setValidator(function ($answer) { + if (!filter_var($answer, FILTER_VALIDATE_URL)) { + throw new \RuntimeException('The URL is not valid'); + } + return $answer; + }); + + $projectHomePage = $helper->ask($input, $output, $homepageQuestion); + + $repositoryQuestion = new Question(sprintf('What is the URL of your project\'s repository? ')); + $repositoryQuestion->setAutocompleterValues([ + 'https://github.com/' . $composerInfo?->getComposerName(), + 'https://gitlab.com/' . $composerInfo?->getComposerName(), + $composerInfo?->getHomepage(), + ]); + + $repositoryUrl = $helper->ask($input, $output, $repositoryQuestion); + + $repositoryQuestion = new Question(sprintf('Where can users report issues? [%s]', $composerInfo?->getIssues()), $composerInfo?->getIssues()); + $repositoryQuestion->setAutocompleterValues([ + 'https://github.com/' . $composerInfo?->getComposerName() . '/issues', + 'https://gitlab.com/' . $composerInfo?->getComposerName() . '/-/issues', + $composerInfo?->getHomepage(), + ]); + + $issuesUrl = $helper->ask($input, $output, $repositoryQuestion); + $typo3CoreVersion = $helper->ask($input, $output, new Question('Which version of typo3 is the prefered version to use? [stable]: ', 'stable')); + + $output->writeln('Thank you for your input. We will setup your Documentation folder now.'); + + // Create the project structure + if (!@mkdir('Documentation') && !is_dir('Documentation')) { + $output->writeln('Directory Documentation was not created'); + return Command::FAILURE; + } + + assert(is_string($projectName)); + assert(is_string($projectHomePage)); + assert(is_string($repositoryUrl)); + assert(is_string($issuesUrl)); + assert(is_string($typo3CoreVersion)); + + + file_put_contents( + 'Documentation/guides.xml', + << + + + + + XML + ); + + return Command::SUCCESS; + } + + + private function getComposerInfo(OutputInterface $output): ComposerPackage|null + { + if (!file_exists('composer.json')) { + $output->writeln('No composer.json file was found in the current directory.'); + return null; + } + + $output->writeln('A composer.json file was found in the current directory.'); + $packageName = $this->fetchComposerPackageName(); + if (!is_string($packageName)) { + $output->writeln('The package name could not be determined from the composer.json file.'); + return null; + } + + $composerInfo = (new PackagistService())->getComposerInfo($packageName); + $output->writeln('The package ' . $composerInfo->getComposerName() . ' was found on packagist.org'); + + return $composerInfo; + } + + private function fetchComposerPackageName(): string|null + { + $fileContent = file_get_contents('composer.json'); + if ($fileContent === false) { + return null; + } + + $composerJson = json_decode($fileContent, true); + + if (!is_array($composerJson)) { + return null; + } + + return $composerJson['name']; + } + +} diff --git a/packages/typo3-docs-theme/src/Packagist/ComposerPackage.php b/packages/typo3-guides-cli/src/Packagist/ComposerPackage.php similarity index 97% rename from packages/typo3-docs-theme/src/Packagist/ComposerPackage.php rename to packages/typo3-guides-cli/src/Packagist/ComposerPackage.php index 5fd398c62..be9612d6b 100644 --- a/packages/typo3-docs-theme/src/Packagist/ComposerPackage.php +++ b/packages/typo3-guides-cli/src/Packagist/ComposerPackage.php @@ -1,6 +1,6 @@ cache[$composerName] = new ComposerPackage( $composerName, 'composer req ' . ($isDev ? '--dev ' : '') . $composerName, diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a010533fd..0b6de7763 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -13,17 +13,17 @@ parameters: - message: "#^Cannot access offset 'packages' on mixed\\.$#" count: 1 - path: packages/typo3-docs-theme/src/Packagist/PackagistService.php + path: packages/typo3-guides-cli/src/Packagist/PackagistService.php - message: "#^Cannot access offset 0 on mixed\\.$#" count: 1 - path: packages/typo3-docs-theme/src/Packagist/PackagistService.php + path: packages/typo3-guides-cli/src/Packagist/PackagistService.php - message: "#^Cannot access offset string on mixed\\.$#" count: 1 - path: packages/typo3-docs-theme/src/Packagist/PackagistService.php + path: packages/typo3-guides-cli/src/Packagist/PackagistService.php - message: "#^Result of && is always false\\.$#" From 3b0cb2e23e50bb795dcaa797d2bdc1ceb29bb46c Mon Sep 17 00:00:00 2001 From: Lina Wolf <48202465+linawolf@users.noreply.github.com> Date: Thu, 28 Nov 2024 13:34:34 +0100 Subject: [PATCH 02/11] Apply suggestions from code review Co-authored-by: Garvin Hicking --- packages/typo3-guides-cli/src/Command/InitCommand.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index 30574b86a..997979fbe 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -25,7 +25,7 @@ protected function configure(): void <<<'HELP' This interactive command will help you to setup your project documentation. To do so, it will ask you a few questions about your project and then - create a new documentation project in the current directory. + create a new documentation project in the working directory (default: current directory). For more information, see: https://docs.typo3.org/permalink/h2document:basic-principles @@ -53,7 +53,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if (file_exists('Documentation/guides.xml')) { - $output->writeln('A Documentation directory already exists in this directory'); + $output->writeln('A "Documentation" directory already exists in this directory'); return Command::INVALID; } @@ -101,13 +101,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int ]); $issuesUrl = $helper->ask($input, $output, $repositoryQuestion); - $typo3CoreVersion = $helper->ask($input, $output, new Question('Which version of typo3 is the prefered version to use? [stable]: ', 'stable')); + $typo3CoreVersion = $helper->ask($input, $output, new Question('Which version of TYPO3 is the prefered version to use? [stable]: ', 'stable')); - $output->writeln('Thank you for your input. We will setup your Documentation folder now.'); + $output->writeln('Thank you for your input. We will setup your "Documentation" folder now.'); // Create the project structure if (!@mkdir('Documentation') && !is_dir('Documentation')) { - $output->writeln('Directory Documentation was not created'); + $output->writeln('Directory "Documentation" was not created'); return Command::FAILURE; } From 5f2e3a6ce59ed9c572ea5f7e37c1f676be65819b Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Sun, 15 Dec 2024 07:50:47 +0100 Subject: [PATCH 03/11] [TASK] Remove Release and Version, adjust copyright Release is actually not used anywhere, version is only used during local rendering, both tend to confuse users. --- packages/typo3-guides-cli/src/Command/InitCommand.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index 997979fbe..c878c6216 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -130,9 +130,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int > Date: Sun, 15 Dec 2024 09:51:23 +0100 Subject: [PATCH 04/11] [TASK] Move library to version handling That package is required by all other packages and Packagist is a related topic --- .../resources/config/typo3-docs-theme.php | 2 +- .../src/Nodes/Inline/ComposerInlineNode.php | 2 +- .../src/TextRoles/ComposerTextRole.php | 2 +- .../src/Command/InitCommand.php | 4 +-- .../src/Packagist/ComposerPackage.php | 2 +- .../src/Packagist/PackagistService.php | 2 +- phpstan-baseline.neon | 30 +++++++++---------- 7 files changed, 22 insertions(+), 22 deletions(-) rename packages/{typo3-guides-cli => typo3-version-handling}/src/Packagist/ComposerPackage.php (97%) rename packages/{typo3-guides-cli => typo3-version-handling}/src/Packagist/PackagistService.php (98%) diff --git a/packages/typo3-docs-theme/resources/config/typo3-docs-theme.php b/packages/typo3-docs-theme/resources/config/typo3-docs-theme.php index 37ac86c92..09ddd9a11 100644 --- a/packages/typo3-docs-theme/resources/config/typo3-docs-theme.php +++ b/packages/typo3-docs-theme/resources/config/typo3-docs-theme.php @@ -17,7 +17,7 @@ use phpDocumentor\Guides\RestructuredText\Parser\Productions\DirectiveContentRule; use phpDocumentor\Guides\RestructuredText\Parser\Productions\DocumentRule; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; -use T3Docs\GuidesCli\Packagist\PackagistService; +use T3Docs\VersionHandling\Packagist\PackagistService; use T3Docs\Typo3DocsTheme\Api\Typo3ApiService; use T3Docs\Typo3DocsTheme\Compiler\NodeTransformers\CollectPrefixLinkTargetsTransformer; use T3Docs\Typo3DocsTheme\Compiler\NodeTransformers\ConfvalMenuNodeTransformer; diff --git a/packages/typo3-docs-theme/src/Nodes/Inline/ComposerInlineNode.php b/packages/typo3-docs-theme/src/Nodes/Inline/ComposerInlineNode.php index 0dd35cc7b..6265a5174 100644 --- a/packages/typo3-docs-theme/src/Nodes/Inline/ComposerInlineNode.php +++ b/packages/typo3-docs-theme/src/Nodes/Inline/ComposerInlineNode.php @@ -3,7 +3,7 @@ namespace T3Docs\Typo3DocsTheme\Nodes\Inline; use phpDocumentor\Guides\Nodes\Inline\InlineNode; -use T3Docs\GuidesCli\Packagist\ComposerPackage; +use T3Docs\VersionHandling\Packagist\ComposerPackage; final class ComposerInlineNode extends InlineNode { diff --git a/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php b/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php index bf3cc71c9..5f23235ea 100644 --- a/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php +++ b/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php @@ -7,7 +7,7 @@ use phpDocumentor\Guides\RestructuredText\Parser\DocumentParserContext; use phpDocumentor\Guides\RestructuredText\TextRoles\TextRole; use Psr\Log\LoggerInterface; -use T3Docs\GuidesCli\Packagist\PackagistService; +use T3Docs\VersionHandling\Packagist\PackagistService; use T3Docs\Typo3DocsTheme\Nodes\Inline\ComposerInlineNode; final class ComposerTextRole implements TextRole diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index c878c6216..d83d8aa5f 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -10,8 +10,8 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; -use T3Docs\GuidesCli\Packagist\ComposerPackage; -use T3Docs\GuidesCli\Packagist\PackagistService; +use T3Docs\VersionHandling\Packagist\ComposerPackage; +use T3Docs\VersionHandling\Packagist\PackagistService; final class InitCommand extends Command { diff --git a/packages/typo3-guides-cli/src/Packagist/ComposerPackage.php b/packages/typo3-version-handling/src/Packagist/ComposerPackage.php similarity index 97% rename from packages/typo3-guides-cli/src/Packagist/ComposerPackage.php rename to packages/typo3-version-handling/src/Packagist/ComposerPackage.php index be9612d6b..899f18364 100644 --- a/packages/typo3-guides-cli/src/Packagist/ComposerPackage.php +++ b/packages/typo3-version-handling/src/Packagist/ComposerPackage.php @@ -1,6 +1,6 @@ Date: Sun, 15 Dec 2024 11:55:51 +0100 Subject: [PATCH 05/11] Add init to docker image We need to disable deprecations as those are breaking the auto completion in the cli commands. --- Dockerfile | 1 + entrypoint.sh | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index 7732e7ea5..46da7f349 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ WORKDIR /opt/guides COPY --from=builder /opt/guides/vendor /opt/guides/vendor RUN echo "memory_limit=4G" >> /usr/local/etc/php/conf.d/typo3.ini +RUN echo "error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT" >> /usr/local/etc/php/conf.d/typo3.ini ARG TYPO3AZUREEDGEURIVERSION ENV TYPO3AZUREEDGEURIVERSION=$TYPO3AZUREEDGEURIVERSION diff --git a/entrypoint.sh b/entrypoint.sh index 97fa2bb91..dea71361b 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -65,6 +65,9 @@ ENTRYPOINT_SYMFONY_COMMANDS="/opt/guides/packages/typo3-guides-cli/bin/typo3-gui if [ "$1" = "migrate" ]; then ENTRYPOINT="${ENTRYPOINT_SYMFONY_COMMANDS} migrate" shift +elif [ "$1" = "init" ]; then + ENTRYPOINT="${ENTRYPOINT_SYMFONY_COMMANDS} init" + shift elif [ "$1" = "lint-guides-xml" ]; then ENTRYPOINT="${ENTRYPOINT_SYMFONY_COMMANDS} lint-guides-xml" shift From 4af78a03a82a84cc67ed9fc090107d9778a3d77c Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Mon, 16 Dec 2024 09:17:34 +0100 Subject: [PATCH 06/11] [FEATURE] Automatically generate rst or md documentation --- .../resources/templates/Index.md.twig | 48 +++++ .../resources/templates/guides.xml.twig | 34 ++++ .../templates/rst/Configuration.rst.twig | 42 +++++ .../resources/templates/rst/Faq.rst.twig | 29 +++ .../resources/templates/rst/GetHelp.rst.twig | 22 +++ .../resources/templates/rst/Index.rst.twig | 47 +++++ .../templates/rst/Installation.rst.twig | 33 ++++ .../src/Command/InitCommand.php | 176 ++++++++++++------ .../src/Generation/DocumentationGenerator.php | 62 ++++++ .../src/Twig/RstExtension.php | 21 +++ 10 files changed, 455 insertions(+), 59 deletions(-) create mode 100644 packages/typo3-guides-cli/resources/templates/Index.md.twig create mode 100644 packages/typo3-guides-cli/resources/templates/guides.xml.twig create mode 100644 packages/typo3-guides-cli/resources/templates/rst/Configuration.rst.twig create mode 100644 packages/typo3-guides-cli/resources/templates/rst/Faq.rst.twig create mode 100644 packages/typo3-guides-cli/resources/templates/rst/GetHelp.rst.twig create mode 100644 packages/typo3-guides-cli/resources/templates/rst/Index.rst.twig create mode 100644 packages/typo3-guides-cli/resources/templates/rst/Installation.rst.twig create mode 100644 packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php create mode 100644 packages/typo3-guides-cli/src/Twig/RstExtension.php diff --git a/packages/typo3-guides-cli/resources/templates/Index.md.twig b/packages/typo3-guides-cli/resources/templates/Index.md.twig new file mode 100644 index 000000000..7e1d8613e --- /dev/null +++ b/packages/typo3-guides-cli/resources/templates/Index.md.twig @@ -0,0 +1,48 @@ +# {{ projectName }} + +{{ description | default('No description provided.') }} + +## Installation + +Install the extension via Composer: + +``` +composer req {{ composerName }} +``` + +{% if projectHomePage %} +Or download the extension from {{ projectHomePage }} and install it in +the Extension Manager. +{% endif %} + +See also [Installing extensions, TYPO3 Getting started](https://docs.typo3.org/permalink/t3start:installing-extensions) + +## Configuration + + +{% if siteSet %} + +### Include the site set + +This extension comes with a site set called `{{ siteSet }}`. To use it include +this set in your site configuration via + +``` +base: 'https://example.com/' +rootPageId: 1 +dependencies: + - {{ siteSet }} +``` + +See also: `TYPO3 Explained, Using a site set as dependency in a site `_. +{% else %} +Describe how to configure the extension. +{% endif %} + +## Report issues + +{% if issuesUrl %} +You can report issues at {{ issuesUrl }}. +{% else %} +Explain, how to report issues. +{% endif %} diff --git a/packages/typo3-guides-cli/resources/templates/guides.xml.twig b/packages/typo3-guides-cli/resources/templates/guides.xml.twig new file mode 100644 index 000000000..7dbab53aa --- /dev/null +++ b/packages/typo3-guides-cli/resources/templates/guides.xml.twig @@ -0,0 +1,34 @@ + + + + + diff --git a/packages/typo3-guides-cli/resources/templates/rst/Configuration.rst.twig b/packages/typo3-guides-cli/resources/templates/rst/Configuration.rst.twig new file mode 100644 index 000000000..7855a6bc8 --- /dev/null +++ b/packages/typo3-guides-cli/resources/templates/rst/Configuration.rst.twig @@ -0,0 +1,42 @@ +:navigation-title: Configuration +.. _configuration: + +============= +Configuration +============= + +{% if siteSet %} +.. _site-set: + +Include the site set +==================== + +This extension comes with a site set called `{{ siteSet }}`. To use it include +this set in your site configuration via + +.. code-block:: diff + :caption: config/sites/my-site/config.yaml (diff) + + base: 'https://example.com/' + rootPageId: 1 + +dependencies: + + - {{ siteSet }} + +See also: `TYPO3 Explained, Using a site set as dependency in a site `_. + +{% if siteSetDefinition %} +.. _site-set-settings: + +Use the settings to configure the extension +------------------------------------------- + +.. typo3:site-set-settings:: PROJECT:/ + :name: main-set + :type: + :Label: max=30 + :default: max=10 +{% endif %} + +{% else %} +Describe how to configure the extension. +{% endif %} diff --git a/packages/typo3-guides-cli/resources/templates/rst/Faq.rst.twig b/packages/typo3-guides-cli/resources/templates/rst/Faq.rst.twig new file mode 100644 index 000000000..12c1be3c2 --- /dev/null +++ b/packages/typo3-guides-cli/resources/templates/rst/Faq.rst.twig @@ -0,0 +1,29 @@ +:navigation-title: FAQ + +.. _faq: + +================================ +Frequently Asked Questions (FAQ) +================================ + +.. accordion:: + :name: faq + + .. accordion-item:: How can I install this extension? + :name: installation + :header-level: 2 + :show: + + See chapter :ref:`installation`. + + .. accordion-item:: How to can I include the TypoScript? + :name: configuration + :header-level: 2 + + See chapter :ref:`configuration`. + + .. accordion-item:: Where to get help? + :name: help + :header-level: 2 + + See chapter :ref:`help`. diff --git a/packages/typo3-guides-cli/resources/templates/rst/GetHelp.rst.twig b/packages/typo3-guides-cli/resources/templates/rst/GetHelp.rst.twig new file mode 100644 index 000000000..b241dcf0b --- /dev/null +++ b/packages/typo3-guides-cli/resources/templates/rst/GetHelp.rst.twig @@ -0,0 +1,22 @@ +:navigation-title: Get Help + +.. _help: + +================= +Where to get help +================= + +You can get help in the TYPO3 Slack https://typo3.org/community/meet/chat-slack, +Ask a question in the official TYPO3 forum, https://talk.typo3.org/c/typo3-questions/19 +or contact the extension author. + +.. _report-issues: + +Report Issues +============= + +{% if issuesUrl %} +You can report issues at `{{ issuesUrl }} <{{ issuesUrl }}>`_. +{% else %} +No issue tracker is currently available. +{% endif %} diff --git a/packages/typo3-guides-cli/resources/templates/rst/Index.rst.twig b/packages/typo3-guides-cli/resources/templates/rst/Index.rst.twig new file mode 100644 index 000000000..a0e04d749 --- /dev/null +++ b/packages/typo3-guides-cli/resources/templates/rst/Index.rst.twig @@ -0,0 +1,47 @@ +.. _start: + +{{ '='|repeat(projectName|length) }} +{{ projectName }} +{{ '='|repeat(projectName|length) }} + +{{ description | default('No description provided.') }} + +.. toctree:: + :glob: + :titlesonly: + :hidden: + + */Index + Installation + Configuration + GetHelp + * + +.. card-grid:: + :columns: 1 + :columns-md: 2 + :gap: 4 + :class: pb-4 + :card-height: 100 + +.. card:: :ref:`Installation ` + + Explains how to install this extension in Composer-based and Classic + TYPO3 installations. + +.. card:: :ref:`Configuration ` + + {% if siteSet %} + Learn how to include the site set `{{ siteSet }}` and how to use settings + to configure this extension. + {% else %} + Learn how to configure this extension. + {% endif %} + +.. card:: :ref:`Frequently Asked Questions (FAQ) ` + + These questions have been frequently asked. + +.. card:: :ref:`How to get help ` + + Learn where to get help and how to report issues you found. diff --git a/packages/typo3-guides-cli/resources/templates/rst/Installation.rst.twig b/packages/typo3-guides-cli/resources/templates/rst/Installation.rst.twig new file mode 100644 index 000000000..6ddb0bad4 --- /dev/null +++ b/packages/typo3-guides-cli/resources/templates/rst/Installation.rst.twig @@ -0,0 +1,33 @@ +:navigation-title: Installation + +.. _installation: + +============ +Installation +============ + +.. _installation-composer: + +Install {{ projectName }} with Composer +======================================= + +Install the extension via Composer: + +.. code-block:: bash + + composer req {{ composerName }} + +See also `Installing extensions, TYPO3 Getting started `_. + +.. _installation-classic: + +Install {{ projectName }} in Classic Mode +========================================= + +{% if projectHomePage %} +Or download the extension from `{{ projectHomePage }} <{{ projectHomePage }}>`_ and install it in +the Extension Manager. +{% else %} +Or download the extension from the `TER `_ and install it in +the Extension Manager. +{% endif %} diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index d83d8aa5f..f68a8f204 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -4,6 +4,7 @@ namespace T3Docs\GuidesCli\Command; +use T3Docs\GuidesCli\Generation\DocumentationGenerator; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; @@ -13,6 +14,12 @@ use T3Docs\VersionHandling\Packagist\ComposerPackage; use T3Docs\VersionHandling\Packagist\PackagistService; +/** + * You can run this command, for example like + * + * ddev exec packages/typo3-guides-cli/bin/typo3-guides init --working-dir=packages/typo3-guides-cli + * + */ final class InitCommand extends Command { protected static $defaultName = 'init'; @@ -66,42 +73,80 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** @var QuestionHelper $helper */ $helper = $this->getHelper('question'); - $projectName = $helper->ask($input, $output, new Question(sprintf('What is the name of your project? [%s]: ', $composerInfo?->getComposerName()), $composerInfo?->getComposerName())); - $homepageQuestion = new Question(sprintf('What is the URL of your project\'s homepage? [%s]: ', $composerInfo?->getHomepage()), $composerInfo?->getHomepage()); - $homepageQuestion->setAutocompleterValues([ - 'https://extensions.typo3.org/extension/' . $composerInfo?->getComposerName(), - 'https://extensions.typo3.org/package/' . $composerInfo?->getComposerName(), - $composerInfo?->getHomepage(), - ]); + $question = new Question(sprintf('Do you want to use reStructuredText(rst) or MarkDown(md)? [rst, md]: '), 'rst'); + $question->setValidator(function ($answer) { + if (is_null($answer) || !in_array($answer, ['rst', 'md'], true)) { + throw new \RuntimeException('Choose reStructuredText(rst) or MarkDown(md). '); + } + return $answer; + }); + $format = $helper->ask($input, $output, $question); - $homepageQuestion->setValidator(function ($answer) { - if (!filter_var($answer, FILTER_VALIDATE_URL)) { - throw new \RuntimeException('The URL is not valid'); + $projectNameQuestion = new Question(sprintf('What is the title of your documentation? [%s]: ', $composerInfo?->getComposerName()), $composerInfo?->getComposerName()); + $projectNameQuestion->setValidator(function ($answer) { + if (is_null($answer) || trim($answer) === '') { + throw new \RuntimeException('The project title cannot be empty.'); } return $answer; }); - $projectHomePage = $helper->ask($input, $output, $homepageQuestion); + $projectName = $helper->ask($input, $output, $projectNameQuestion); - $repositoryQuestion = new Question(sprintf('What is the URL of your project\'s repository? ')); - $repositoryQuestion->setAutocompleterValues([ - 'https://github.com/' . $composerInfo?->getComposerName(), - 'https://gitlab.com/' . $composerInfo?->getComposerName(), + $question = $this->createValidatedUrlQuestion( + sprintf('What is the URL of your project\'s homepage? [%s]: ', $composerInfo?->getHomepage()), $composerInfo?->getHomepage(), - ]); + ['https://extensions.typo3.org/package/' . $composerInfo?->getComposerName()] + ); + $projectHomePage = $helper->ask($input, $output, $question); - $repositoryUrl = $helper->ask($input, $output, $repositoryQuestion); - $repositoryQuestion = new Question(sprintf('Where can users report issues? [%s]', $composerInfo?->getIssues()), $composerInfo?->getIssues()); - $repositoryQuestion->setAutocompleterValues([ - 'https://github.com/' . $composerInfo?->getComposerName() . '/issues', - 'https://gitlab.com/' . $composerInfo?->getComposerName() . '/-/issues', + $question = $this->createValidatedUrlQuestion( + sprintf(sprintf('What is the URL of your project\'s repository? [%s]', 'https://github.com/' . $composerInfo?->getComposerName()), 'https://github.com/' . $composerInfo?->getComposerName()), $composerInfo?->getHomepage(), - ]); + [ + 'https://github.com/' . $composerInfo?->getComposerName(), + 'https://gitlab.com/' . $composerInfo?->getComposerName(), + $composerInfo?->getHomepage(), + ] + ); + $repositoryUrl = $helper->ask($input, $output, $question); + + $question = $this->createValidatedUrlQuestion( + sprintf('Where can users report issues? [%s]', $composerInfo?->getIssues()), + $composerInfo?->getIssues(), + [ + 'https://github.com/' . $composerInfo?->getComposerName() . '/issues', + 'https://gitlab.com/' . $composerInfo?->getComposerName() . '/-/issues', + $composerInfo?->getHomepage(), + ] + ); + + $issuesUrl = $helper->ask($input, $output, $question); + $typo3CoreVersion = $helper->ask($input, $output, new Question('Which version of TYPO3 is the preferred version to use? [stable]: ', 'stable')); - $issuesUrl = $helper->ask($input, $output, $repositoryQuestion); - $typo3CoreVersion = $helper->ask($input, $output, new Question('Which version of TYPO3 is the prefered version to use? [stable]: ', 'stable')); + $question = new Question('Do you want generate some Documentation? (yes/no) ', 'yes'); + $question->setValidator(function ($answer) { + if (!in_array(strtolower($answer), ['yes', 'y', 'no', 'n'], true)) { + throw new \RuntimeException('Please answer with yes, no, y, or n.'); + } + return strtolower($answer); + }); + + $answer = $helper->ask($input, $output, $question); + $enableExampleFileGeneration = in_array($answer, ['yes', 'y'], true); + + $question = new Question('Does your extension offer a site set to be included? If so enter the name: '); + $siteSet = $helper->ask($input, $output, $question); + $siteSetPath = ''; + $siteSetDefinition = ''; + if (is_string($siteSet) && $siteSet !== '') { + $question = new Question('Enter the path to your site set: '); + $siteSetPath = $helper->ask($input, $output, $question); + if (file_exists($siteSetPath . '/settings.definitions.yaml')) { + $siteSetDefinition = $siteSetPath . '/settings.definitions.yaml'; + } + } $output->writeln('Thank you for your input. We will setup your "Documentation" folder now.'); @@ -111,44 +156,57 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::FAILURE; } - assert(is_string($projectName)); - assert(is_string($projectHomePage)); - assert(is_string($repositoryUrl)); - assert(is_string($issuesUrl)); - assert(is_string($typo3CoreVersion)); - - - file_put_contents( - 'Documentation/guides.xml', - << - - - - - XML - ); + + $outputDir = 'Documentation'; + if (!is_dir($outputDir)) { + mkdir($outputDir, 0o777, true); + } + + assert(is_string($repositoryUrl ?? '')); + $editOnGitHub = null; + if (str_starts_with($repositoryUrl ?? '', 'https://github.com/')) { + $editOnGitHub = str_replace('https://github.com/', '', $repositoryUrl); + } + // Define your data + $data = [ + 'format' => $format, + 'useMd' => ($format === 'md'), + 'projectName' => $projectName, + 'description' => $composerInfo?->getDescription(), + 'composerName' => $composerInfo?->getComposerName(), + 'projectHomePage' => $projectHomePage, + 'issuesUrl' => $issuesUrl, + 'repositoryUrl' => $repositoryUrl, + 'typo3CoreVersion' => $typo3CoreVersion, + 'editOnGitHub' => $editOnGitHub, + 'siteSet' => $siteSet, + 'siteSetPath' => $siteSetPath, + 'siteSetDefinition' => $siteSetDefinition, + ]; + (new DocumentationGenerator())->generate($data, __DIR__ . '/../../resources/templates', $outputDir, $enableExampleFileGeneration); return Command::SUCCESS; } + /** + * @param ?scalar $default + * @param array $autocompleteValues + */ + private function createValidatedUrlQuestion(string $questionText, mixed $default, array $autocompleteValues = []): Question + { + $question = new Question($questionText, $default); + if (!empty($autocompleteValues)) { + $question->setAutocompleterValues($autocompleteValues); + } + $question->setValidator(function ($answer) { + if (!is_null($answer) && !filter_var($answer, FILTER_VALIDATE_URL)) { + throw new \RuntimeException('The URL is not valid'); + } + return $answer; + }); + + return $question; + } private function getComposerInfo(OutputInterface $output): ComposerPackage|null { @@ -165,7 +223,7 @@ private function getComposerInfo(OutputInterface $output): ComposerPackage|null } $composerInfo = (new PackagistService())->getComposerInfo($packageName); - $output->writeln('The package ' . $composerInfo->getComposerName() . ' was found on packagist.org'); + $output->writeln(sprintf("The package %s was found on packagist.org", $composerInfo->getComposerName())); return $composerInfo; } diff --git a/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php b/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php new file mode 100644 index 000000000..34da408d4 --- /dev/null +++ b/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php @@ -0,0 +1,62 @@ + $data + */ + public function generate(array $data, string $templatesDir, string $outputDir, bool $enableExampleFileGeneration): void + { + $loader = new FilesystemLoader($templatesDir); + $twig = new Environment($loader); + $twig->addExtension(new RstExtension()); + + + // Render the XML + $xmlContent = $twig->render('guides.xml.twig', $data); + file_put_contents($outputDir . '/guides.xml', $xmlContent); + + if (!$enableExampleFileGeneration) { + return; + } + + // Generate the Documantation + if ($data['format'] === 'md') { + $xmlContent = $twig->render('Index.md.twig', $data); + file_put_contents($outputDir . '/Index.md', $xmlContent); + return; + } + // Directory containing the templates + $templatesDir = __DIR__ . '/../../resources/templates/rst'; + $files = scandir($templatesDir); + + if (!$files) { + return; + } + foreach ($files as $file) { + if (pathinfo($file, PATHINFO_EXTENSION) !== 'twig') { + continue; + } + // Determine the output filename + $outputFileName = str_replace('.twig', '', $file); + $outputFilePath = sprintf("%s/%s", $outputDir, $outputFileName); + + // Check if the output file already exists + if (file_exists($outputFilePath)) { + continue; + } + + // Render the template + $output = $twig->render("rst/$file", $data); + + // Save the rendered content to the output file + file_put_contents($outputFilePath, $output); + } + } +} diff --git a/packages/typo3-guides-cli/src/Twig/RstExtension.php b/packages/typo3-guides-cli/src/Twig/RstExtension.php new file mode 100644 index 000000000..18d0ea427 --- /dev/null +++ b/packages/typo3-guides-cli/src/Twig/RstExtension.php @@ -0,0 +1,21 @@ + Date: Mon, 16 Dec 2024 10:52:06 +0100 Subject: [PATCH 07/11] [FEATURE] Automatically generate rst or md documentation --- .../src/TextRoles/ComposerTextRole.php | 6 ++-- .../src/Command/InitCommand.php | 30 +++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php b/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php index 5f23235ea..110c5bde0 100644 --- a/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php +++ b/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php @@ -7,15 +7,17 @@ use phpDocumentor\Guides\RestructuredText\Parser\DocumentParserContext; use phpDocumentor\Guides\RestructuredText\TextRoles\TextRole; use Psr\Log\LoggerInterface; -use T3Docs\VersionHandling\Packagist\PackagistService; use T3Docs\Typo3DocsTheme\Nodes\Inline\ComposerInlineNode; +use T3Docs\VersionHandling\Packagist\PackagistService; final class ComposerTextRole implements TextRole { public function __construct( private readonly PackagistService $packagistService, private readonly LoggerInterface $logger, - ) {} + ) + { + } public function getName(): string { diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index f68a8f204..34929c499 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -4,20 +4,20 @@ namespace T3Docs\GuidesCli\Command; -use T3Docs\GuidesCli\Generation\DocumentationGenerator; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; +use T3Docs\GuidesCli\Generation\DocumentationGenerator; use T3Docs\VersionHandling\Packagist\ComposerPackage; use T3Docs\VersionHandling\Packagist\PackagistService; /** * You can run this command, for example like * - * ddev exec packages/typo3-guides-cli/bin/typo3-guides init --working-dir=packages/typo3-guides-cli + * ddev exec packages/typo3-guides-cli/bin/typo3-guides init --working-dir=packages/my-extension * */ final class InitCommand extends Command @@ -32,7 +32,8 @@ protected function configure(): void <<<'HELP' This interactive command will help you to setup your project documentation. To do so, it will ask you a few questions about your project and then - create a new documentation project in the working directory (default: current directory). + create a new documentation project in the working directory + (default: The directory from which you run this command). For more information, see: https://docs.typo3.org/permalink/h2document:basic-principles @@ -60,12 +61,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if (file_exists('Documentation/guides.xml')) { - $output->writeln('A "Documentation" directory already exists in this directory'); + $output->writeln('A file "Documentation/guides.xml" already exists in this directory'); return Command::INVALID; } $output->writeln('Welcome to the TYPO3 documentation project setup wizard'); - $output->writeln('This wizard will help you to create a new documentation project in the current directory.'); + $output->writeln('This wizard will help you to create a new documentation project in the current directory (or work directory).'); $output->writeln(''); $composerInfo = $this->getComposerInfo($output); @@ -76,7 +77,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $question = new Question(sprintf('Do you want to use reStructuredText(rst) or MarkDown(md)? [rst, md]: '), 'rst'); $question->setValidator(function ($answer) { - if (is_null($answer) || !in_array($answer, ['rst', 'md'], true)) { + if (is_null($answer) || !in_array($answer, [ + 'rst', + 'md', + ], true)) { throw new \RuntimeException('Choose reStructuredText(rst) or MarkDown(md). '); } return $answer; @@ -127,14 +131,22 @@ protected function execute(InputInterface $input, OutputInterface $output): int $question = new Question('Do you want generate some Documentation? (yes/no) ', 'yes'); $question->setValidator(function ($answer) { - if (!in_array(strtolower($answer), ['yes', 'y', 'no', 'n'], true)) { + if (!in_array(strtolower($answer), [ + 'yes', + 'y', + 'no', + 'n', + ], true)) { throw new \RuntimeException('Please answer with yes, no, y, or n.'); } return strtolower($answer); }); $answer = $helper->ask($input, $output, $question); - $enableExampleFileGeneration = in_array($answer, ['yes', 'y'], true); + $enableExampleFileGeneration = in_array($answer, [ + 'yes', + 'y', + ], true); $question = new Question('Does your extension offer a site set to be included? If so enter the name: '); $siteSet = $helper->ask($input, $output, $question); @@ -210,7 +222,7 @@ private function createValidatedUrlQuestion(string $questionText, mixed $default private function getComposerInfo(OutputInterface $output): ComposerPackage|null { - if (!file_exists('composer.json')) { + if (!is_file('composer.json')) { $output->writeln('No composer.json file was found in the current directory.'); return null; } From 349757c7288475ed149f7cd866206fe5d9a2e380 Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Mon, 16 Dec 2024 11:22:28 +0100 Subject: [PATCH 08/11] [FEATURE] Automatically generate rst or md documentation --- packages/typo3-guides-cli/src/Command/InitCommand.php | 4 ++-- .../src/Generation/DocumentationGenerator.php | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index 34929c499..8f5c5674f 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -155,7 +155,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (is_string($siteSet) && $siteSet !== '') { $question = new Question('Enter the path to your site set: '); $siteSetPath = $helper->ask($input, $output, $question); - if (file_exists($siteSetPath . '/settings.definitions.yaml')) { + if (is_file($siteSetPath . '/settings.definitions.yaml')) { $siteSetDefinition = $siteSetPath . '/settings.definitions.yaml'; } } @@ -235,7 +235,7 @@ private function getComposerInfo(OutputInterface $output): ComposerPackage|null } $composerInfo = (new PackagistService())->getComposerInfo($packageName); - $output->writeln(sprintf("The package %s was found on packagist.org", $composerInfo->getComposerName())); + $output->writeln(sprintf('The package %s was found on packagist.org', $composerInfo->getComposerName())); return $composerInfo; } diff --git a/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php b/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php index 34da408d4..b3fc8a443 100644 --- a/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php +++ b/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php @@ -26,26 +26,27 @@ public function generate(array $data, string $templatesDir, string $outputDir, b return; } - // Generate the Documantation + // Generate the Documentation if ($data['format'] === 'md') { $xmlContent = $twig->render('Index.md.twig', $data); file_put_contents($outputDir . '/Index.md', $xmlContent); return; } - // Directory containing the templates $templatesDir = __DIR__ . '/../../resources/templates/rst'; $files = scandir($templatesDir); if (!$files) { return; } + foreach ($files as $file) { if (pathinfo($file, PATHINFO_EXTENSION) !== 'twig') { continue; } + // Determine the output filename $outputFileName = str_replace('.twig', '', $file); - $outputFilePath = sprintf("%s/%s", $outputDir, $outputFileName); + $outputFilePath = sprintf('%s/%s', $outputDir, $outputFileName); // Check if the output file already exists if (file_exists($outputFilePath)) { @@ -53,7 +54,7 @@ public function generate(array $data, string $templatesDir, string $outputDir, b } // Render the template - $output = $twig->render("rst/$file", $data); + $output = $twig->render(sprintf('rst/%s', $file), $data); // Save the rendered content to the output file file_put_contents($outputFilePath, $output); From 1f4d7438390f25d7652c0df460e489cf6b67b1f9 Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Mon, 16 Dec 2024 11:24:31 +0100 Subject: [PATCH 09/11] [FEATURE] Automatically generate rst or md documentation --- packages/typo3-guides-cli/src/Command/InitCommand.php | 2 +- .../typo3-guides-cli/src/Generation/DocumentationGenerator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index 8f5c5674f..efe42a754 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -60,7 +60,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::INVALID; } - if (file_exists('Documentation/guides.xml')) { + if (is_file('Documentation/guides.xml')) { $output->writeln('A file "Documentation/guides.xml" already exists in this directory'); return Command::INVALID; } diff --git a/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php b/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php index b3fc8a443..a3a6af124 100644 --- a/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php +++ b/packages/typo3-guides-cli/src/Generation/DocumentationGenerator.php @@ -49,7 +49,7 @@ public function generate(array $data, string $templatesDir, string $outputDir, b $outputFilePath = sprintf('%s/%s', $outputDir, $outputFileName); // Check if the output file already exists - if (file_exists($outputFilePath)) { + if (is_file($outputFilePath)) { continue; } From ae4ff0cfedea425a40b9a72f2b2638ee3184b2ef Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Mon, 16 Dec 2024 11:25:43 +0100 Subject: [PATCH 10/11] [FEATURE] Automatically generate rst or md documentation --- packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php | 4 +--- packages/typo3-guides-cli/src/Command/InitCommand.php | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php b/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php index 110c5bde0..12e062c75 100644 --- a/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php +++ b/packages/typo3-docs-theme/src/TextRoles/ComposerTextRole.php @@ -15,9 +15,7 @@ final class ComposerTextRole implements TextRole public function __construct( private readonly PackagistService $packagistService, private readonly LoggerInterface $logger, - ) - { - } + ) {} public function getName(): string { diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index efe42a754..6b1bee815 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -46,6 +46,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($input->getOption('working-dir')) { $workdir = $input->getOption('working-dir'); assert(is_string($workdir)); + $workdir = (string) $workdir; if (chdir($workdir)) { $output->writeln('Changed working directory to ' . getcwd() . ''); From 2fe399e7c21bab34551df28439ce9c45c98bb496 Mon Sep 17 00:00:00 2001 From: Lina Wolf <48202465+linawolf@users.noreply.github.com> Date: Mon, 16 Dec 2024 19:02:07 +0100 Subject: [PATCH 11/11] Update packages/typo3-guides-cli/src/Command/InitCommand.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stefan Frömken <123929835+sfroemkenjw@users.noreply.github.com> --- packages/typo3-guides-cli/src/Command/InitCommand.php | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/typo3-guides-cli/src/Command/InitCommand.php b/packages/typo3-guides-cli/src/Command/InitCommand.php index 6b1bee815..4b2def077 100644 --- a/packages/typo3-guides-cli/src/Command/InitCommand.php +++ b/packages/typo3-guides-cli/src/Command/InitCommand.php @@ -75,7 +75,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** @var QuestionHelper $helper */ $helper = $this->getHelper('question'); - $question = new Question(sprintf('Do you want to use reStructuredText(rst) or MarkDown(md)? [rst, md]: '), 'rst'); $question->setValidator(function ($answer) { if (is_null($answer) || !in_array($answer, [