From b902913220d05e1d4a277706de3e86ef563b747c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 10 Aug 2015 13:18:27 +0200 Subject: [PATCH] doc: Support setext-style only headers Setext-style used to work before too but only if an atx-style header comes first. --- modules/doc/library/Doc/DocParser.php | 46 ++++++++++++++++++++------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index a35ebc05b..038ae3e02 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -3,6 +3,7 @@ namespace Icinga\Module\Doc; +use CachingIterator; use LogicException; use SplStack; use Icinga\Data\Tree\SimpleTree; @@ -15,6 +16,20 @@ use Icinga\Module\Doc\Exception\DocException; */ class DocParser { + /** + * Internal identifier for Atx-style headers + * + * @var int + */ + const HEADER_ATX = 1; + + /** + * Internal identifier for Setext-style headers + * + * @var int + */ + const HEADER_SETEXT = 2; + /** * Path to the documentation * @@ -70,11 +85,11 @@ class DocParser * Extract atx- or setext-style headers from the given lines * * @param string $line - * @param string $lastLine + * @param string $nextLine * * @return array|null An array containing the header and the header level or null if there's nothing to extract */ - protected function extractHeader($line, $lastLine) + protected function extractHeader($line, $nextLine) { if (! $line) { return null; @@ -90,13 +105,14 @@ class DocParser if (! $header) { return null; } + $headerStyle = static::HEADER_ATX; } elseif ( - $line - && ($line[0] === '=' || $line[0] === '-') - && preg_match('/^[=-]+\s*$/', $line, $match) === 1 + $nextLine + && ($nextLine[0] === '=' || $nextLine[0] === '-') + && preg_match('/^[=-]+\s*$/', $nextLine, $match) === 1 ) { // Setext - $header = trim($lastLine); + $header = trim($line); if (! $header) { return null; } @@ -105,6 +121,7 @@ class DocParser } else { $level = 2; } + $headerStyle = static::HEADER_SETEXT; } if ($header === null) { return null; @@ -117,7 +134,7 @@ class DocParser } else { $id = null; } - return array($header, $id, $level); + return array($header, $id, $level, $headerStyle); } /** @@ -133,10 +150,13 @@ class DocParser /** @var $fileInfo \SplFileInfo */ $file = $fileInfo->openFile(); $lastLine = null; - foreach ($file as $line) { - $header = $this->extractHeader($line, $lastLine); + $cachingIterator = new CachingIterator($file, CachingIterator::TOSTRING_USE_CURRENT); + for ($cachingIterator->rewind(); $line = $cachingIterator->valid(); $cachingIterator->next()) { + $fileIterator = $cachingIterator->getInnerIterator(); + $line = $cachingIterator->current(); + $header = $this->extractHeader($line, $fileIterator->valid() ? $fileIterator->current() : null); if ($header !== null) { - list($title, $id, $level) = $header; + list($title, $id, $level, $headerStyle) = $header; while (! $stack->isEmpty() && $stack->top()->getLevel() >= $level) { $stack->pop(); } @@ -169,14 +189,16 @@ class DocParser $tree->addChild($section, $stack->top()); } $stack->push($section); + if ($headerStyle === static::HEADER_SETEXT) { + $cachingIterator->next(); + continue; + } } else { if ($stack->isEmpty()) { throw new LogicException('Heading required'); } $stack->top()->appendContent($line); } - // Save last line for setext-style headers - $lastLine = $line; } } return $tree;