Skip to content

Commit f1aa6ef

Browse files
authored
Merge pull request #690 from phpDocumentor/feature/emphasize-lines
[FEATURE] Support emphasize-lines in code-block directive
2 parents e33cb9f + 03e2de4 commit f1aa6ef

File tree

6 files changed

+71
-4
lines changed

6 files changed

+71
-4
lines changed

packages/guides-restructured-text/src/RestructuredText/Directives/CodeBlockDirective.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
use phpDocumentor\Guides\RestructuredText\Parser\BlockContext;
1111
use phpDocumentor\Guides\RestructuredText\Parser\Directive;
1212
use phpDocumentor\Guides\RestructuredText\Parser\DirectiveOption;
13+
use Psr\Log\LoggerInterface;
1314

15+
use function preg_match;
1416
use function trim;
1517

1618
/**
@@ -26,8 +28,13 @@
2628
*/
2729
class CodeBlockDirective extends BaseDirective
2830
{
29-
public function __construct(private readonly CodeNodeOptionMapper $codeNodeOptionMapper)
30-
{
31+
/** @see https://regex101.com/r/I3KttH/1 */
32+
public const LINE_NUMBER_RANGES_REGEX = '/^\d+(-\d+)?(?:,\s*\d+(-\d+)?)*$/';
33+
34+
public function __construct(
35+
private readonly LoggerInterface $logger,
36+
private readonly CodeNodeOptionMapper $codeNodeOptionMapper,
37+
) {
3138
}
3239

3340
public function getName(): string
@@ -58,6 +65,7 @@ public function process(
5865

5966
$this->setStartingLineNumberBasedOnOptions($directive->getOptions(), $node);
6067
$this->setCaptionBasedOnOptions($directive->getOptions(), $node);
68+
$this->setEmphasizeLinesBasedOnOptions($blockContext, $directive->getOptions(), $node);
6169
$this->codeNodeOptionMapper->apply($node, $directive->getOptions());
6270

6371
if ($directive->getVariable() !== '') {
@@ -101,4 +109,19 @@ private function setCaptionBasedOnOptions(array $options, CodeNode $node): void
101109

102110
$node->setCaption($caption);
103111
}
112+
113+
/** @param DirectiveOption[] $options */
114+
private function setEmphasizeLinesBasedOnOptions(BlockContext $blockContext, array $options, CodeNode $node): void
115+
{
116+
$emphasizeLines = null;
117+
if (isset($options['emphasize-lines'])) {
118+
$emphasizeLines = (string) $options['emphasize-lines']->getValue();
119+
if (!preg_match(self::LINE_NUMBER_RANGES_REGEX, $emphasizeLines)) {
120+
// Input does not fit the pattern, log a warning
121+
$this->logger->warning('Invalid value for option emphasize-lines in code-block directive. Expected format: \'1-5, 7, 33\'', $blockContext->getLoggerInformation());
122+
}
123+
}
124+
125+
$node->setEmphasizeLines($emphasizeLines);
126+
}
104127
}

packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public function testCodeBlockValue(string $input, string $expectedValue): void
103103
$this->givenInlineMarkupRule(),
104104
new Logger('test'),
105105
new GeneralDirective(new DirectiveContentRule(new RuleContainer())),
106-
[$this->directiveHandler, new CodeBlockDirective(new CodeNodeOptionMapper())],
106+
[$this->directiveHandler, new CodeBlockDirective(new Logger('test'), new CodeNodeOptionMapper())],
107107
);
108108
$context = $this->createContext($input);
109109
$node = $this->rule->apply($context);

packages/guides/resources/template/html/body/code.html.twig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@
77
<span class="caption-text">{{ node.caption }}</span>
88
</div>
99
{%- endif -%}
10-
<pre{% if node.classes %} class="{{ node.classesString }}"{% endif %}><code class="language-{{ node.language }}{{ node.startingLineNumber ? ' line-numbers' }}" {%- if node.startingLineNumber %} data-start="{{ node.startingLineNumber }}"{% endif %}>{{ node.value }}</code></pre>
10+
<pre{% if node.classes %} class="{{ node.classesString }}"{% endif %}><code class="language-{{ node.language }}{{ node.startingLineNumber ? ' line-numbers' }}"
11+
{%- if node.startingLineNumber %} data-start="{{ node.startingLineNumber }}"{% endif -%}
12+
{%- if node.emphasizeLines %} data-emphasize-lines="{{ node.emphasizeLines }}"{% endif -%}>{{ node.value }}</code></pre>
1113
{%- endif -%}

packages/guides/src/Nodes/CodeNode.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class CodeNode extends TextNode
2222

2323
private string|null $caption = null;
2424

25+
private string|null $emphasizeLines = null;
26+
2527
/** @param string[] $lines */
2628
public function __construct(array $lines, protected string|null $language = null)
2729
{
@@ -57,4 +59,14 @@ public function setCaption(string|null $caption): void
5759
{
5860
$this->caption = $caption;
5961
}
62+
63+
public function getEmphasizeLines(): string|null
64+
{
65+
return $this->emphasizeLines;
66+
}
67+
68+
public function setEmphasizeLines(string|null $emphasizeLines): void
69+
{
70+
$this->emphasizeLines = $emphasizeLines;
71+
}
6072
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Title</title>
5+
6+
</head>
7+
<body>
8+
<div class="section" id="title">
9+
<h1>Title</h1>
10+
11+
<pre><code class="language-python" data-emphasize-lines="3,5">def some_function():
12+
interesting = False
13+
print(&#039;This line is highlighted.&#039;)
14+
print(&#039;This one is not...&#039;)
15+
print(&#039;...but this one is.&#039;)</code></pre>
16+
</div>
17+
18+
</body>
19+
</html>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Title
2+
=====
3+
4+
.. code-block:: python
5+
:emphasize-lines: 3,5
6+
7+
def some_function():
8+
interesting = False
9+
print('This line is highlighted.')
10+
print('This one is not...')
11+
print('...but this one is.')

0 commit comments

Comments
 (0)