Skip to content

Commit

Permalink
Add Inline Theme
Browse files Browse the repository at this point in the history
  • Loading branch information
brendt committed Apr 2, 2024
1 parent 56aadb7 commit 4f3c048
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 39 deletions.
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ You can read about why I started this package [here](https://stitcher.io/blog/a-
- [Quickstart](#quickstart)
- [Supported languages](#supported-languages)
- [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)
Expand Down Expand Up @@ -37,18 +35,17 @@ All supported languages can be found in the [Languages folder](./src/Languages).

## Themes

### For the web

For HTML rendering, you can use one of the provided themes that comes with this package:
There are a [bunch of themes](./src/Themes) included in this package. You can load them either by importing the correct CSS file into your project's CSS file, or you can manually copy a stylesheet.

```css
@import "../vendor/tempest/highlight/src/Themes/highlight-light-lite.css";
@import "../vendor/tempest/highlight/src/Themes/highlight-dark-lite.css";
```

You can build your own CSS theme with just a couple of classes, copy over [the base stylesheet](./src/Themes/highlight-light-lite.css), and make adjustments however you like. Note that `pre` tag styling isn't included in this package.

### For the terminal
### Terminal themes

Terminal themes are more limited because of their limited styling options. Right now there's one terminal theme provided: `LightTerminalTheme`. More terminal themes are planned to be added in the future.

```php
use Tempest\Highlight\Highlighter;
Expand Down
5 changes: 5 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.2.0

- Added a collection of themes (#87)
- Added a new `InlineTheme`, which doesn't require loading a CSS style sheet (#88)

## 1.1.0

- Added Gutter support:
Expand Down
19 changes: 10 additions & 9 deletions src/CommonMark/CodeBlockRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use League\CommonMark\Node\Node;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Renderer\NodeRendererInterface;
use League\CommonMark\Util\HtmlElement;
use Tempest\Highlight\Highlighter;
use Tempest\Highlight\WithPre;

final class CodeBlockRenderer implements NodeRendererInterface
{
Expand All @@ -31,13 +31,14 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer)
$this->highlighter->withGutter((int)$startAt);
}

return new HtmlElement(
'pre',
[],
$this->highlighter->parse(
content: $node->getLiteral(),
language: $matches['language'],
),
);
$parsed = $this->highlighter->parse($node->getLiteral(), $matches['language']);

$theme = $this->highlighter->getTheme();

if ($theme instanceof WithPre) {
return $theme->preBefore() . $parsed . $theme->preAfter();
} else {
return '<pre>' . $parsed . '</pre>';
}
}
}
69 changes: 69 additions & 0 deletions src/Themes/InlineTheme.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Themes;

use Tempest\Highlight\Theme;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;
use Tempest\Highlight\WithPre;

final class InlineTheme implements Theme, WithPre
{
private array $map = [];

public function __construct(string $themePath)
{
preg_match_all('/(?<selector>[\w,\.\s\-]+){(?<style>(.|\n)*?)}/', @file_get_contents($themePath) ?? '', $matches);

foreach ($matches[0] as $key => $match) {
$selector = trim($matches['selector'][$key]);
$style = str_replace([PHP_EOL, ' ', "\t"], [' ', '', ''], trim($matches['style'][$key]));

$this->map[$selector] = $style;
}
}

public function before(TokenType $tokenType): string
{
$class = match ($tokenType) {
TokenTypeEnum::KEYWORD => 'hl-keyword',
TokenTypeEnum::PROPERTY => 'hl-property',
TokenTypeEnum::TYPE => 'hl-type',
TokenTypeEnum::GENERIC => 'hl-generic',
TokenTypeEnum::VALUE => 'hl-value',
TokenTypeEnum::COMMENT => 'hl-comment',
TokenTypeEnum::ATTRIBUTE => 'hl-attribute',
TokenTypeEnum::INJECTION => 'hl-injection',
TokenTypeEnum::VARIABLE => 'hl-variable',
TokenTypeEnum::OPERATOR => 'hl-operator',
default => $tokenType->getValue(),
};

$style = $this->map[".{$class}"] ?? null;

if (! $style) {
return '<span>';
}

return "<span style=\"{$style}\">";
}

public function after(TokenType $tokenType): string
{
return '</span>';
}

public function preBefore(): string
{
$preStyle = $this->map['pre'] ?? $this->map['pre, code'] ?? '';

return "<pre style=\"{$preStyle}\">";
}

public function preAfter(): string
{
return '</pre>';
}
}
2 changes: 1 addition & 1 deletion src/Themes/solarized-dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pre, code {
}

.hl-variable {
color: #000;
color: #839496;
}

.hl-comment {
Expand Down
12 changes: 12 additions & 0 deletions src/WithPre.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight;

interface WithPre
{
public function preBefore(): string;

public function preAfter(): string;
}
29 changes: 29 additions & 0 deletions tests/CommonMark/CodeBlockRendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use League\CommonMark\MarkdownConverter;
use PHPUnit\Framework\TestCase;
use Tempest\Highlight\CommonMark\CodeBlockRenderer;
use Tempest\Highlight\Highlighter;
use Tempest\Highlight\Themes\InlineTheme;

class CodeBlockRendererTest extends TestCase
{
Expand Down Expand Up @@ -52,6 +54,33 @@ class Foo {}
$expected = <<<'TXT'
<pre><span class="hl-gutter ">10</span> <span class="hl-keyword">class</span> <span class="hl-type">Foo</span> {}</pre>

TXT;

$this->assertSame($expected, $markdown->convert($input)->getContent());
}

public function test_commonmark_with_pre(): void
{

$environment = new Environment();

$environment
->addExtension(new CommonMarkCoreExtension())
->addExtension(new FrontMatterExtension())
->addRenderer(FencedCode::class, new CodeBlockRenderer(new Highlighter(new InlineTheme(__DIR__ . '/../../src/Themes/min-light.css'))));

$markdown = new MarkdownConverter($environment);

$input = <<<'TXT'
```php
echo;
```
TXT;

$expected = <<<'TXT'
<pre style="color: #212121; background-color: #ffffff;"><span style="color: #D32F2F;">echo</span>;
</pre>

TXT;

$this->assertSame($expected, $markdown->convert($input)->getContent());
Expand Down
10 changes: 10 additions & 0 deletions tests/HighlighterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Tempest\Highlight\Highlighter;
use Tempest\Highlight\Themes\InlineTheme;

class HighlighterTest extends TestCase
{
Expand All @@ -34,6 +35,15 @@ public function test_escaped_with_unknown_language(): void
$this->assertSame('&lt;style&gt;', $output);
}

public function test_inline_theme(): void
{
$highlighter = (new Highlighter(new InlineTheme(__DIR__ . '/../src/Themes/min-light.css')));

$output = $highlighter->parse('echo 1', 'php');

$this->assertSame('<span style="color: #D32F2F;">echo</span> 1', $output);
}

public static function data(): array
{
return [
Expand Down
11 changes: 5 additions & 6 deletions tests/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
use Tempest\Highlight\CommonMark\CodeBlockRenderer;
use Tempest\Highlight\CommonMark\InlineCodeBlockRenderer;
use Tempest\Highlight\Highlighter;
use Tempest\Highlight\Themes\InlineTheme;

$environment = new Environment();

$highlighter = (new Highlighter())->withGutter(20);
$highlighter = (new Highlighter(new InlineTheme(__DIR__ . '/../src/Themes/solarized-dark.css')));

$environment
->addExtension(new CommonMarkCoreExtension())
Expand Down Expand Up @@ -52,10 +53,10 @@
padding: .1em;
}

.hl {
pre {
margin: 3em auto;
box-shadow: 0 0 10px 0 #00000044;
padding: 1em 2em 1em 1ch;
padding: 2em 2em 2em 1ch;
/*background-color: #fafafa;*/
border-radius: 3px;
color: #000;
Expand All @@ -71,9 +72,7 @@
</head>
<body>
<div class="container">
<div class="hl">
<?= $contents ?>
</div>
<?= $contents ?>
</div>
</body>
</html>
26 changes: 10 additions & 16 deletions tests/targets/test.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
```php
foreach ($lines as $i => $line) {
$gutterNumber = $gutterNumbers[$i];
```php{1}
$environment = new Environment();
$gutterClass = 'hl-gutter ' . ($this->classes[$i + 1] ?? '');
{+
$lines[$i] = sprintf(
Escape::tokens('<span class="%s">%s</span>%s'),+}
$gutterClass,
str_pad(
string: {-$gutterNumber-},
length: $gutterWidth,
pad_type: STR_PAD_LEFT,
),
$line,
);
}
$theme = new InlineTheme(__DIR__ . {+'/../src/Themes/solarized-dark.css'+}));
$highlighter = (new Highlighter($theme))->withGutter();
$environment
->addExtension(new CommonMarkCoreExtension())
->addRenderer(FencedCode::class, new CodeBlockRenderer($highlighter))
->addRenderer(Code::class, new InlineCodeBlockRenderer($highlighter));
```

0 comments on commit 4f3c048

Please sign in to comment.