From 03e2de471269381787dd254db80f6b1acdf152b9 Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Mon, 20 Nov 2023 16:16:23 +0100 Subject: [PATCH] [FEATURE] Support emphasize-lines in code-block directive --- .../Directives/CodeBlockDirective.php | 27 +++++++++++++++++-- .../Parser/Productions/DirectiveRuleTest.php | 2 +- .../template/html/body/code.html.twig | 4 ++- packages/guides/src/Nodes/CodeNode.php | 12 +++++++++ .../code-block-emphasize/expected/index.html | 19 +++++++++++++ .../code/code-block-emphasize/input/index.rst | 11 ++++++++ 6 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 tests/Integration/tests/code/code-block-emphasize/expected/index.html create mode 100644 tests/Integration/tests/code/code-block-emphasize/input/index.rst diff --git a/packages/guides-restructured-text/src/RestructuredText/Directives/CodeBlockDirective.php b/packages/guides-restructured-text/src/RestructuredText/Directives/CodeBlockDirective.php index 056604b30..f47cd07e6 100644 --- a/packages/guides-restructured-text/src/RestructuredText/Directives/CodeBlockDirective.php +++ b/packages/guides-restructured-text/src/RestructuredText/Directives/CodeBlockDirective.php @@ -10,7 +10,9 @@ use phpDocumentor\Guides\RestructuredText\Parser\BlockContext; use phpDocumentor\Guides\RestructuredText\Parser\Directive; use phpDocumentor\Guides\RestructuredText\Parser\DirectiveOption; +use Psr\Log\LoggerInterface; +use function preg_match; use function trim; /** @@ -26,8 +28,13 @@ */ class CodeBlockDirective extends BaseDirective { - public function __construct(private readonly CodeNodeOptionMapper $codeNodeOptionMapper) - { + /** @see https://regex101.com/r/I3KttH/1 */ + public const LINE_NUMBER_RANGES_REGEX = '/^\d+(-\d+)?(?:,\s*\d+(-\d+)?)*$/'; + + public function __construct( + private readonly LoggerInterface $logger, + private readonly CodeNodeOptionMapper $codeNodeOptionMapper, + ) { } public function getName(): string @@ -58,6 +65,7 @@ public function process( $this->setStartingLineNumberBasedOnOptions($directive->getOptions(), $node); $this->setCaptionBasedOnOptions($directive->getOptions(), $node); + $this->setEmphasizeLinesBasedOnOptions($blockContext, $directive->getOptions(), $node); $this->codeNodeOptionMapper->apply($node, $directive->getOptions()); if ($directive->getVariable() !== '') { @@ -101,4 +109,19 @@ private function setCaptionBasedOnOptions(array $options, CodeNode $node): void $node->setCaption($caption); } + + /** @param DirectiveOption[] $options */ + private function setEmphasizeLinesBasedOnOptions(BlockContext $blockContext, array $options, CodeNode $node): void + { + $emphasizeLines = null; + if (isset($options['emphasize-lines'])) { + $emphasizeLines = (string) $options['emphasize-lines']->getValue(); + if (!preg_match(self::LINE_NUMBER_RANGES_REGEX, $emphasizeLines)) { + // Input does not fit the pattern, log a warning + $this->logger->warning('Invalid value for option emphasize-lines in code-block directive. Expected format: \'1-5, 7, 33\'', $blockContext->getLoggerInformation()); + } + } + + $node->setEmphasizeLines($emphasizeLines); + } } diff --git a/packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php b/packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php index 297190c4d..01237d3c0 100644 --- a/packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php +++ b/packages/guides-restructured-text/tests/unit/Parser/Productions/DirectiveRuleTest.php @@ -103,7 +103,7 @@ public function testCodeBlockValue(string $input, string $expectedValue): void $this->givenInlineMarkupRule(), new Logger('test'), new GeneralDirective(new DirectiveContentRule(new RuleContainer())), - [$this->directiveHandler, new CodeBlockDirective(new CodeNodeOptionMapper())], + [$this->directiveHandler, new CodeBlockDirective(new Logger('test'), new CodeNodeOptionMapper())], ); $context = $this->createContext($input); $node = $this->rule->apply($context); diff --git a/packages/guides/resources/template/html/body/code.html.twig b/packages/guides/resources/template/html/body/code.html.twig index e78e65aa3..47f603fa3 100644 --- a/packages/guides/resources/template/html/body/code.html.twig +++ b/packages/guides/resources/template/html/body/code.html.twig @@ -7,5 +7,7 @@ {{ node.caption }} {%- endif -%} - {{ node.value }} + {{ node.value }} {%- endif -%} diff --git a/packages/guides/src/Nodes/CodeNode.php b/packages/guides/src/Nodes/CodeNode.php index 7bedbfa0f..dd86ebfc5 100644 --- a/packages/guides/src/Nodes/CodeNode.php +++ b/packages/guides/src/Nodes/CodeNode.php @@ -22,6 +22,8 @@ class CodeNode extends TextNode private string|null $caption = null; + private string|null $emphasizeLines = null; + /** @param string[] $lines */ public function __construct(array $lines, protected string|null $language = null) { @@ -57,4 +59,14 @@ public function setCaption(string|null $caption): void { $this->caption = $caption; } + + public function getEmphasizeLines(): string|null + { + return $this->emphasizeLines; + } + + public function setEmphasizeLines(string|null $emphasizeLines): void + { + $this->emphasizeLines = $emphasizeLines; + } } diff --git a/tests/Integration/tests/code/code-block-emphasize/expected/index.html b/tests/Integration/tests/code/code-block-emphasize/expected/index.html new file mode 100644 index 000000000..ef6bf853a --- /dev/null +++ b/tests/Integration/tests/code/code-block-emphasize/expected/index.html @@ -0,0 +1,19 @@ + + + + Title + + + +
+

Title

+ +
def some_function():
+    interesting = False
+    print('This line is highlighted.')
+    print('This one is not...')
+    print('...but this one is.')
+
+ + + diff --git a/tests/Integration/tests/code/code-block-emphasize/input/index.rst b/tests/Integration/tests/code/code-block-emphasize/input/index.rst new file mode 100644 index 000000000..8037dacb4 --- /dev/null +++ b/tests/Integration/tests/code/code-block-emphasize/input/index.rst @@ -0,0 +1,11 @@ +Title +===== + +.. code-block:: python + :emphasize-lines: 3,5 + + def some_function(): + interesting = False + print('This line is highlighted.') + print('This one is not...') + print('...but this one is.')