Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
brendt committed Mar 15, 2024
1 parent 1500428 commit 57adb88
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 7 deletions.
42 changes: 37 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ composer require league/commonmark;

This package makes it easy for developers to add new languages or extend existing languages. Right now, these languages are supported: `php`, `html`, `css`. More will be added.

In order to build your own highlighter functionality, you need to understand _two_ concepts of how code is highlighted.
In order to build your own highlighter functionality, you need to understand _three_ concepts of how code is highlighted: _patterns_, _injections_, and _languages_.

### 1. Patterns

Expand Down Expand Up @@ -178,14 +178,46 @@ The second step in providing an _injection_ is to parse the matched content into
- Just like patterns, injection regexes should contain a group named `match`, which is written like so `(?<match>…)`
- Finally, an injection will use the highlighter to parse its matched content into another language

### Extending existing languages
### 3. Languages

Instead of starting from scratch, the best approach to adding new languages is by extending existing ones. For example, let's add support for `blade`:
The last concept to understand, although it doesn't mean much. _Languages_ are classes that bring these two concepts together. They are nothing more than a collection of patterns and injections. Take a look at the `HtmlLanguage`, for example:

```php
class BladeLanguage extends HtmlLanguage
class HtmlLanguage implements Language
{
public function getInjections(): array
{
return [
new PhpInjection(),
new PhpShortEchoInjection(),
new CssInjection(),
];
}

public function getPatterns(): array
{
return [
new OpenTagPattern(),
new CloseTagPattern(),
new TagAttributePattern(),
new HtmlCommentPattern(),
];
}
}
```

// TODO
This `HtmlLanguage` class specifies the following things:

- PHP can be injected within HTML, both with the short echo tag `<?=` and longer `<?php` tags
- CSS can be injected as well, JavaScript support is still work in progress
- There are a bunch of patterns to highlight HTML tags properly

So, let's bring everything together to explain how you can add your own languages.

### Adding custom languages

Let's say you're adding `blade` support. You could create a plain language file and start from there, but it'd probably be easier to extend an existing language.

```php

```
13 changes: 13 additions & 0 deletions src/Languages/BladeLanguage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Tempest\Highlight\Languages;

class BladeLanguage extends HtmlLanguage
{
public function getPatterns(): array
{
return parent::getPatterns() + [

];
}
}
2 changes: 1 addition & 1 deletion src/Patterns/Php/ClassNamePattern.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

public function getPattern(): string
{
return 'class (?<match>[\w]+)';
return '(class|interface) (?<match>[\w]+)';
}

public function getTokenType(): TokenType
Expand Down
2 changes: 1 addition & 1 deletion src/Themes/highlight-light-lite.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
}

.hl-attribute {
font-family: "Radon", serif;
font-family: "Radon", inherit, monospace;
}

.hl-type {
Expand Down
5 changes: 5 additions & 0 deletions test-server.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

require_once __DIR__ . '/vendor/autoload.php';

passthru("php -S localhost:8080 -t tests/");
6 changes: 6 additions & 0 deletions tests/Patterns/Php/ClassNamePatternTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,11 @@ public function test_pattern()
content: 'class Foo implements Bar',
expected: 'Foo',
);

$this->assertMatches(
pattern: new ClassNamePattern(),
content: 'interface Foo implements Bar',
expected: 'Foo',
);
}
}
54 changes: 54 additions & 0 deletions tests/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

require_once __DIR__ . '/../vendor/autoload.php';

use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
use League\CommonMark\MarkdownConverter;
use Tempest\Highlight\CommonMark\HighlightCodeBlockRenderer;

$environment = new Environment();

$environment
->addExtension(new CommonMarkCoreExtension())
->addRenderer(FencedCode::class, new HighlightCodeBlockRenderer());

$markdown = new MarkdownConverter($environment);

$contents = $markdown->convert(file_get_contents(__DIR__ . '/test.md'))->getContent();

?>

<html>
<head>
<title>Test</title>
<style>
<?= file_get_contents(__DIR__ . '/../src/Themes/highlight-light-lite.css') ?>

body {
font-size: 15px;
}

pre {
overflow-x: scroll;
line-height: 1.8em;
font-family: "JetBrains Mono", monospace;
}

.hl {
width: 800px;
margin: 3em auto;
box-shadow: 0 0 10px 0 #00000044;
padding: 1em 2em;
background-color: #fafafa;
border-radius: 3px;
}
</style>
</head>
<body>
<div class="hl">
<?= $contents ?>
</div>
</body>
</html>
10 changes: 10 additions & 0 deletions tests/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
```php
declare(strict_types=1);

namespace Tempest\Highlight;

interface Injection
{
public function parse(string $content, Highlighter $highlighter): string;
}
```

0 comments on commit 57adb88

Please sign in to comment.