Skip to content

Commit 5b5ef68

Browse files
authored
Merge pull request #194 from afu-dev/fix-xml-and-html-bugs
fix: independant HTML implementation
2 parents aa56161 + 246acac commit 5b5ef68

11 files changed

Lines changed: 230 additions & 5 deletions

File tree

src/Languages/Html/HtmlLanguage.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
namespace Tempest\Highlight\Languages\Html;
66

77
use Override;
8+
use Tempest\Highlight\Languages\Base\BaseLanguage;
89
use Tempest\Highlight\Languages\Html\Injections\CssAttributeInHtmlInjection;
910
use Tempest\Highlight\Languages\Html\Injections\CssInHtmlInjection;
1011
use Tempest\Highlight\Languages\Html\Injections\JavaScriptInHtmlInjection;
1112
use Tempest\Highlight\Languages\Html\Injections\PhpInHtmlInjection;
1213
use Tempest\Highlight\Languages\Html\Injections\PhpShortEchoInHtmlInjection;
13-
use Tempest\Highlight\Languages\Xml\XmlLanguage;
14+
use Tempest\Highlight\Languages\Html\Patterns\HtmlAttributePattern;
15+
use Tempest\Highlight\Languages\Html\Patterns\HtmlCloseTagPattern;
16+
use Tempest\Highlight\Languages\Html\Patterns\HtmlOpenTagPattern;
17+
use Tempest\Highlight\Languages\Xml\Patterns\XmlCommentPattern;
1418

