Skip to content

Commit

Permalink
Improve JS language
Browse files Browse the repository at this point in the history
  • Loading branch information
brendt committed Mar 21, 2024
1 parent 04a546d commit b64c646
Show file tree
Hide file tree
Showing 12 changed files with 520 additions and 71 deletions.
122 changes: 68 additions & 54 deletions src/Languages/JavaScript/JavaScriptLanguage.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
namespace Tempest\Highlight\Languages\JavaScript;

use Tempest\Highlight\Languages\Base\BaseLanguage;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsClassNamePattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsDoubleQuoteValuePattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsKeywordPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsMethodPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsMultilineCommentPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsNewObjectPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsObjectPropertyPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsPropertyPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsSinglelineCommentPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsSingleQuoteValuePattern;
use Tempest\Highlight\Languages\Php\Patterns\KeywordPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsStaticClassPattern;
use Tempest\Highlight\Languages\JavaScript\Patterns\JsStaticPropertyPattern;

class JavaScriptLanguage extends BaseLanguage
{
Expand All @@ -26,67 +31,76 @@ public function getPatterns(): array
{
return [
...parent::getPatterns(),
new KeywordPattern('set'),
new KeywordPattern('of'),
new KeywordPattern('get'),
new KeywordPattern('from'),
new KeywordPattern('eval'),
new KeywordPattern('async'),
new KeywordPattern('as'),
new KeywordPattern('break'),
new KeywordPattern('case'),
new KeywordPattern('catch'),
new KeywordPattern('class'),
new KeywordPattern('const'),
new KeywordPattern('continue'),
new KeywordPattern('debugger'),
new KeywordPattern('default'),
new KeywordPattern('delete'),
new KeywordPattern('do'),
new KeywordPattern('else'),
new KeywordPattern('export'),
new KeywordPattern('extends'),
new KeywordPattern('false'),
new KeywordPattern('finally'),
new KeywordPattern('for'),
new KeywordPattern('function'),
new KeywordPattern('if'),
new KeywordPattern('import'),
new KeywordPattern('in'),
new KeywordPattern('instanceof'),
new KeywordPattern('new'),
new KeywordPattern('null'),
new KeywordPattern('return'),
new KeywordPattern('super'),
new KeywordPattern('switch'),
new KeywordPattern('this'),
new KeywordPattern('throw'),
new KeywordPattern('true'),
new KeywordPattern('try'),
new KeywordPattern('typeof'),
new KeywordPattern('var'),
new KeywordPattern('void'),
new KeywordPattern('while'),
new KeywordPattern('with'),
new KeywordPattern('let'),
new KeywordPattern('static'),
new KeywordPattern('yield'),
new KeywordPattern('await'),
new KeywordPattern('enum'),
new KeywordPattern('implements'),
new KeywordPattern('interface'),
new KeywordPattern('package'),
new KeywordPattern('private'),
new KeywordPattern('protected'),
new KeywordPattern('public'),
new JsKeywordPattern('set'),
new JsKeywordPattern('of'),
new JsKeywordPattern('get'),
new JsKeywordPattern('from'),
new JsKeywordPattern('eval'),
new JsKeywordPattern('async'),
new JsKeywordPattern('as'),
new JsKeywordPattern('break'),
new JsKeywordPattern('case'),
new JsKeywordPattern('catch'),
new JsKeywordPattern('class'),
new JsKeywordPattern('const'),
new JsKeywordPattern('continue'),
new JsKeywordPattern('debugger'),
new JsKeywordPattern('default'),
new JsKeywordPattern('delete'),
new JsKeywordPattern('do'),
new JsKeywordPattern('else'),
new JsKeywordPattern('export'),
new JsKeywordPattern('extends'),
new JsKeywordPattern('false'),
new JsKeywordPattern('finally'),
new JsKeywordPattern('for'),
new JsKeywordPattern('function'),
new JsKeywordPattern('if'),
new JsKeywordPattern('import'),
new JsKeywordPattern('in'),
new JsKeywordPattern('instanceof'),
new JsKeywordPattern('new'),
new JsKeywordPattern('null'),
new JsKeywordPattern('return'),
new JsKeywordPattern('super'),
new JsKeywordPattern('switch'),
new JsKeywordPattern('this'),
new JsKeywordPattern('throw'),
new JsKeywordPattern('true'),
new JsKeywordPattern('try'),
new JsKeywordPattern('typeof'),
new JsKeywordPattern('var'),
new JsKeywordPattern('void'),
new JsKeywordPattern('while'),
new JsKeywordPattern('with'),
new JsKeywordPattern('let'),
new JsKeywordPattern('static'),
new JsKeywordPattern('yield'),
new JsKeywordPattern('await'),
new JsKeywordPattern('enum'),
new JsKeywordPattern('implements'),
new JsKeywordPattern('interface'),
new JsKeywordPattern('package'),
new JsKeywordPattern('private'),
new JsKeywordPattern('protected'),
new JsKeywordPattern('public'),
new JsKeywordPattern('constructor'),
new JsKeywordPattern('this'),

// COMMENTS
new JsMultilineCommentPattern(),
new JsSinglelineCommentPattern(),

// TYPES
new JsClassNamePattern(),
new JsNewObjectPattern(),
new JsStaticClassPattern(),

// PROPERTIES
new JsPropertyPattern(),
new JsObjectPropertyPattern(),
new JsMethodPattern(),
new JsStaticPropertyPattern(),

// VALUES
new JsSingleQuoteValuePattern(),
Expand Down
26 changes: 26 additions & 0 deletions src/Languages/JavaScript/Patterns/JsClassNamePattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\JavaScript\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;

#[PatternTest(input: 'class Rectangle', output: 'Rectangle')]
final readonly class JsClassNamePattern implements Pattern
{
use IsPattern;

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

public function getTokenType(): TokenType
{
return TokenType::TYPE;
}
}
43 changes: 43 additions & 0 deletions src/Languages/JavaScript/Patterns/JsKeywordPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\JavaScript\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\Tokens\TokenType;

final class JsKeywordPattern implements Pattern
{
use IsPattern;

private bool $caseInsensitive = false;

public function __construct(private string $keyword)
{
}

public function caseInsensitive(): self
{
$this->caseInsensitive = true;

return $this;
}

public function getPattern(): string
{
$pattern = "/\b(?<!\.)(?<match>{$this->keyword})(\,|\.|\)|\;|\:|\s|\()/";

if ($this->caseInsensitive) {
$pattern .= 'i';
}

return $pattern;
}

public function getTokenType(): TokenType
{
return TokenType::KEYWORD;
}
}
26 changes: 26 additions & 0 deletions src/Languages/JavaScript/Patterns/JsMethodPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\JavaScript\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;

#[PatternTest(input: 'calcArea() {', output: 'calcArea')]
final readonly class JsMethodPattern implements Pattern
{
use IsPattern;

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

public function getTokenType(): TokenType
{
return TokenType::PROPERTY;
}
}
27 changes: 27 additions & 0 deletions src/Languages/JavaScript/Patterns/JsNewObjectPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\JavaScript\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;

#[PatternTest(input: 'new Rectangle(', output: 'Rectangle')]
#[PatternTest(input: 'new qq.AjaxRequester(', output: 'AjaxRequester')]
final readonly class JsNewObjectPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return 'new (\w+\.)*(?<match>[\w]+)(\s)*\(';
}

public function getTokenType(): TokenType
{
return TokenType::TYPE;
}
}
27 changes: 27 additions & 0 deletions src/Languages/JavaScript/Patterns/JsStaticClassPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\JavaScript\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;

#[PatternTest(input: 'Math.round', output: 'Math')]
#[PatternTest(input: 'customHeaders.get', output: null)]
final readonly class JsStaticClassPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '\b(?<match>[A-Z][\w]+)\.';
}

