/** * Execute the console command. * * @return false|null */ public function handle() { $outputPath = $this->option('location'); $documentarian = new Documentarian(); if (!is_dir($outputPath)) { $this->error('There is no generated documentation available at ' . $outputPath . '.'); return false; } $this->info('Updating API HTML code'); $documentarian->generate($outputPath); $this->info('Wrote HTML documentation to: ' . $outputPath . '/public/index.html'); }
public function test_can_generate_html() { $outputDir = __DIR__ . '/output'; $assertionDir = __DIR__ . '/assertions'; $documentarian = new Documentarian(); $documentarian->create($outputDir); // test1.md - no frontmatter yaml present copy(__DIR__ . '/files/test1.md', $outputDir . '/source/index.md'); $documentarian->generate($outputDir); $this->assertFileEquals($outputDir . '/index.html', $assertionDir . '/test1.html'); // test2.md - valid frontmatter yaml copy(__DIR__ . '/files/test2.md', $outputDir . '/source/index.md'); $documentarian->generate($outputDir); $this->assertFileEquals($outputDir . '/index.html', $assertionDir . '/test2.html'); // test3.md - include and parse additional markdown files copy(__DIR__ . '/files/test3.md', $outputDir . '/source/index.md'); $documentarian->generate($outputDir); $this->assertFileEquals($outputDir . '/index.html', $assertionDir . '/test3.html'); // test4.md - ignore not existing include file copy(__DIR__ . '/files/test4.md', $outputDir . '/source/index.md'); $documentarian->generate($outputDir); $this->assertFileEquals($outputDir . '/index.html', $assertionDir . '/test4.html'); }
/** * @param Collection $parsedRoutes * * @return void */ private function writeMarkdown($parsedRoutes) { $outputPath = $this->option('output'); $targetFile = $outputPath . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR . 'index.md'; $compareFile = $outputPath . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR . '.compare.md'; $infoText = view('apidoc::partials.info')->with('outputPath', ltrim($outputPath, 'public/'))->with('showPostmanCollectionButton', !$this->option('noPostmanCollection')); $parsedRouteOutput = $parsedRoutes->map(function ($routeGroup) { return $routeGroup->map(function ($route) { $route['output'] = (string) view('apidoc::partials.route')->with('parsedRoute', $route); return $route; }); }); $frontmatter = view('apidoc::partials.frontmatter'); /* * In case the target file already exists, we should check if the documentation was modified * and skip the modified parts of the routes. */ if (file_exists($targetFile) && file_exists($compareFile)) { $generatedDocumentation = file_get_contents($targetFile); $compareDocumentation = file_get_contents($compareFile); if (preg_match('/<!-- START_INFO -->(.*)<!-- END_INFO -->/is', $generatedDocumentation, $generatedInfoText)) { $infoText = trim($generatedInfoText[1], "\n"); } if (preg_match('/---(.*)---\\s<!-- START_INFO -->/is', $generatedDocumentation, $generatedFrontmatter)) { $frontmatter = trim($generatedFrontmatter[1], "\n"); } $parsedRouteOutput->transform(function ($routeGroup) use($generatedDocumentation, $compareDocumentation) { return $routeGroup->transform(function ($route) use($generatedDocumentation, $compareDocumentation) { if (preg_match('/<!-- START_' . $route['id'] . ' -->(.*)<!-- END_' . $route['id'] . ' -->/is', $generatedDocumentation, $routeMatch)) { $routeDocumentationChanged = preg_match('/<!-- START_' . $route['id'] . ' -->(.*)<!-- END_' . $route['id'] . ' -->/is', $compareDocumentation, $compareMatch) && $compareMatch[1] !== $routeMatch[1]; if ($routeDocumentationChanged === false || $this->option('force')) { if ($routeDocumentationChanged) { $this->warn('Discarded manual changes for route [' . implode(',', $route['methods']) . '] ' . $route['uri']); } } else { $this->warn('Skipping modified route [' . implode(',', $route['methods']) . '] ' . $route['uri']); $route['modified_output'] = $routeMatch[0]; } } return $route; }); }); } $documentarian = new Documentarian(); $markdown = view('apidoc::documentarian')->with('writeCompareFile', false)->with('frontmatter', $frontmatter)->with('infoText', $infoText)->with('outputPath', $this->option('output'))->with('showPostmanCollectionButton', !$this->option('noPostmanCollection'))->with('parsedRoutes', $parsedRouteOutput); if (!is_dir($outputPath)) { $documentarian->create($outputPath); } // Write output file file_put_contents($targetFile, $markdown); // Write comparable markdown file $compareMarkdown = view('apidoc::documentarian')->with('writeCompareFile', true)->with('frontmatter', $frontmatter)->with('infoText', $infoText)->with('outputPath', $this->option('output'))->with('showPostmanCollectionButton', !$this->option('noPostmanCollection'))->with('parsedRoutes', $parsedRouteOutput); file_put_contents($compareFile, $compareMarkdown); $this->info('Wrote index.md to: ' . $outputPath); $this->info('Generating API HTML code'); $documentarian->generate($outputPath); $this->info('Wrote HTML documentation to: ' . $outputPath . '/public/index.html'); if ($this->option('noPostmanCollection') !== true) { $this->info('Generating Postman collection'); file_put_contents($outputPath . DIRECTORY_SEPARATOR . 'collection.json', $this->generatePostmanCollection($parsedRoutes)); } }