diff --git a/bin/docs-builder b/bin/docs-builder index be6975a..758582d 100755 --- a/bin/docs-builder +++ b/bin/docs-builder @@ -16,7 +16,7 @@ foreach ($autoloadFiles as $autoloadFile) { use Symfony\Component\Console\Input\ArgvInput; use SymfonyDocsBuilder\Application; -$input = new ArgvInput(); +$input = new ArgvInput(); $version = $input->getParameterOption(['--symfony-version'], false === getenv('SYMFONY_VERSION') ? 'master' : getenv('SYMFONY_VERSION')); if (!$version) { diff --git a/src/Command/BuildDocsCommand.php b/src/Command/BuildDocsCommand.php index d483045..8442e96 100644 --- a/src/Command/BuildDocsCommand.php +++ b/src/Command/BuildDocsCommand.php @@ -49,93 +49,77 @@ public function __construct(BuildConfig $buildConfig) protected function configure() { - parent::configure(); - $this ->addArgument('source-dir', InputArgument::OPTIONAL, 'RST files Source directory', getcwd()) - ->addArgument('output-dir', InputArgument::OPTIONAL, 'HTML files output directory') - ->addOption( - 'parse-sub-path', - null, - InputOption::VALUE_OPTIONAL, - 'Parse only given sub directory and combine it into a single file (directory relative from source-dir)', - '' - ) - ->addOption( - 'output-json', - null, - InputOption::VALUE_NONE, - 'If provided, .fjson metadata files will be written' - ) - ->addOption( - 'disable-cache', - null, - InputOption::VALUE_NONE, - 'If provided, caching meta will be disabled' - ) - ->addOption( - 'save-errors', - null, - InputOption::VALUE_REQUIRED, - 'Path where any errors should be saved' - ) - ->addOption( - 'error-output-format', - null, - InputOption::VALUE_REQUIRED, - 'The output format for errors on std out', - Configuration::OUTPUT_FORMAT_CONSOLE - ) - ->addOption( - 'no-theme', - null, - InputOption::VALUE_NONE, - 'Use the default theme instead of the styled one' - ) - ->addOption( - 'fail-on-errors', - null, - InputOption::VALUE_NONE, - 'Return a non-zero code if there are errors/warnings' - ) + ->addArgument('output-dir', InputArgument::OPTIONAL, 'HTML files output directory', rtrim(getcwd(), '/').'/html') + + ->addOption('images-dir', null, InputOption::VALUE_REQUIRED, 'Images files output directory') + ->addOption('config', null, InputOption::VALUE_REQUIRED, 'Path to the config file') + + ->addOption('disable-cache', null, InputOption::VALUE_NONE, 'If provided, caching meta will be disabled') + ->addOption('parse-sub-path', null, InputOption::VALUE_REQUIRED, 'Parse only given sub directory and combine it into a single file (directory relative from source-dir)', '') + ->addOption('output-json', null, InputOption::VALUE_NONE, 'If provided, .fjson metadata files will be written') + ->addOption('no-theme', null, InputOption::VALUE_NONE, 'Use the default theme instead of the styled one') + + ->addOption('fail-on-errors', null, InputOption::VALUE_NONE, 'Return a non-zero code if there are errors/warnings') + ->addOption('save-errors', null, InputOption::VALUE_REQUIRED, 'Path where any errors should be saved') + ->addOption('error-output-format', null, InputOption::VALUE_REQUIRED, 'The output format for errors on std out', Configuration::OUTPUT_FORMAT_CONSOLE) ; } protected function initialize(InputInterface $input, OutputInterface $output) { + $filesystem = new Filesystem(); $this->io = new SymfonyStyle($input, $output); + if ($input->getOption('disable-cache')) { + $this->buildConfig->disableBuildCache(); + } + $sourceDir = $input->getArgument('source-dir'); - if (!file_exists($sourceDir)) { + if (!$filesystem->exists($sourceDir)) { throw new \InvalidArgumentException(sprintf('RST source directory "%s" does not exist', $sourceDir)); } $this->buildConfig->setContentDir($sourceDir); - $filesystem = new Filesystem(); - $htmlOutputDir = $input->getArgument('output-dir') ?? rtrim(getcwd(), '/').'/html'; - if ($input->getOption('disable-cache') && $filesystem->exists($htmlOutputDir)) { + $htmlOutputDir = $input->getArgument('output-dir'); + if (!$this->buildConfig->isBuildCacheEnabled() && $filesystem->exists($htmlOutputDir)) { $filesystem->remove($htmlOutputDir); } $filesystem->mkdir($htmlOutputDir); $this->buildConfig->setOutputDir($htmlOutputDir); + $imgOutputDir = $input->getOption('images-dir'); + if ($imgOutputDir) { + if (!$this->buildConfig->isBuildCacheEnabled() && $filesystem->exists($imgOutputDir)) { + $filesystem->remove($imgOutputDir); + } + $this->buildConfig->setImageDir($imgOutputDir); + } + $parseSubPath = $input->getOption('parse-sub-path'); if ($parseSubPath && $input->getOption('output-json')) { throw new \InvalidArgumentException('Cannot pass both --parse-sub-path and --output-json options.'); } - if (!file_exists($sourceDir.'/'.$parseSubPath)) { + if (!$filesystem->exists($sourceDir.'/'.$parseSubPath)) { throw new \InvalidArgumentException(sprintf('Given "parse-sub-path" directory "%s" does not exist', $parseSubPath)); } $this->buildConfig->setSubdirectoryToBuild($parseSubPath); - if ($input->getOption('disable-cache')) { - $this->buildConfig->disableBuildCache(); + $this->buildConfig->setTheme($input->getOption('no-theme') ? Configuration::THEME_DEFAULT : 'rtd'); + + $configFileParser = new ConfigFileParser($this->buildConfig); + $configPath = $input->getOption('config'); + if ($configPath && !file_exists($configPath)) { + throw new \RuntimeException(sprintf('No config file present at %s', $configPath)); } - $this->buildConfig->setTheme($input->getOption('no-theme') ? Configuration::THEME_DEFAULT : 'rtd'); + if (!$configPath && !file_exists($configPath = $sourceDir.'/docs.json')) { + return; + } - $configFileParser = new ConfigFileParser($this->buildConfig, $output); - $configFileParser->processConfigFile($sourceDir); + $this->io->writeln(sprintf('Loading config file: %s', $configPath)); + $configFileParser->processConfigFile($configPath); } protected function execute(InputInterface $input, OutputInterface $output): int @@ -146,6 +130,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $configuration = $builder->getConfiguration(); $configuration->setOutputFormat($input->getOption('error-output-format')); + $configuration->silentOnError(false); $this->addProgressListener($configuration->getEventManager()); $builder->build( @@ -184,7 +169,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->io->success('Build completed with warnings'); if ($input->getOption('fail-on-errors')) { - return 1; + return Command::FAILURE; } } else { $this->io->success('Build completed successfully!'); diff --git a/src/ConfigFileParser.php b/src/ConfigFileParser.php index 6a79134..98c09bd 100644 --- a/src/ConfigFileParser.php +++ b/src/ConfigFileParser.php @@ -2,38 +2,37 @@ namespace SymfonyDocsBuilder; -use Symfony\Component\Console\Output\OutputInterface; - /** * Parses the docs.json config file */ class ConfigFileParser { private $buildConfig; - private $output; - public function __construct(BuildConfig $buildConfig, OutputInterface $output) + public function __construct(BuildConfig $buildConfig) { $this->buildConfig = $buildConfig; - $this->output = $output; } - public function processConfigFile(string $sourceDir): void + public function processConfigFile(string $configPath): void { - $configPath = $sourceDir.'/docs.json'; if (!file_exists($configPath)) { - $this->output->writeln(sprintf('No config file present at %s', $configPath)); + throw new \RuntimeException(sprintf('No config file present at %s', $configPath)); return; } - $this->output->writeln(sprintf('Loading config file: %s', $configPath)); $configData = json_decode(file_get_contents($configPath), true); $exclude = $configData['exclude'] ?? []; $this->buildConfig->setExcludedPaths($exclude); unset($configData['exclude']); + if ($sfVersion = $configData['symfony-version'] ?? false) { + $this->buildConfig->setSymfonyVersion($sfVersion); + } + unset($configData['symfony-version']); + if (count($configData) > 0) { throw new \Exception(sprintf('Unsupported keys in docs.json: %s', implode(', ', array_keys($configData)))); }