public function getTokenType(): TokenType
{
return TokenType::TYPE;
}
}
26 changes: 26 additions & 0 deletions src/Languages/JavaScript/Patterns/JsStaticPropertyPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\JavaScript\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;

#[PatternTest(input: 'static foo', output: 'foo')]
final readonly class JsStaticPropertyPattern implements Pattern
{
use IsPattern;

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

public function getTokenType(): TokenType
{
return TokenType::PROPERTY;
}
}
2 changes: 1 addition & 1 deletion src/Languages/Php/Patterns/KeywordPattern.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function caseInsensitive(): self

public function getPattern(): string
{
$pattern = "/\b(?<!\\$)(?<!\-\>)(?<match>{$this->keyword})(\)|\;|\:|\s|\()/";
$pattern = "/\b(?<!\\$)(?<!\-\>)(?<match>{$this->keyword})(\,|\)|\;|\:|\s|\()/";

if ($this->caseInsensitive) {
$pattern .= 'i';
Expand Down
2 changes: 1 addition & 1 deletion src/Tokens/TokenType.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function canContain(self $other): bool
{
return match ($this) {
self::OPERATOR, self::VARIABLE, self::VALUE, self::INJECTION, self::COMMENT => false,
self::TYPE => ! in_array($other->value, [self::KEYWORD->value]),
self::TYPE => ! in_array($other->value, [self::KEYWORD->value, self::PROPERTY->value]),
self::GENERIC => ! in_array($other->value, [self::TYPE->value]),
default => true,
};
Expand Down
10 changes: 5 additions & 5 deletions tests/Languages/Html/HtmlLanguageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function test_highlight(string $content, string $expected): void

$this->assertSame(
$expected,
$highlighter->parse($content, 'xml'),
$highlighter->parse($content, 'html'),
);
}

Expand All @@ -42,10 +42,10 @@ public static function data(): array
<span class="hl-comment">&lt;!-- comment --&gt;</span>
&lt;<span class="hl-keyword">style</span>&gt;body {color: red}&lt;/<span class="hl-keyword">style</span>&gt;
&lt;<span class="hl-keyword">tag</span> <span class="hl-property">style</span>=&quot;background-color: #fff;&quot;&gt;&lt;/<span class="hl-keyword">tag</span>&gt;
&lt;?= foo() ?&gt;
&lt;?php foo(); ?&gt;
&lt;<span class="hl-keyword">style</span>&gt;<span class="hl-keyword">body </span>{<span class="hl-property">color</span>: red}&lt;/<span class="hl-keyword">style</span>&gt;
&lt;<span class="hl-keyword">tag</span> <span class="hl-property">style</span>=&quot;<span class="hl-property">background-color</span>: #fff;&quot;&gt;&lt;/<span class="hl-keyword">tag</span>&gt;
&lt;?= <span class="hl-property">foo</span>() ?&gt;
&lt;?php <span class="hl-property">foo</span>(); ?&gt;
&lt;/<span class="hl-keyword">tag</span>&gt;
TXT],
];
Expand Down
Loading

0 comments on commit b64c646

Please sign in to comment.