Skip to content

Commit 05f7960

Browse files
committed
1 parent 58ed5c7 commit 05f7960

File tree

6 files changed

+64
-27
lines changed

6 files changed

+64
-27
lines changed

lib/Parser/DocumentParser.php

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ final class DocumentParser
109109
/** @var string|null */
110110
private $listMarker = null;
111111

112+
/** @var array{name: string,body: string,offset: int}|null */
113+
private $fieldOption = null;
114+
112115
/**
113116
* @param Directive[] $directives
114117
*/
@@ -454,20 +457,37 @@ private function parseLine(string $line): bool
454457
break;
455458

456459
case State::DIRECTIVE:
457-
if (! $this->isDirectiveOption($line)) {
458-
if (! $this->lineChecker->isDirective($line)) {
459-
$directive = $this->getCurrentDirective();
460-
$this->isCode = $directive !== null ? $directive->wantCode() : false;
461-
$this->setState(State::BEGIN);
460+
if ($this->lineChecker->isDirective($line) && $this->directive === null) {
461+
$this->flush();
462+
$this->initDirective($line);
462463

463-
return false;
464+
break;
465+
}
466+
467+
if ($this->fieldOption !== null && $this->lineChecker->isBlockLine($line, $this->fieldOption['offset'])) {
468+
$line = ltrim($line);
469+
$this->fieldOption['body'] .= strlen($line) > 0 ? ' '.$line : '';
470+
471+
break;
472+
}
473+
474+
if ($this->lineChecker->isFieldList($line)) {
475+
if ($this->fieldOption !== null) {
476+
$this->directive->setOption($this->fieldOption['name'], $this->fieldOption['body']);
464477
}
465478

466-
$this->flush();
467-
$this->initDirective($line);
479+
$fieldData = $this->lineDataParser->parseFieldList($line);
480+
$fieldData['offset'] = strlen($fieldData['offset']) + 1;
481+
$this->fieldOption = $fieldData;
482+
483+
break;
468484
}
469485

470-
break;
486+
$directive = $this->getCurrentDirective();
487+
$this->isCode = $directive !== null ? $directive->wantCode() : false;
488+
$this->setState(State::BEGIN);
489+
490+
return false;
471491

472492
default:
473493
$this->environment->getErrorManager()->error('Parser ended in an unexcepted state');
@@ -599,6 +619,11 @@ private function flush(): void
599619
if ($this->directive !== null) {
600620
$currentDirective = $this->getCurrentDirective();
601621

622+
if ($this->fieldOption !== null) {
623+
$this->directive->setOption($this->fieldOption['name'], $this->fieldOption['body']);
624+
$this->fieldOption = null;
625+
}
626+
602627
if ($currentDirective !== null) {
603628
try {
604629
$currentDirective->process(
@@ -646,23 +671,6 @@ private function getCurrentDirective(): ?Directive
646671
return $this->directives[$name];
647672
}
648673

649-
private function isDirectiveOption(string $line): bool
650-
{
651-
if ($this->directive === null) {
652-
return false;
653-
}
654-
655-
$directiveOption = $this->lineDataParser->parseDirectiveOption($line);
656-
657-
if ($directiveOption === null) {
658-
return false;
659-
}
660-
661-
$this->directive->setOption($directiveOption->getName(), $directiveOption->getValue());
662-
663-
return true;
664-
}
665-
666674
private function initDirective(string $line): bool
667675
{
668676
$parserDirective = $this->lineDataParser->parseDirective($line);

lib/Parser/LineChecker.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ public function isDirective(string $line): bool
122122
return preg_match('/^\.\. (\|(.+)\| |)([^\s]+)::( (.*)|)$/mUsi', $line) > 0;
123123
}
124124

125+
public function isFieldList(string $line, int $offset = 0): bool
126+
{
127+
return preg_match('/:.+: .+/', $line) > 0;
128+
}
129+
125130
/**
126131
* Check if line is an indented one.
127132
*

lib/Parser/LineDataParser.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,16 @@ public function parseDefinitionList(array $lines): DefinitionList
233233

234234
return new DefinitionList($definitionList);
235235
}
236+
237+
/**
238+
* @return array{offset: string, name: string, body: string}
239+
*/
240+
public function parseFieldList(string $line): ?array
241+
{
242+
if (preg_match('/^(?P<offset>\s+):(?P<name>.+): +(?P<body>.+)$/', $line, $match) > 0) {
243+
return $match;
244+
}
245+
246+
return null;
247+
}
236248
}

tests/Functional/tests/figure/figure.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<figure>
2-
<img src="foo.jpg" width="100" />
2+
<img src="foo.jpg" width="100" alt="Field options might use more than one line" />
33
<figcaption>
44
<p>This is a foo!</p>
55
</figcaption>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
.. figure:: foo.jpg
22
:width: 100
3+
:alt: Field options might use
4+
more than one line
35

46
This is a foo!

tests/Parser/LineCheckerTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,14 @@ public function testIsDefinitionListEnded(): void
9191
self::assertFalse($this->lineChecker->isDefinitionListEnded('Term', ' Definition'));
9292
self::assertFalse($this->lineChecker->isDefinitionListEnded('', ' Definition'));
9393
}
94+
95+
public function testIsFieldList(): void
96+
{
97+
self::assertTrue($this->lineChecker->isFieldList(':Date: 2001-08-16'));
98+
self::assertTrue($this->lineChecker->isFieldList(' :Date: 2001-08-16'));
99+
self::assertTrue($this->lineChecker->isFieldList(':Date published: 2001-08-16'));
100+
self::assertTrue($this->lineChecker->isFieldList(':Date:published: 2001-08-16'));
101+
self::assertFalse($this->lineChecker->isFieldList('Date: 2001-08-16'));
102+
self::assertFalse($this->lineChecker->isFieldList(':Date:'));
103+
}
94104
}

0 commit comments

Comments
 (0)