15-
class HtmlLanguage extends XmlLanguage
19+
class HtmlLanguage extends BaseLanguage
1620
{
1721
#[Override]
1822
public function getName(): string
@@ -38,6 +42,10 @@ public function getPatterns(): array
3842
{
3943
return [
4044
...parent::getPatterns(),
45+
new HtmlOpenTagPattern(),
46+
new HtmlCloseTagPattern(),
47+
new HtmlAttributePattern(),
48+
new XmlCommentPattern(),
4149
];
4250
}
4351
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Html\Patterns;
6+
7+
use Tempest\Highlight\IsPattern;
8+
use Tempest\Highlight\Pattern;
9+
use Tempest\Highlight\PatternTest;
10+
use Tempest\Highlight\Tokens\TokenTypeEnum;
11+
12+
#[PatternTest(input: '<x-hello attr="">', output: 'attr')]
13+
#[PatternTest(input: '<a href="">', output: 'href')]
14+
#[PatternTest(input: '<a data-type="">', output: 'data-type')]
15+
#[PatternTest(input: '<x-post :foreach="$this->posts as $post">', output: ':foreach')]
16+
#[PatternTest(input: '<xsl xmlns:xsl="http">', output: 'xmlns:xsl')]
17+
#[PatternTest(input: "<item attr='value'>", output: 'attr')]
18+
#[PatternTest(input: "<item simple=value>", output: 'simple')]
19+
#[PatternTest(input: "<item with-hyphen=simple-with-hyphen>", output: 'with-hyphen')]
20+
#[PatternTest(input: "<div class=''><span style=''></span></div>", output: ['class', 'style'])]
21+
#[PatternTest(input: '<item
22+
id =
23+
"multiline-attr">', output: 'id')]
24+
#[PatternTest(input: '<item
25+
type
26+
=
27+
"multiline-attr">', output: 'type')]
28+
#[PatternTest(input: '<item
29+
a
30+
="multiline-attr">', output: 'a')]
31+
#[PatternTest(input: '<p></p>', output: null)]
32+
# Not yet implemented
33+
# #[PatternTest(input: "<script defer>", output: 'defer')]
34+
final readonly class HtmlAttributePattern implements Pattern
35+
{
36+
use IsPattern;
37+
38+
public function getPattern(): string
39+
{
40+
return '(?<match>[\w\-:]+)\s*=\s*(?:["\']|[\w-]+)';
41+
}
42+
43+
public function getTokenType(): TokenTypeEnum
44+
{
45+
return TokenTypeEnum::PROPERTY;
46+
}
47+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Html\Patterns;
6+
7+
use Tempest\Highlight\IsPattern;
8+
use Tempest\Highlight\Pattern;
9+
use Tempest\Highlight\PatternTest;
10+
use Tempest\Highlight\Tokens\TokenTypeEnum;
11+
12+
#[PatternTest(input: '</simple>', output: 'simple')]
13+
#[PatternTest(input: '</UPPERCASE>', output: 'UPPERCASE')]
14+
#[PatternTest(input: '</CamelCase>', output: 'CamelCase')]
15+
#[PatternTest(input: '</x-hello>', output: 'x-hello')]
16+
#[PatternTest(input: '</a>', output: 'a')]
17+
# The following are not HTML valid
18+
#[PatternTest(input: '</ns:tag>', output: null)]
19+
#[PatternTest(input: '</point.x>', output: null)]
20+
#[PatternTest(input: '</point_y>', output: null)]
21+
#[PatternTest(input: '</_private>', output: null)]
22+
#[PatternTest(input: '</1tag>', output: null)]
23+
#[PatternTest(input: '</-tag>', output: null)]
24+
final readonly class HtmlCloseTagPattern implements Pattern
25+
{
26+
use IsPattern;
27+
28+
public function getPattern(): string
29+
{
30+
return '<\/(?<match>[a-zA-Z][a-zA-Z0-9\-]*(?![:_\.\w]))';
31+
}
32+
33+
public function getTokenType(): TokenTypeEnum
34+
{
35+
return TokenTypeEnum::KEYWORD;
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Html\Patterns;
6+
7+
use Tempest\Highlight\IsPattern;
8+
use Tempest\Highlight\Pattern;
9+
use Tempest\Highlight\PatternTest;
10+
use Tempest\Highlight\Tokens\TokenTypeEnum;
11+
12+
#[PatternTest(input: '<div>', output: 'div')]
13+
#[PatternTest(input: '<UPPERCASE>', output: 'UPPERCASE')]
14+
#[PatternTest(input: '<CamelCase>', output: 'CamelCase')]
15+
#[PatternTest(input: '<a-component>', output: 'a-component')]
16+
#[PatternTest(input: '<a href="">', output: 'a')]
17+
# The following are not HTML valid
18+
#[PatternTest(input: '<_private>', output: null)]
19+
#[PatternTest(input: '<ns:tag>', output: null)]
20+
#[PatternTest(input: '<point.x>', output: null)]
21+
#[PatternTest(input: '<point_y>', output: null)]
22+
#[PatternTest(input: '<1tag>', output: null)]
23+
#[PatternTest(input: '<-tag>', output: null)]
24+
final readonly class HtmlOpenTagPattern implements Pattern
25+
{
26+
use IsPattern;
27+
28+
public function getPattern(): string
29+
{
30+
return '<(?<match>[a-zA-Z][a-zA-Z0-9\-]*(?![:_\.\w]))';
31+
}
32+
33+
public function getTokenType(): TokenTypeEnum
34+
{
35+
return TokenTypeEnum::KEYWORD;
36+
}
37+
}

src/Languages/Xml/Patterns/XmlAttributePattern.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,24 @@
1313
#[PatternTest(input: '<a href="">', output: 'href')]
1414
#[PatternTest(input: '<a data-type="">', output: 'data-type')]
1515
#[PatternTest(input: '<xsl xmlns:xsl="http">', output: 'xmlns:xsl')]
16+
#[PatternTest(input: "<item attr='value'>", output: 'attr')]
17+
#[PatternTest(input: '<item
18+
id =
19+
"multiline-attr">', output: 'id')]
20+
#[PatternTest(input: '<item
21+
type
22+
=
23+
"multiline-attr">', output: 'type')]
24+
#[PatternTest(input: '<item
25+
a
26+
="multiline-attr">', output: 'a')]
1627
final readonly class XmlAttributePattern implements Pattern
1728
{
1829
use IsPattern;
1930

2031
public function getPattern(): string
2132
{
22-
return '(?<match>[\w\-\:]+)="';
33+
return '(?<match>[\w\-\:]+)\s*=\s*["\']';
2334
}
2435

2536
public function getTokenType(): TokenTypeEnum

src/Languages/Xml/Patterns/XmlCloseTagPattern.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,25 @@
99
use Tempest\Highlight\PatternTest;
1010
use Tempest\Highlight\Tokens\TokenTypeEnum;
1111

12+
#[PatternTest(input: '</simple>', output: 'simple')]
13+
#[PatternTest(input: '</UPPERCASE>', output: 'UPPERCASE')]
14+
#[PatternTest(input: '</CamelCase>', output: 'CamelCase')]
1215
#[PatternTest(input: '</x-hello>', output: 'x-hello')]
1316
#[PatternTest(input: '</a>', output: 'a')]
1417
#[PatternTest(input: '</ns:tag>', output: 'ns:tag')]
18+
#[PatternTest(input: '</point.x>', output: 'point.x')]
19+
#[PatternTest(input: '</point_y>', output: 'point_y')]
20+
#[PatternTest(input: '</_private>', output: '_private')]
21+
# The following are not valid XML tags
22+
#[PatternTest(input: '</1tag>', output: null)]
23+
#[PatternTest(input: '</-tag>', output: null)]
1524
final readonly class XmlCloseTagPattern implements Pattern
1625
{
1726
use IsPattern;
1827

1928
public function getPattern(): string
2029
{
21-
return '<\/(?<match>[\w\-\:]+)';
30+
return '<\/(?<match>[a-zA-Z_][\w\-\:\.]*)';
2231
}
2332

2433
public function getTokenType(): TokenTypeEnum

src/Languages/Xml/Patterns/XmlOpenTagPattern.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,26 @@
99
use Tempest\Highlight\PatternTest;
1010
use Tempest\Highlight\Tokens\TokenTypeEnum;
1111

12+
#[PatternTest(input: '<simple>', output: 'simple')]
13+
#[PatternTest(input: '<UPPERCASE>', output: 'UPPERCASE')]
14+
#[PatternTest(input: '<CamelCase>', output: 'CamelCase')]
1215
#[PatternTest(input: '<x-hello attr="">', output: 'x-hello')]
1316
#[PatternTest(input: '<a href="">', output: 'a')]
1417
#[PatternTest(input: '<br/>', output: 'br')]
1518
#[PatternTest(input: '<ns:tag>', output: 'ns:tag')]
19+
#[PatternTest(input: '<point.x>', output: 'point.x')]
20+
#[PatternTest(input: '<point_y>', output: 'point_y')]
21+
#[PatternTest(input: '<_private>', output: '_private')]
22+
# The following are not valid XML tags
23+
#[PatternTest(input: '<1tag>', output: null)]
24+
#[PatternTest(input: '<-tag>', output: null)]
1625
final readonly class XmlOpenTagPattern implements Pattern
1726
{
1827
use IsPattern;
1928

2029
public function getPattern(): string
2130
{
22-
return '<(?<match>[\w\-\:]+)';
31+
return '<(?<match>[a-zA-Z_][\w\-\:\.]*)';
2332
}
2433

2534
public function getTokenType(): TokenTypeEnum

tests/targets/blade.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
```blade
2+
<!-- resources/views/layouts/app.blade.php -->
3+
4+
<html>
5+
<head>
6+
<title>App Name - @yield('title')</title>
7+
</head>
8+
<body>
9+
@section('sidebar')
10+
This is the master sidebar.
11+
@show
12+
13+
<div class="container">
14+
@yield('content')
15+
</div>
16+
</body>
17+
</html>
18+
```

tests/targets/tempest.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
```blade
2+
<x-base title="Home">
3+
<x-post :foreach="$this->posts as $post">
4+
{{-- a comment which won't be rendered to HTML --}}
5+
6+
{!! $post->title !!}
7+
8+
<span :if="$this->showDate($post)">
9+
{{ $post->date }}
10+
</span>
11+
<span :else>
12+
-
13+
</span>
14+
</x-post>
15+
<div :forelse>
16+
<form action="…">
17+
<x-csrf-token />
18+
<math-α></math-α>
19+
<emotion-😍></emotion-😍>
20+
</form>
21+
</div>
22+
23+
<x-footer />
24+
</x-base>
25+
```

tests/targets/twig.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
```twig
2+
<!DOCTYPE html>
3+
<html>
4+
<head>
5+
<title>My Webpage</title>
6+
</head>
7+
<body>
8+
<ul id="navigation">
9+
{% for item in navigation %}
10+
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
11+
{% endfor %}
12+
</ul>
13+
14+
<h1>My Webpage</h1>
15+
{{ a_variable }}
16+
</body>
17+
</html>
18+
```

0 commit comments

Comments
 (0)