Skip to content

Commit 5242137

Browse files
authored
Merge pull request #1257 from phpDocumentor/fix/enumerated-list
Allow offset on lists
2 parents 80a11f8 + 6e3e42f commit 5242137

File tree

3 files changed

+66
-9
lines changed

3 files changed

+66
-9
lines changed

packages/guides-restructured-text/src/RestructuredText/Parser/Productions/EnumeratedListRule.php

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@
2727
use function ltrim;
2828
use function mb_strlen;
2929
use function mb_substr;
30+
use function ord;
3031
use function preg_match;
3132
use function sprintf;
3233
use function str_ends_with;
3334
use function str_starts_with;
3435
use function strlen;
3536
use function strpos;
37+
use function strtolower;
38+
use function strtoupper;
3639
use function trim;
3740

3841
/**
@@ -119,8 +122,8 @@ public function apply(BlockContext $blockContext, CompoundNode|null $on = null):
119122
$start = null;
120123
$orderType = null;
121124
if (isset($items[0])) {
122-
$start = $items[0]->getOrderNumber();
123125
$orderType = $items[0]->getOrderType();
126+
$start = (string) $this->getStartValue($items[0]->getOrderNumber(), $orderType);
124127
}
125128

126129
return new ListNode($items, true, $start, $orderType);
@@ -245,4 +248,58 @@ private function markerSuffix(string $marker): string
245248

246249
return '';
247250
}
251+
252+
private function getStartValue(string|null $firstItemNumber, string|null $orderType): int|null
253+
{
254+
if ($firstItemNumber === null) {
255+
return null;
256+
}
257+
258+
if ($orderType === 'auto_number' . $this->markerSuffix($firstItemNumber)) {
259+
return null;
260+
}
261+
262+
if (preg_match('/^\d+$/', $firstItemNumber)) {
263+
return (int) $firstItemNumber;
264+
}
265+
266+
if (preg_match('/^' . self::ROMAN_NUMBER . '$/i', $firstItemNumber, $m)) {
267+
$roman = strtoupper($m[1]);
268+
$map = [
269+
'M' => 1000,
270+
'CM' => 900,
271+
'D' => 500,
272+
'CD' => 400,
273+
'C' => 100,
274+
'XC' => 90,
275+
'L' => 50,
276+
'XL' => 40,
277+
'X' => 10,
278+
'IX' => 9,
279+
'V' => 5,
280+
'IV' => 4,
281+
'I' => 1,
282+
];
283+
284+
$number = 0;
285+
$i = 0;
286+
while ($i < strlen($roman)) {
287+
foreach ($map as $symbol => $value) {
288+
if (str_starts_with(mb_substr($roman, $i), $symbol)) {
289+
$number += $value;
290+
$i += strlen($symbol);
291+
break;
292+
}
293+
}
294+
}
295+
296+
return $number;
297+
}
298+
299+
if (preg_match('/^[a-z]$/i', $firstItemNumber)) {
300+
return ord(strtolower($firstItemNumber)) - ord('a') + 1;
301+
}
302+
303+
return 1;
304+
}
248305
}

tests/Functional/tests/list-enumerated/list-enumerated.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
<li value="2">Second item</li>
2323
</ol>
2424
<p>This is an enumerated list using letters:</p>
25-
<ol start="a" type="a">
26-
<li value="a">First</li>
27-
<li value="b">Second</li>
28-
<li value="c">Third</li>
25+
<ol start="7" type="a">
26+
<li value="g">First</li>
27+
<li value="h">Second</li>
28+
<li value="i">Third</li>
2929
</ol>
3030
<p>This is an roman list using letters:</p>
31-
<ol start="I" type="i">
31+
<ol start="1" type="i">
3232
<li value="I">First</li>
3333
<li value="II">Second</li>
3434
<li value="III">Third</li>

tests/Functional/tests/list-enumerated/list-enumerated.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ Using right-parenthesis:
2323

2424
This is an enumerated list using letters:
2525

26-
a. First
27-
b. Second
28-
c. Third
26+
g. First
27+
h. Second
28+
i. Third
2929

3030
This is an roman list using letters:
3131

0 commit comments

Comments
 (0)