From f8492e782dd5eee151f65efd3ac9c091b9be04c2 Mon Sep 17 00:00:00 2001 From: brendt Date: Mon, 1 Apr 2024 09:23:45 +0200 Subject: [PATCH 1/6] wip --- src/CommonMark/CodeBlockRenderer.php | 9 ++- src/CommonMark/InlineCodeBlockRenderer.php | 9 ++- src/Highlighter.php | 57 ++++++++++++++++- src/Languages/Base/BaseLanguage.php | 4 -- src/Renderer.php | 8 +++ src/Renderers/AdditionRenderer.php | 55 +++++++++++++++++ src/Renderers/DeletionRenderer.php | 55 +++++++++++++++++ src/Renderers/GutterRenderer.php | 71 ++++++++++++++++++++++ src/Themes/highlight-light-lite.css | 18 ++++++ src/WithGutter.php | 10 +++ tests/index.php | 9 ++- tests/targets/test.md | 24 +++++--- 12 files changed, 308 insertions(+), 21 deletions(-) create mode 100644 src/Renderer.php create mode 100644 src/Renderers/AdditionRenderer.php create mode 100644 src/Renderers/DeletionRenderer.php create mode 100644 src/Renderers/GutterRenderer.php create mode 100644 src/WithGutter.php diff --git a/src/CommonMark/CodeBlockRenderer.php b/src/CommonMark/CodeBlockRenderer.php index 62e2460..7540af7 100644 --- a/src/CommonMark/CodeBlockRenderer.php +++ b/src/CommonMark/CodeBlockRenderer.php @@ -12,22 +12,25 @@ use League\CommonMark\Util\HtmlElement; use Tempest\Highlight\Highlighter; -class CodeBlockRenderer implements NodeRendererInterface +final class CodeBlockRenderer implements NodeRendererInterface { + public function __construct( + private Highlighter $highlighter = new Highlighter(), + ) {} + public function render(Node $node, ChildNodeRendererInterface $childRenderer) { if (! $node instanceof FencedCode) { throw new InvalidArgumentException('Block must be instance of ' . FencedCode::class); } - $highlight = new Highlighter(); $code = $node->getLiteral(); $language = $node->getInfoWords()[0] ?? 'txt'; return new HtmlElement( 'pre', [], - $highlight->parse($code, $language) + $this->highlighter->parse($code, $language) ); } } diff --git a/src/CommonMark/InlineCodeBlockRenderer.php b/src/CommonMark/InlineCodeBlockRenderer.php index 7634d4b..65f21f0 100644 --- a/src/CommonMark/InlineCodeBlockRenderer.php +++ b/src/CommonMark/InlineCodeBlockRenderer.php @@ -11,8 +11,12 @@ use League\CommonMark\Renderer\NodeRendererInterface; use Tempest\Highlight\Highlighter; -class InlineCodeBlockRenderer implements NodeRendererInterface +final class InlineCodeBlockRenderer implements NodeRendererInterface { + public function __construct( + private Highlighter $highlighter = new Highlighter(), + ) {} + public function render(Node $node, ChildNodeRendererInterface $childRenderer) { if (! $node instanceof Code) { @@ -21,10 +25,9 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer) preg_match('/^\{(?[\w]+)}(?.*)/', $node->getLiteral(), $match); - $highlighter = new Highlighter(); $language = $match['match'] ?? 'txt'; $code = $match['code'] ?? $node->getLiteral(); - return '' . $highlighter->parse($code, $language) . ''; + return '' . $this->highlighter->parse($code, $language) . ''; } } diff --git a/src/Highlighter.php b/src/Highlighter.php index 7820110..aaac497 100644 --- a/src/Highlighter.php +++ b/src/Highlighter.php @@ -17,6 +17,12 @@ use Tempest\Highlight\Languages\Twig\TwigLanguage; use Tempest\Highlight\Languages\Xml\XmlLanguage; use Tempest\Highlight\Languages\Yaml\YamlLanguage; +use Tempest\Highlight\Renderers\AdditionRenderer; +use Tempest\Highlight\Renderers\BlurRenderer; +use Tempest\Highlight\Renderers\DeletionRenderer; +use Tempest\Highlight\Renderers\EmphasizeRenderer; +use Tempest\Highlight\Renderers\GutterRenderer; +use Tempest\Highlight\Renderers\StrongRenderer; use Tempest\Highlight\Themes\CssTheme; use Tempest\Highlight\Tokens\GroupTokens; use Tempest\Highlight\Tokens\ParseTokens; @@ -25,8 +31,11 @@ final class Highlighter { private array $languages = []; + private array $renderers = []; private ?Language $currentLanguage = null; private bool $shouldEscape = true; + private bool $shouldRender = true; + private ?GutterRenderer $gutterRenderer = null; public function __construct( private readonly Theme $theme = new CssTheme(), @@ -46,11 +55,30 @@ public function __construct( ->setLanguage('yml', new YamlLanguage()) ->setLanguage('twig', new TwigLanguage()); + $this + ->addRenderer(new AdditionRenderer()) + ->addRenderer(new DeletionRenderer()) + ; + if ($this->theme instanceof TerminalTheme) { $this->shouldEscape = false; } } + public function withGutter(int $startAt = 1): self + { + $this->gutterRenderer = new GutterRenderer($startAt); + + return $this; + } + + public function addRenderer(Renderer $renderer): self + { + $this->renderers[] = $renderer; + + return $this; + } + public function setLanguage(string $name, Language $language): self { $this->languages[$name] = $language; @@ -93,13 +121,25 @@ public function withoutEscaping(): self return $clone; } + public function withoutRenderers(): self + { + $clone = clone $this; + + $clone->shouldRender = false; + + return $clone; + } + private function parseContent(string $content, Language $language): string { $tokens = []; // Injections foreach ($language->getInjections() as $injection) { - $parsedInjection = $injection->parse($content, $this->withoutEscaping()); + $parsedInjection = $injection->parse( + $content, + $this->withoutEscaping()->withoutRenderers() + ); // Injections are allowed to return one of two things: // 1. A string of content, which will be used to replace the existing content @@ -131,6 +171,21 @@ private function parseContent(string $content, Language $language): string $output = (new RenderTokens($this->theme))($content, $groupedTokens); + if ($this->shouldRender) { + // Renderers + foreach ($this->renderers as $renderer) { + if ($renderer instanceof WithGutter && $this->gutterRenderer) { + $renderer->setGutter($this->gutterRenderer); + } + + $output = $renderer->render($output); + } + + if ($this->gutterRenderer) { + $output = $this->gutterRenderer->render($output); + } + } + // Determine proper escaping return match(true) { $this->theme instanceof TerminalTheme => Escape::terminal($output), diff --git a/src/Languages/Base/BaseLanguage.php b/src/Languages/Base/BaseLanguage.php index 6c02547..8a9ecc2 100644 --- a/src/Languages/Base/BaseLanguage.php +++ b/src/Languages/Base/BaseLanguage.php @@ -5,10 +5,8 @@ namespace Tempest\Highlight\Languages\Base; use Tempest\Highlight\Language; -use Tempest\Highlight\Languages\Base\Injections\AdditionInjection; use Tempest\Highlight\Languages\Base\Injections\BlurInjection; use Tempest\Highlight\Languages\Base\Injections\CustomClassInjection; -use Tempest\Highlight\Languages\Base\Injections\DeletionInjection; use Tempest\Highlight\Languages\Base\Injections\EmphasizeInjection; use Tempest\Highlight\Languages\Base\Injections\StrongInjection; use Tempest\Highlight\Languages\Base\Patterns\InjectionTokenPattern; @@ -21,8 +19,6 @@ public function getInjections(): array new BlurInjection(), new EmphasizeInjection(), new StrongInjection(), - new AdditionInjection(), - new DeletionInjection(), new CustomClassInjection(), ]; } diff --git a/src/Renderer.php b/src/Renderer.php new file mode 100644 index 0000000..b1927e6 --- /dev/null +++ b/src/Renderer.php @@ -0,0 +1,8 @@ +gutterRenderer = $gutterRenderer; + } + + public function render(string $content): string + { + preg_match_all('/(?\{\+)/', $content, $matches, PREG_OFFSET_CAPTURE); + + $parsedOffset = 0; + + foreach ($matches['match'] as $match) { + $span = Escape::tokens(''); + + $content = substr_replace( + string: $content, + replace: $span, + offset: $match[1] + $parsedOffset, + length: strlen($match[0]), + ); + + if ($this->gutterRenderer) { + $lineNumber = substr_count( + haystack: $content, + needle: PHP_EOL, + length: $match[1] + $parsedOffset, + ) + 1; + + $this->gutterRenderer + ->addIcon($lineNumber, '+') + ->addClass($lineNumber, 'hl-gutter-addition'); + } + + $parsedOffset += strlen($span) - strlen($match[0]); + } + + return str_replace( + '+}', + Escape::tokens(''), + $content, + ); + } +} \ No newline at end of file diff --git a/src/Renderers/DeletionRenderer.php b/src/Renderers/DeletionRenderer.php new file mode 100644 index 0000000..c83f6eb --- /dev/null +++ b/src/Renderers/DeletionRenderer.php @@ -0,0 +1,55 @@ +gutterRenderer = $gutterRenderer; + } + + public function render(string $content): string + { + preg_match_all('/(?\{\-)/', $content, $matches, PREG_OFFSET_CAPTURE); + + $parsedOffset = 0; + + foreach ($matches['match'] as $match) { + $span = Escape::tokens(''); + + $content = substr_replace( + string: $content, + replace: $span, + offset: $match[1] + $parsedOffset, + length: strlen($match[0]), + ); + + if ($this->gutterRenderer) { + $lineNumber = substr_count( + haystack: $content, + needle: PHP_EOL, + length: $match[1] + $parsedOffset, + ) + 1; + + $this->gutterRenderer + ->addIcon($lineNumber, '-') + ->addClass($lineNumber, 'hl-gutter-deletion'); + } + + $parsedOffset += strlen($span) - strlen($match[0]); + } + + return str_replace( + '-}', + Escape::tokens(''), + $content, + ); + } +} \ No newline at end of file diff --git a/src/Renderers/GutterRenderer.php b/src/Renderers/GutterRenderer.php new file mode 100644 index 0000000..8e2daee --- /dev/null +++ b/src/Renderers/GutterRenderer.php @@ -0,0 +1,71 @@ +icons[$line + $this->startAt - 1] = $token; + + return $this; + } + + public function addClass(int $line, string $class): self + { + $this->classes[$line + $this->startAt - 1] = $class; + + return $this; + } + + public function render(string $content): string + { + $lines = explode(PHP_EOL, trim($content)); + + $gutterNumbers = []; + $longestGutterNumber = ''; + + foreach ($lines as $i => $line) { + $gutterNumber = $i + $this->startAt; + + if ($icon = ($this->icons[$i + $this->startAt] ?? null)) { + $gutterNumber .= ' ' . $icon; + } + + $gutterNumbers[$i] = $gutterNumber; + + if (strlen($longestGutterNumber) < strlen($gutterNumber)) { + $longestGutterNumber = $gutterNumber; + } + } + + $gutterWidth = strlen($longestGutterNumber); + + foreach ($lines as $i => $line) { + $gutterNumber = $gutterNumbers[$i]; + + $gutterClass = 'hl-gutter ' . ($this->classes[$i + $this->startAt] ?? ''); + + $lines[$i] = sprintf( + Escape::tokens('%s%s'), + $gutterClass, + str_pad( + string: $gutterNumber, + length: $gutterWidth, + pad_type: STR_PAD_LEFT, + ), + $line, + ); + } + + return implode(PHP_EOL, $lines); + } +} \ No newline at end of file diff --git a/src/Themes/highlight-light-lite.css b/src/Themes/highlight-light-lite.css index 573a2bc..24a51ec 100644 --- a/src/Themes/highlight-light-lite.css +++ b/src/Themes/highlight-light-lite.css @@ -57,4 +57,22 @@ pre, code { display: inline-block; min-width: 100%; background-color: #FF000022; +} + +.hl-gutter { + display: inline-block; + margin-right: 1ch; + font-size: 0.9em; + color: #555; + padding: 0 1ch; +} + +.hl-gutter-addition { + background-color: #34A853; + color: #fff; +} + +.hl-gutter-deletion { + background-color: #EA4334; + color: #fff; } \ No newline at end of file diff --git a/src/WithGutter.php b/src/WithGutter.php new file mode 100644 index 0000000..7ff7e24 --- /dev/null +++ b/src/WithGutter.php @@ -0,0 +1,10 @@ +withGutter(20); + $environment ->addExtension(new CommonMarkCoreExtension()) - ->addRenderer(FencedCode::class, new CodeBlockRenderer()) - ->addRenderer(Code::class, new InlineCodeBlockRenderer()) + ->addRenderer(FencedCode::class, new CodeBlockRenderer($highlighter)) + ->addRenderer(Code::class, new InlineCodeBlockRenderer($highlighter)) ; $markdown = new MarkdownConverter($environment); @@ -52,7 +55,7 @@ .hl { margin: 3em auto; box-shadow: 0 0 10px 0 #00000044; - padding: 1em 2em; + padding: 1em 2em 1em 1ch; /*background-color: #fafafa;*/ border-radius: 3px; color: #000; diff --git a/tests/targets/test.md b/tests/targets/test.md index cac72fc..3400289 100644 --- a/tests/targets/test.md +++ b/tests/targets/test.md @@ -1,8 +1,18 @@ -```js -/** - * Class making something fun and easy. - * @param {string} arg1 An argument that makes this more interesting. - * @param {Array.} arg2 List of numbers to be processed. - * @constructor - */ +```php +foreach ($lines as $i => $line) { + $gutterNumber = $gutterNumbers[$i]; + +{+ $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? '');+} +{++} +{+ $lines[$i] = sprintf(+} +{+ Escape::tokens('%s%s'),+} +{- $gutterClass,-} +{+ str_pad(+} +{+ string: $gutterNumber,+} +{+ length: $gutterWidth,+} +{+ pad_type: STR_PAD_LEFT,+} +{+ ),+} +{+ $line,+} +{+ );+} +} ``` \ No newline at end of file From febbe582b371a06d77db9473d0d78f4dcefff8e3 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Mon, 1 Apr 2024 09:47:14 +0200 Subject: [PATCH 2/6] Before and After injections --- src/After.php | 11 ++ src/Before.php | 11 ++ src/Highlighter.php | 178 ++++++++++-------- src/Languages/Base/BaseLanguage.php | 4 + .../Base/Injections/AdditionInjection.php | 47 ++++- .../Base/Injections/DeletionInjection.php | 48 ++++- .../Base/Injections/GutterInjection.php} | 12 +- src/Renderer.php | 8 - src/Renderers/AdditionRenderer.php | 55 ------ src/Renderers/DeletionRenderer.php | 55 ------ src/WithGutter.php | 10 - tests/TestsInjections.php | 2 +- tests/targets/test.md | 2 +- 13 files changed, 209 insertions(+), 234 deletions(-) create mode 100644 src/After.php create mode 100644 src/Before.php rename src/{Renderers/GutterRenderer.php => Languages/Base/Injections/GutterInjection.php} (84%) delete mode 100644 src/Renderer.php delete mode 100644 src/Renderers/AdditionRenderer.php delete mode 100644 src/Renderers/DeletionRenderer.php delete mode 100644 src/WithGutter.php diff --git a/src/After.php b/src/After.php new file mode 100644 index 0000000..02a5230 --- /dev/null +++ b/src/After.php @@ -0,0 +1,11 @@ +setLanguage('blade', new BladeLanguage()) ->setLanguage('css', new CssLanguage()) @@ -54,29 +50,18 @@ public function __construct( ->setLanguage('yaml', new YamlLanguage()) ->setLanguage('yml', new YamlLanguage()) ->setLanguage('twig', new TwigLanguage()); - - $this - ->addRenderer(new AdditionRenderer()) - ->addRenderer(new DeletionRenderer()) - ; - - if ($this->theme instanceof TerminalTheme) { - $this->shouldEscape = false; - } } public function withGutter(int $startAt = 1): self { - $this->gutterRenderer = new GutterRenderer($startAt); + $this->gutterInjection = new GutterInjection($startAt); return $this; } - public function addRenderer(Renderer $renderer): self + public function getGutterInjection(): ?GutterInjection { - $this->renderers[] = $renderer; - - return $this; + return $this->gutterInjection; } public function setLanguage(string $name, Language $language): self @@ -112,20 +97,11 @@ public function setCurrentLanguage(Language $language): void $this->currentLanguage = $language; } - public function withoutEscaping(): self + public function nested(): self { $clone = clone $this; - $clone->shouldEscape = false; - - return $clone; - } - - public function withoutRenderers(): self - { - $clone = clone $this; - - $clone->shouldRender = false; + $clone->isNested = true; return $clone; } @@ -134,63 +110,103 @@ private function parseContent(string $content, Language $language): string { $tokens = []; - // Injections - foreach ($language->getInjections() as $injection) { - $parsedInjection = $injection->parse( - $content, - $this->withoutEscaping()->withoutRenderers() - ); - - // Injections are allowed to return one of two things: - // 1. A string of content, which will be used to replace the existing content - // 2. a `ParsedInjection` object, which contains both the new content AND a list of tokens to be parsed - // - // One benefit of returning ParsedInjections is that the list of returned tokens will be added - // to all other tokens detected by patterns, and thus follow all token rules. - // They are grouped and checked on whether tokens can be contained by other tokens. - // This offers more flexibility from the injection's point of view, and in same cases lead to more accurate highlighting. - // - // The other benefit is that injections returning ParsedInjection objects don't need to worry about Escape::injection anymore. - // This escape only exists to prevent outside patterns from matching already highlighted content that's injected. - // If an injection doesn't highlight content anymore, then there also isn't any danger for these kinds of collisions. - // And so, Escape::injection becomes obsolete. - // - // TODO: a future version might only allow ParsedTokens and no more standalone strings, but for now we'll keep it as is. - if (is_string($parsedInjection)) { - $content = $parsedInjection; - } else { - $content = $parsedInjection->content; - $tokens = [...$tokens, ...$parsedInjection->tokens]; - } + // Before Injections + foreach ($this->getBeforeInjections($language) as $injection) { + $parsedInjection = $this->parseInjection($content, $injection); + $content = $parsedInjection->content; + $tokens = [...$tokens, ...$parsedInjection->tokens]; } // Patterns $tokens = [...$tokens, ...(new ParseTokens())($content, $language)]; - $groupedTokens = (new GroupTokens())($tokens); + $content = (new RenderTokens($this->theme))($content, $groupedTokens); - $output = (new RenderTokens($this->theme))($content, $groupedTokens); + // After Injections + foreach ($this->getAfterInjections($language) as $injection) { + $parsedInjection = $this->parseInjection($content, $injection); + $content = $parsedInjection->content; + } - if ($this->shouldRender) { - // Renderers - foreach ($this->renderers as $renderer) { - if ($renderer instanceof WithGutter && $this->gutterRenderer) { - $renderer->setGutter($this->gutterRenderer); - } + // Determine proper escaping + return match (true) { + $this->isNested => $content, + $this->theme instanceof TerminalTheme => Escape::terminal($content), + default => Escape::html($content), + }; + } - $output = $renderer->render($output); + /** + * @param \Tempest\Highlight\Language $language + * @return \Tempest\Highlight\Injection[] + */ + private function getBeforeInjections(Language $language): Generator + { + foreach ($language->getInjections() as $injection) { + $after = (new ReflectionClass($injection))->getAttributes(After::class)[0] ?? null; + + if ($after) { + continue; } - if ($this->gutterRenderer) { - $output = $this->gutterRenderer->render($output); + // Only injections without the `After` attribute are allowed + yield $injection; + } + } + + /** + * @param \Tempest\Highlight\Language $language + * @return \Tempest\Highlight\Injection[] + */ + private function getAfterInjections(Language $language): Generator + { + if ($this->isNested) { + // After injections are only parsed at the very end + return; + } + + foreach ($language->getInjections() as $injection) { + $after = (new ReflectionClass($injection))->getAttributes(After::class)[0] ?? null; + + if (! $after) { + continue; } + + yield $injection; } - // Determine proper escaping - return match(true) { - $this->theme instanceof TerminalTheme => Escape::terminal($output), - $this->shouldEscape => Escape::html($output), - default => $output, - }; + // The gutter is always the latest injection + if ($this->gutterInjection) { + yield $this->gutterInjection; + } + } + + private function parseInjection(string $content, Injection $injection): ParsedInjection + { + $parsedInjection = $injection->parse( + $content, + $this->nested(), + ); + + // Injections are allowed to return one of two things: + // 1. A string of content, which will be used to replace the existing content + // 2. a `ParsedInjection` object, which contains both the new content AND a list of tokens to be parsed + // + // One benefit of returning ParsedInjections is that the list of returned tokens will be added + // to all other tokens detected by patterns, and thus follow all token rules. + // They are grouped and checked on whether tokens can be contained by other tokens. + // This offers more flexibility from the injection's point of view, and in same cases lead to more accurate highlighting. + // + // The other benefit is that injections returning ParsedInjection objects don't need to worry about Escape::injection anymore. + // This escape only exists to prevent outside patterns from matching already highlighted content that's injected. + // If an injection doesn't highlight content anymore, then there also isn't any danger for these kinds of collisions. + // And so, Escape::injection becomes obsolete. + // + // TODO: a future version might only allow ParsedTokens and no more standalone strings, but for now we'll keep it as is. + if (is_string($parsedInjection)) { + return new ParsedInjection($parsedInjection); + } + + return $parsedInjection; } } diff --git a/src/Languages/Base/BaseLanguage.php b/src/Languages/Base/BaseLanguage.php index 8a9ecc2..a181c5c 100644 --- a/src/Languages/Base/BaseLanguage.php +++ b/src/Languages/Base/BaseLanguage.php @@ -5,8 +5,10 @@ namespace Tempest\Highlight\Languages\Base; use Tempest\Highlight\Language; +use Tempest\Highlight\Languages\Base\Injections\AdditionInjection; use Tempest\Highlight\Languages\Base\Injections\BlurInjection; use Tempest\Highlight\Languages\Base\Injections\CustomClassInjection; +use Tempest\Highlight\Languages\Base\Injections\DeletionInjection; use Tempest\Highlight\Languages\Base\Injections\EmphasizeInjection; use Tempest\Highlight\Languages\Base\Injections\StrongInjection; use Tempest\Highlight\Languages\Base\Patterns\InjectionTokenPattern; @@ -20,6 +22,8 @@ public function getInjections(): array new EmphasizeInjection(), new StrongInjection(), new CustomClassInjection(), + new AdditionInjection(), + new DeletionInjection(), ]; } diff --git a/src/Languages/Base/Injections/AdditionInjection.php b/src/Languages/Base/Injections/AdditionInjection.php index 3a5788c..ca84047 100644 --- a/src/Languages/Base/Injections/AdditionInjection.php +++ b/src/Languages/Base/Injections/AdditionInjection.php @@ -4,20 +4,49 @@ namespace Tempest\Highlight\Languages\Base\Injections; +use Tempest\Highlight\After; +use Tempest\Highlight\Escape; +use Tempest\Highlight\Highlighter; use Tempest\Highlight\Injection; -use Tempest\Highlight\Languages\Base\IsHighlightInjection; +#[After] final readonly class AdditionInjection implements Injection { - use IsHighlightInjection; - - private function getToken(): string + public function parse(string $content, Highlighter $highlighter): string { - return '+'; - } + preg_match_all('/(?\{\+)/', $content, $matches, PREG_OFFSET_CAPTURE); - private function getClassname(): string - { - return 'hl-addition'; + $parsedOffset = 0; + + foreach ($matches['match'] as $match) { + $span = Escape::tokens(''); + + $content = substr_replace( + string: $content, + replace: $span, + offset: $match[1] + $parsedOffset, + length: strlen($match[0]), + ); + + if ($gutter = $highlighter->getGutterInjection()) { + $lineNumber = substr_count( + haystack: $content, + needle: PHP_EOL, + length: $match[1] + $parsedOffset, + ) + 1; + + $gutter + ->addIcon($lineNumber, '+') + ->addClass($lineNumber, 'hl-gutter-addition'); + } + + $parsedOffset += strlen($span) - strlen($match[0]); + } + + return str_replace( + '+}', + Escape::tokens(''), + $content, + ); } } diff --git a/src/Languages/Base/Injections/DeletionInjection.php b/src/Languages/Base/Injections/DeletionInjection.php index be1df23..9d0e1e5 100644 --- a/src/Languages/Base/Injections/DeletionInjection.php +++ b/src/Languages/Base/Injections/DeletionInjection.php @@ -4,20 +4,50 @@ namespace Tempest\Highlight\Languages\Base\Injections; +use Tempest\Highlight\After; +use Tempest\Highlight\Escape; +use Tempest\Highlight\Highlighter; use Tempest\Highlight\Injection; -use Tempest\Highlight\Languages\Base\IsHighlightInjection; +#[After] final readonly class DeletionInjection implements Injection { - use IsHighlightInjection; - - private function getToken(): string + public function parse(string $content, Highlighter $highlighter): string { - return '-'; - } - private function getClassname(): string - { - return 'hl-deletion'; + preg_match_all('/(?\{\-)/', $content, $matches, PREG_OFFSET_CAPTURE); + + $parsedOffset = 0; + + foreach ($matches['match'] as $match) { + $span = Escape::tokens(''); + + $content = substr_replace( + string: $content, + replace: $span, + offset: $match[1] + $parsedOffset, + length: strlen($match[0]), + ); + + if ($gutter = $highlighter->getGutterInjection()) { + $lineNumber = substr_count( + haystack: $content, + needle: PHP_EOL, + length: $match[1] + $parsedOffset, + ) + 1; + + $gutter + ->addIcon($lineNumber, '-') + ->addClass($lineNumber, 'hl-gutter-deletion'); + } + + $parsedOffset += strlen($span) - strlen($match[0]); + } + + return str_replace( + '-}', + Escape::tokens(''), + $content, + ); } } diff --git a/src/Renderers/GutterRenderer.php b/src/Languages/Base/Injections/GutterInjection.php similarity index 84% rename from src/Renderers/GutterRenderer.php rename to src/Languages/Base/Injections/GutterInjection.php index 8e2daee..14abfe5 100644 --- a/src/Renderers/GutterRenderer.php +++ b/src/Languages/Base/Injections/GutterInjection.php @@ -1,11 +1,13 @@ $line) { diff --git a/src/Renderer.php b/src/Renderer.php deleted file mode 100644 index b1927e6..0000000 --- a/src/Renderer.php +++ /dev/null @@ -1,8 +0,0 @@ -gutterRenderer = $gutterRenderer; - } - - public function render(string $content): string - { - preg_match_all('/(?\{\+)/', $content, $matches, PREG_OFFSET_CAPTURE); - - $parsedOffset = 0; - - foreach ($matches['match'] as $match) { - $span = Escape::tokens(''); - - $content = substr_replace( - string: $content, - replace: $span, - offset: $match[1] + $parsedOffset, - length: strlen($match[0]), - ); - - if ($this->gutterRenderer) { - $lineNumber = substr_count( - haystack: $content, - needle: PHP_EOL, - length: $match[1] + $parsedOffset, - ) + 1; - - $this->gutterRenderer - ->addIcon($lineNumber, '+') - ->addClass($lineNumber, 'hl-gutter-addition'); - } - - $parsedOffset += strlen($span) - strlen($match[0]); - } - - return str_replace( - '+}', - Escape::tokens(''), - $content, - ); - } -} \ No newline at end of file diff --git a/src/Renderers/DeletionRenderer.php b/src/Renderers/DeletionRenderer.php deleted file mode 100644 index c83f6eb..0000000 --- a/src/Renderers/DeletionRenderer.php +++ /dev/null @@ -1,55 +0,0 @@ -gutterRenderer = $gutterRenderer; - } - - public function render(string $content): string - { - preg_match_all('/(?\{\-)/', $content, $matches, PREG_OFFSET_CAPTURE); - - $parsedOffset = 0; - - foreach ($matches['match'] as $match) { - $span = Escape::tokens(''); - - $content = substr_replace( - string: $content, - replace: $span, - offset: $match[1] + $parsedOffset, - length: strlen($match[0]), - ); - - if ($this->gutterRenderer) { - $lineNumber = substr_count( - haystack: $content, - needle: PHP_EOL, - length: $match[1] + $parsedOffset, - ) + 1; - - $this->gutterRenderer - ->addIcon($lineNumber, '-') - ->addClass($lineNumber, 'hl-gutter-deletion'); - } - - $parsedOffset += strlen($span) - strlen($match[0]); - } - - return str_replace( - '-}', - Escape::tokens(''), - $content, - ); - } -} \ No newline at end of file diff --git a/src/WithGutter.php b/src/WithGutter.php deleted file mode 100644 index 7ff7e24..0000000 --- a/src/WithGutter.php +++ /dev/null @@ -1,10 +0,0 @@ -withoutEscaping(); + $highlighter = (new Highlighter())->nested(); if ($currentLanguage) { $highlighter->setCurrentLanguage($currentLanguage); diff --git a/tests/targets/test.md b/tests/targets/test.md index 3400289..3d310d3 100644 --- a/tests/targets/test.md +++ b/tests/targets/test.md @@ -1,6 +1,6 @@ ```php foreach ($lines as $i => $line) { - $gutterNumber = $gutterNumbers[$i]; + {~$gutterNumber = $gutterNumbers[$i];~} {+ $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? '');+} {++} From 53c350e2422aabf30e45bbd8f12362a661377959 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Apr 2024 08:47:12 +0200 Subject: [PATCH 3/6] Add Gutter support --- src/After.php | 8 ++- src/Before.php | 8 ++- src/CommonMark/CodeBlockRenderer.php | 3 +- src/CommonMark/InlineCodeBlockRenderer.php | 3 +- src/Highlighter.php | 7 +-- .../Base/Injections/AdditionInjection.php | 57 ++++++++++-------- .../Base/Injections/DeletionInjection.php | 58 ++++++++++--------- .../Base/Injections/GutterInjection.php | 14 +++-- src/Themes/highlight-dark-lite.css | 20 ++++++- src/Themes/highlight-light-lite.css | 6 +- .../Base/Injections/AdditionInjectionTest.php | 11 ++-- .../Base/Injections/DeletionInjectionTest.php | 11 ++-- tests/targets/test.md | 26 ++++----- 13 files changed, 133 insertions(+), 99 deletions(-) diff --git a/src/After.php b/src/After.php index 02a5230..b8e0694 100644 --- a/src/After.php +++ b/src/After.php @@ -1,5 +1,7 @@ setLanguage('blade', new BladeLanguage()) ->setLanguage('css', new CssLanguage()) @@ -137,7 +136,7 @@ private function parseContent(string $content, Language $language): string } /** - * @param \Tempest\Highlight\Language $language + * @param Language $language * @return \Tempest\Highlight\Injection[] */ private function getBeforeInjections(Language $language): Generator @@ -155,7 +154,7 @@ private function getBeforeInjections(Language $language): Generator } /** - * @param \Tempest\Highlight\Language $language + * @param Language $language * @return \Tempest\Highlight\Injection[] */ private function getAfterInjections(Language $language): Generator diff --git a/src/Languages/Base/Injections/AdditionInjection.php b/src/Languages/Base/Injections/AdditionInjection.php index ca84047..1ad62bf 100644 --- a/src/Languages/Base/Injections/AdditionInjection.php +++ b/src/Languages/Base/Injections/AdditionInjection.php @@ -14,39 +14,46 @@ { public function parse(string $content, Highlighter $highlighter): string { - preg_match_all('/(?\{\+)/', $content, $matches, PREG_OFFSET_CAPTURE); + preg_match_all('/(\{\+)((.|\n)*?)(\+})/', $content, $matches, PREG_OFFSET_CAPTURE); - $parsedOffset = 0; + foreach ($matches[0] as $match) { + $matchedContent = $match[0]; + $offset = $match[1]; - foreach ($matches['match'] as $match) { - $span = Escape::tokens(''); + $open = Escape::tokens(''); + $close = Escape::tokens(''); - $content = substr_replace( - string: $content, - replace: $span, - offset: $match[1] + $parsedOffset, - length: strlen($match[0]), + // Replace tags + EOLs with appropriate span tags + $parsedMatchedContent = str_replace( + ['{+', PHP_EOL, '+}'], + [$open, $close . PHP_EOL . $open, $close], + $matchedContent, ); + // Inject the parsed match into the content + $content = str_replace($matchedContent, $parsedMatchedContent, $content); + + // Configure the gutter, if ($gutter = $highlighter->getGutterInjection()) { - $lineNumber = substr_count( - haystack: $content, - needle: PHP_EOL, - length: $match[1] + $parsedOffset, - ) + 1; - - $gutter - ->addIcon($lineNumber, '+') - ->addClass($lineNumber, 'hl-gutter-addition'); + $startingLineNumber = substr_count( + haystack: $content, + needle: PHP_EOL, + length: $offset, + ) + 1; + + $totalAmountOfLines = substr_count( + haystack: $parsedMatchedContent, + needle: PHP_EOL, + ) + 1; + + for ($lineNumber = $startingLineNumber; $lineNumber < $startingLineNumber + $totalAmountOfLines; $lineNumber++) { + $gutter + ->addIcon($lineNumber, '+') + ->addClass($lineNumber, 'hl-gutter-addition'); + } } - - $parsedOffset += strlen($span) - strlen($match[0]); } - return str_replace( - '+}', - Escape::tokens(''), - $content, - ); + return $content; } } diff --git a/src/Languages/Base/Injections/DeletionInjection.php b/src/Languages/Base/Injections/DeletionInjection.php index 9d0e1e5..753427b 100644 --- a/src/Languages/Base/Injections/DeletionInjection.php +++ b/src/Languages/Base/Injections/DeletionInjection.php @@ -14,40 +14,46 @@ { public function parse(string $content, Highlighter $highlighter): string { + preg_match_all('/(\{-)((.|\n)*?)(-})/', $content, $matches, PREG_OFFSET_CAPTURE); - preg_match_all('/(?\{\-)/', $content, $matches, PREG_OFFSET_CAPTURE); + foreach ($matches[0] as $match) { + $matchedContent = $match[0]; + $offset = $match[1]; - $parsedOffset = 0; + $open = Escape::tokens(''); + $close = Escape::tokens(''); - foreach ($matches['match'] as $match) { - $span = Escape::tokens(''); - - $content = substr_replace( - string: $content, - replace: $span, - offset: $match[1] + $parsedOffset, - length: strlen($match[0]), + // Replace tags + EOLs with appropriate span tags + $parsedMatchedContent = str_replace( + ['{-', PHP_EOL, '-}'], + [$open, $close . PHP_EOL . $open, $close], + $matchedContent, ); + // Inject the parsed match into the content + $content = str_replace($matchedContent, $parsedMatchedContent, $content); + + // Configure the gutter, if ($gutter = $highlighter->getGutterInjection()) { - $lineNumber = substr_count( - haystack: $content, - needle: PHP_EOL, - length: $match[1] + $parsedOffset, - ) + 1; - - $gutter - ->addIcon($lineNumber, '-') - ->addClass($lineNumber, 'hl-gutter-deletion'); + $startingLineNumber = substr_count( + haystack: $content, + needle: PHP_EOL, + length: $offset, + ) + 1; + + $totalAmountOfLines = substr_count( + haystack: $parsedMatchedContent, + needle: PHP_EOL, + ) + 1; + + for ($lineNumber = $startingLineNumber; $lineNumber < $startingLineNumber + $totalAmountOfLines; $lineNumber++) { + $gutter + ->addIcon($lineNumber, '-') + ->addClass($lineNumber, 'hl-gutter-deletion'); + } } - - $parsedOffset += strlen($span) - strlen($match[0]); } - return str_replace( - '-}', - Escape::tokens(''), - $content, - ); + return $content; } } diff --git a/src/Languages/Base/Injections/GutterInjection.php b/src/Languages/Base/Injections/GutterInjection.php index 14abfe5..0dca1ea 100644 --- a/src/Languages/Base/Injections/GutterInjection.php +++ b/src/Languages/Base/Injections/GutterInjection.php @@ -1,5 +1,7 @@ %s%s'), $gutterClass, str_pad( - string: $gutterNumber, + string: (string) $gutterNumber, length: $gutterWidth, pad_type: STR_PAD_LEFT, ), @@ -70,4 +74,4 @@ public function parse(string $content, Highlighter $highlighter): string|ParsedI return implode(PHP_EOL, $lines); } -} \ No newline at end of file +} diff --git a/src/Themes/highlight-dark-lite.css b/src/Themes/highlight-dark-lite.css index a2a32fa..3c9dbd9 100644 --- a/src/Themes/highlight-dark-lite.css +++ b/src/Themes/highlight-dark-lite.css @@ -49,13 +49,29 @@ pre, code { } .hl-addition { - display: inline-block; min-width: 100%; background-color: #00FF0033; } .hl-deletion { - display: inline-block; min-width: 100%; background-color: #FF000022; +} + +.hl-gutter { + display: inline-block; + margin-right: 1ch; + font-size: 0.9em; + color: #555; + padding: 0 1ch; +} + +.hl-gutter-addition { + background-color: #34A853; + color: #fff; +} + +.hl-gutter-deletion { + background-color: #EA4334; + color: #fff; } \ No newline at end of file diff --git a/src/Themes/highlight-light-lite.css b/src/Themes/highlight-light-lite.css index 24a51ec..a9fe29c 100644 --- a/src/Themes/highlight-light-lite.css +++ b/src/Themes/highlight-light-lite.css @@ -48,15 +48,13 @@ pre, code { } .hl-addition { - display: inline-block; min-width: 100%; - background-color: #00FF0033; + background-color: #00FF0022; } .hl-deletion { - display: inline-block; min-width: 100%; - background-color: #FF000022; + background-color: #FF000011; } .hl-gutter { diff --git a/tests/Languages/Base/Injections/AdditionInjectionTest.php b/tests/Languages/Base/Injections/AdditionInjectionTest.php index d3f8dce..5ae5fb8 100644 --- a/tests/Languages/Base/Injections/AdditionInjectionTest.php +++ b/tests/Languages/Base/Injections/AdditionInjectionTest.php @@ -5,6 +5,7 @@ namespace Tempest\Highlight\Tests\Languages\Base\Injections; use PHPUnit\Framework\TestCase; +use Tempest\Highlight\Escape; use Tempest\Highlight\Highlighter; use Tempest\Highlight\Languages\Base\Injections\AdditionInjection; @@ -17,15 +18,11 @@ public function test_addition_injection() TXT; $expected = <<class Foo TXT; - $parsed = (new AdditionInjection())->parse($content, new Highlighter()); + $content = (new AdditionInjection())->parse($content, new Highlighter()); - $this->assertSame($expected, $parsed->content); - $this->assertCount(1, $parsed->tokens); - $this->assertSame(0, $parsed->tokens[0]->start); - $this->assertSame(9, $parsed->tokens[0]->end); - $this->assertSame('hl-addition', $parsed->tokens[0]->type->getValue()); + $this->assertSame($expected, Escape::html($content)); } } diff --git a/tests/Languages/Base/Injections/DeletionInjectionTest.php b/tests/Languages/Base/Injections/DeletionInjectionTest.php index 2ded3ea..b9c0204 100644 --- a/tests/Languages/Base/Injections/DeletionInjectionTest.php +++ b/tests/Languages/Base/Injections/DeletionInjectionTest.php @@ -5,6 +5,7 @@ namespace Tempest\Highlight\Tests\Languages\Base\Injections; use PHPUnit\Framework\TestCase; +use Tempest\Highlight\Escape; use Tempest\Highlight\Highlighter; use Tempest\Highlight\Languages\Base\Injections\DeletionInjection; @@ -17,15 +18,11 @@ public function test_deletion_injection() TXT; $expected = <<class Foo TXT; - $parsed = (new DeletionInjection())->parse($content, new Highlighter()); + $content = (new DeletionInjection())->parse($content, new Highlighter()); - $this->assertSame($expected, $parsed->content); - $this->assertCount(1, $parsed->tokens); - $this->assertSame(0, $parsed->tokens[0]->start); - $this->assertSame(9, $parsed->tokens[0]->end); - $this->assertSame('hl-deletion', $parsed->tokens[0]->type->getValue()); + $this->assertSame($expected, Escape::html($content)); } } diff --git a/tests/targets/test.md b/tests/targets/test.md index 3d310d3..5a28ff0 100644 --- a/tests/targets/test.md +++ b/tests/targets/test.md @@ -1,18 +1,18 @@ ```php foreach ($lines as $i => $line) { - {~$gutterNumber = $gutterNumbers[$i];~} + $gutterNumber = $gutterNumbers[$i]; -{+ $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? '');+} -{++} -{+ $lines[$i] = sprintf(+} -{+ Escape::tokens('%s%s'),+} -{- $gutterClass,-} -{+ str_pad(+} -{+ string: $gutterNumber,+} -{+ length: $gutterWidth,+} -{+ pad_type: STR_PAD_LEFT,+} -{+ ),+} -{+ $line,+} -{+ );+} + $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? ''); +{+ + $lines[$i] = sprintf( + Escape::tokens('%s%s'),+} + $gutterClass, + str_pad( + string: {-$gutterNumber-}, + length: $gutterWidth, + pad_type: STR_PAD_LEFT, + ), + $line, + ); } ``` \ No newline at end of file From 2660f6ec85d58089ecdba4bfd421363bf20debbc Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Apr 2024 08:50:29 +0200 Subject: [PATCH 4/6] Add UPGRADING --- UPGRADING.md | 31 +++++++++++ .../Base/Injections/GutterInjectionTest.php | 55 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 UPGRADING.md create mode 100644 tests/Languages/Base/Injections/GutterInjectionTest.php diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 0000000..dee7110 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,31 @@ +## 1.1.0 + +- Added Gutter support: + +```php +$highlighter = (new \Tempest\Highlight\Highlighter())->withGutter(); +``` + +**Note**: three new classes have been added for gutter support. If you copied over an existing theme, you'll need to add these: + +```css +.hl-gutter { + display: inline-block; + margin-right: 1ch; + font-size: 0.9em; + color: #555; + padding: 0 1ch; +} + +.hl-gutter-addition { + background-color: #34A853; + color: #fff; +} + +.hl-gutter-deletion { + background-color: #EA4334; + color: #fff; +} +``` + +**Note**: This package doesn't account for `pre` tag styling. You might need to make adjustments to how you style `pre` tags if you enable gutter support. \ No newline at end of file diff --git a/tests/Languages/Base/Injections/GutterInjectionTest.php b/tests/Languages/Base/Injections/GutterInjectionTest.php new file mode 100644 index 0000000..dfde6c6 --- /dev/null +++ b/tests/Languages/Base/Injections/GutterInjectionTest.php @@ -0,0 +1,55 @@ + $line) { + $gutterNumber = $gutterNumbers[$i]; + + $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? ''); +{+ + $lines[$i] = sprintf( + Escape::tokens('%s%s'),+} + $gutterClass, + str_pad( + string: {-$gutterNumber-}, + length: $gutterWidth, + pad_type: STR_PAD_LEFT, + ), + $line, + ); +} +TXT; + + $expected = <<<'TXT' + 10foreach ($lines as $i => $line) { + 11 $gutterNumber = $gutterNumbers[$i]; + 12 + 13 $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? ''); +14 + +15 + $lines[$i] = sprintf( +16 + Escape::tokens('<span class="%s">%s</span>%s'), + 17 $gutterClass, + 18 str_pad( +19 - string: $gutterNumber, + 20 length: $gutterWidth, + 21 pad_type: STR_PAD_LEFT, + 22 ), + 23 $line, + 24 ); + 25} +TXT; + $highlighter = (new Highlighter())->withGutter(10); + + $this->assertSame($expected, $highlighter->parse($input, 'php')); + } +} From bcbb678b6f2e3be62b0cb22ca1d2c377788344b8 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Apr 2024 09:11:44 +0200 Subject: [PATCH 5/6] QA --- .github/highlight-4.png | Bin 0 -> 131124 bytes README.md | 15 +++++ UPGRADING.md | 1 - src/Escape.php | 6 +- .../Base/Injections/GutterInjection.php | 2 +- src/Themes/highlight-light-lite.css | 1 - test-terminal.php | 2 +- .../Base/Injections/GutterInjectionTest.php | 63 +++++++++++++----- 8 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 .github/highlight-4.png diff --git a/.github/highlight-4.png b/.github/highlight-4.png new file mode 100644 index 0000000000000000000000000000000000000000..be9f1cecfe6a04c084163b5f518ef56c4051387f GIT binary patch literal 131124 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 Mp{YTxp2Nkz0X?+^o&W#< literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 4084b4c..52c00f7 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ You can read about why I started this package [here](https://stitcher.io/blog/a- - [Themes](#themes) - [For the web](#for-the-web) - [For the terminal](#for-the-terminal) +- [Gutter](#gutter) - [Special highlighting tags](#special-highlighting-tags) - [Emphasize strong and blur](#emphasize-strong-and-blur) - [Additions and deletions](#additions-and-deletions) @@ -60,6 +61,20 @@ echo $highlighter->parse($code, 'php'); ![](./.github/terminal.png) +## Gutter + +This package can render an optional gutter if needed. + +```php +$highlighter = (new Highlighter())->withGutter(startAt: 10); +``` + +The gutter will show additions and deletions, and can start at any given line number: + +![](./.github/highlight-4.png) + +Gutter styling is managed within your CSS theme. + ## Special highlighting tags This package offers a collection of special tags that you can use within your code snippets. These tags won't be shown in the final output, but rather adjust the highlighter's default styling. All these tags work multi-line, and will still properly render its wrapped content. diff --git a/UPGRADING.md b/UPGRADING.md index dee7110..2d34ccd 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -11,7 +11,6 @@ $highlighter = (new \Tempest\Highlight\Highlighter())->withGutter(); ```css .hl-gutter { display: inline-block; - margin-right: 1ch; font-size: 0.9em; color: #555; padding: 0 1ch; diff --git a/src/Escape.php b/src/Escape.php index d6b8026..3d13433 100644 --- a/src/Escape.php +++ b/src/Escape.php @@ -28,7 +28,11 @@ public static function injection(string $input): string public static function terminal(string $input): string { - return str_replace(self::INJECTION_TOKEN, '', $input); + return preg_replace( + ['/❷(.*?)❸/', '/❿/'], + '', + $input, + ); } public static function html(string $input): string diff --git a/src/Languages/Base/Injections/GutterInjection.php b/src/Languages/Base/Injections/GutterInjection.php index 0dca1ea..e2b83d9 100644 --- a/src/Languages/Base/Injections/GutterInjection.php +++ b/src/Languages/Base/Injections/GutterInjection.php @@ -61,7 +61,7 @@ public function parse(string $content, Highlighter $highlighter): string|ParsedI $gutterClass = 'hl-gutter ' . ($this->classes[$i + $this->startAt] ?? ''); $lines[$i] = sprintf( - Escape::tokens('%s%s'), + Escape::tokens('%s %s'), $gutterClass, str_pad( string: (string) $gutterNumber, diff --git a/src/Themes/highlight-light-lite.css b/src/Themes/highlight-light-lite.css index a9fe29c..038b896 100644 --- a/src/Themes/highlight-light-lite.css +++ b/src/Themes/highlight-light-lite.css @@ -59,7 +59,6 @@ pre, code { .hl-gutter { display: inline-block; - margin-right: 1ch; font-size: 0.9em; color: #555; padding: 0 1ch; diff --git a/test-terminal.php b/test-terminal.php index 50e1590..18e1de1 100644 --- a/test-terminal.php +++ b/test-terminal.php @@ -5,7 +5,7 @@ require_once __DIR__ . '/vendor/autoload.php'; -$highlighter = new Highlighter(new LightTerminalTheme()); +$highlighter = (new Highlighter(new LightTerminalTheme()))->withGutter(); $target = $argc > 1 ? $argv[1] diff --git a/tests/Languages/Base/Injections/GutterInjectionTest.php b/tests/Languages/Base/Injections/GutterInjectionTest.php index dfde6c6..19010e0 100644 --- a/tests/Languages/Base/Injections/GutterInjectionTest.php +++ b/tests/Languages/Base/Injections/GutterInjectionTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\TestCase; use Tempest\Highlight\Highlighter; +use Tempest\Highlight\Themes\LightTerminalTheme; class GutterInjectionTest extends TestCase { @@ -31,25 +32,55 @@ public function test_gutter_injection(): void TXT; $expected = <<<'TXT' - 10foreach ($lines as $i => $line) { - 11 $gutterNumber = $gutterNumbers[$i]; - 12 - 13 $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? ''); -14 + -15 + $lines[$i] = sprintf( -16 + Escape::tokens('<span class="%s">%s</span>%s'), - 17 $gutterClass, - 18 str_pad( -19 - string: $gutterNumber, - 20 length: $gutterWidth, - 21 pad_type: STR_PAD_LEFT, - 22 ), - 23 $line, - 24 ); - 25} + 10 foreach ($lines as $i => $line) { + 11 $gutterNumber = $gutterNumbers[$i]; + 12 + 13 $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? ''); +14 + +15 + $lines[$i] = sprintf( +16 + Escape::tokens('<span class="%s">%s</span>%s'), + 17 $gutterClass, + 18 str_pad( +19 - string: $gutterNumber, + 20 length: $gutterWidth, + 21 pad_type: STR_PAD_LEFT, + 22 ), + 23 $line, + 24 ); + 25 } TXT; $highlighter = (new Highlighter())->withGutter(10); $this->assertSame($expected, $highlighter->parse($input, 'php')); } + + public function test_gutter_injection_terminal(): void + { + $input = <<<'TXT' +foreach ($lines as $i => $line) { + $gutterNumber = $gutterNumbers[$i]; + + $gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? ''); +{+ + $lines[$i] = sprintf( + Escape::tokens('%s%s'),+} + $gutterClass, + str_pad( + string: {-$gutterNumber-}, + length: $gutterWidth, + pad_type: STR_PAD_LEFT, + ), + $line, + ); +} +TXT; + + $expected = <<<'TXT' +ICAxMCAbWzM0bWZvcmVhY2gbWzBtICgbWzBtJGxpbmVzG1swbSAbWzM0bWFzG1swbSAbWzBtJGkbWzBtID0+IBtbMG0kbGluZRtbMG0pIHsKICAxMSAgICAgG1swbSRndXR0ZXJOdW1iZXIbWzBtID0gG1swbSRndXR0ZXJOdW1iZXJzG1swbVsbWzBtJGkbWzBtXTsKICAxMiAKICAxMyAgICAgG1swbSRndXR0ZXJDbGFzcxtbMG0gPSAnG1szMG1obC1ndXR0ZXIgG1swbScgLiAoG1swbSR0aGlzG1swbS0+G1szMm1jbGFzc2VzG1swbVsbWzBtJGkbWzBtICsgMV0gPz8gJxtbMzBtG1swbScpOwoxNCArIAoxNSArICAgICAbWzBtJGxpbmVzG1swbVsbWzBtJGkbWzBtXSA9IBtbMzJtc3ByaW50ZhtbMG0oCjE2ICsgICAgICAgICAbWzMxbUVzY2FwZRtbMG06OhtbMzJtdG9rZW5zG1swbSgnG1szMG08c3BhbiBjbGFzcz0iJXMiPiVzPC9zcGFuPiVzG1swbScpLAogIDE3ICAgICAgICAgG1swbSRndXR0ZXJDbGFzcxtbMG0sCiAgMTggICAgICAgICAbWzMybXN0cl9wYWQbWzBtKAoxOSAtICAgICAgICAgICAgIBtbMzJtc3RyaW5nG1swbTogG1swbSRndXR0ZXJOdW1iZXIbWzBtLAogIDIwICAgICAgICAgICAgIBtbMzJtbGVuZ3RoG1swbTogG1swbSRndXR0ZXJXaWR0aBtbMG0sCiAgMjEgICAgICAgICAgICAgG1szMm1wYWRfdHlwZRtbMG06IBtbMzJtU1RSX1BBRF9MRUZUG1swbSwKICAyMiAgICAgICAgICksCiAgMjMgICAgICAgICAbWzBtJGxpbmUbWzBtLAogIDI0ICAgICApOwogIDI1IH0= +TXT; + + $highlighter = (new Highlighter(new LightTerminalTheme()))->withGutter(10); + + $this->assertSame(base64_decode($expected), $highlighter->parse($input, 'php')); + } } From b83bbad8fb90beda05f1e0f2acd031c9be31d8df Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Apr 2024 09:38:05 +0200 Subject: [PATCH 6/6] Commonmark gutter support --- README.md | 8 +++++- src/CommonMark/CodeBlockRenderer.php | 12 ++++++--- ...ererTest.php => CodeBlockRendererTest.php} | 27 ++++++++++++++++++- 3 files changed, 42 insertions(+), 5 deletions(-) rename tests/CommonMark/{HighlightCodeBlockRendererTest.php => CodeBlockRendererTest.php} (57%) diff --git a/README.md b/README.md index 52c00f7..064f6ba 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,13 @@ The gutter will show additions and deletions, and can start at any given line nu ![](./.github/highlight-4.png) -Gutter styling is managed within your CSS theme. +Finally, you can enable gutter rendering on the fly if you're using [commonmark code blocks](#commonmark-integration) by appending `{startAt}` to the language definition: + +```md +```php{1} +echo 'hi'! +``` +``` ## Special highlighting tags diff --git a/src/CommonMark/CodeBlockRenderer.php b/src/CommonMark/CodeBlockRenderer.php index 8a0830b..f534fd7 100644 --- a/src/CommonMark/CodeBlockRenderer.php +++ b/src/CommonMark/CodeBlockRenderer.php @@ -25,13 +25,19 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer) throw new InvalidArgumentException('Block must be instance of ' . FencedCode::class); } - $code = $node->getLiteral(); - $language = $node->getInfoWords()[0] ?? 'txt'; + preg_match('/^(?[\w]+)(\{(?[\d]+)\})?/', $node->getInfoWords()[0] ?? 'txt', $matches); + + if ($startAt = ($matches['startAt']) ?? null) { + $this->highlighter->withGutter((int)$startAt); + } return new HtmlElement( 'pre', [], - $this->highlighter->parse($code, $language) + $this->highlighter->parse( + content: $node->getLiteral(), + language: $matches['language'], + ), ); } } diff --git a/tests/CommonMark/HighlightCodeBlockRendererTest.php b/tests/CommonMark/CodeBlockRendererTest.php similarity index 57% rename from tests/CommonMark/HighlightCodeBlockRendererTest.php rename to tests/CommonMark/CodeBlockRendererTest.php index 866537b..a27a019 100644 --- a/tests/CommonMark/HighlightCodeBlockRendererTest.php +++ b/tests/CommonMark/CodeBlockRendererTest.php @@ -12,7 +12,7 @@ use PHPUnit\Framework\TestCase; use Tempest\Highlight\CommonMark\CodeBlockRenderer; -class HighlightCodeBlockRendererTest extends TestCase +class CodeBlockRendererTest extends TestCase { public function test_commonmark(): void { @@ -31,4 +31,29 @@ class Foo {} $this->assertStringContainsString('hl-keyword', $parsed->getContent()); } + + public function test_commonmark_with_gutter(): void + { + $environment = new Environment(); + + $environment + ->addExtension(new CommonMarkCoreExtension()) + ->addExtension(new FrontMatterExtension()) + ->addRenderer(FencedCode::class, new CodeBlockRenderer()); + + $markdown = new MarkdownConverter($environment); + + $input = <<<'TXT' +```php{10} +class Foo {} +``` +TXT; + + $expected = <<<'TXT' +

10 class Foo {}
+ +TXT; + + $this->assertSame($expected, $markdown->convert($input)->getContent()); + } }