From d97fba6afa152913b82ac510ff46ae370b8cfb69 Mon Sep 17 00:00:00 2001 From: eas4ai Date: Mon, 19 Oct 2026 20:15:55 -0400 Subject: [PATCH 1/2] Add TOML syntax highlighting --- src/Highlighter.php | 2 + .../Toml/Patterns/TomlBooleanPattern.php | 25 ++++ .../Toml/Patterns/TomlCommentPattern.php | 25 ++++ .../Toml/Patterns/TomlDateTimePattern.php | 25 ++++ .../Toml/Patterns/TomlKeyPattern.php | 27 ++++ .../Toml/Patterns/TomlNumberPattern.php | 27 ++++ .../Toml/Patterns/TomlOperatorPattern.php | 25 ++++ .../Toml/Patterns/TomlStringPattern.php | 27 ++++ .../Toml/Patterns/TomlTablePattern.php | 27 ++++ src/Languages/Toml/TomlLanguage.php | 40 ++++++ tests/Bench/Fixtures/toml.txt | 23 ++++ tests/Bench/HighlighterBench.php | 1 + tests/Languages/Toml/TomlLanguageTest.php | 116 ++++++++++++++++++ 13 files changed, 390 insertions(+) create mode 100644 src/Languages/Toml/Patterns/TomlBooleanPattern.php create mode 100644 src/Languages/Toml/Patterns/TomlCommentPattern.php create mode 100644 src/Languages/Toml/Patterns/TomlDateTimePattern.php create mode 100644 src/Languages/Toml/Patterns/TomlKeyPattern.php create mode 100644 src/Languages/Toml/Patterns/TomlNumberPattern.php create mode 100644 src/Languages/Toml/Patterns/TomlOperatorPattern.php create mode 100644 src/Languages/Toml/Patterns/TomlStringPattern.php create mode 100644 src/Languages/Toml/Patterns/TomlTablePattern.php create mode 100644 src/Languages/Toml/TomlLanguage.php create mode 100644 tests/Bench/Fixtures/toml.txt create mode 100644 tests/Languages/Toml/TomlLanguageTest.php diff --git a/src/Highlighter.php b/src/Highlighter.php index 843cf5b6..3dbc5141 100644 --- a/src/Highlighter.php +++ b/src/Highlighter.php @@ -36,6 +36,7 @@ use Tempest\Highlight\Languages\Terminal\TerminalLanguage; use Tempest\Highlight\Languages\Terraform\TerraformLanguage; use Tempest\Highlight\Languages\Text\TextLanguage; +use Tempest\Highlight\Languages\Toml\TomlLanguage; use Tempest\Highlight\Languages\Tsx\TsxLanguage; use Tempest\Highlight\Languages\Twig\TwigLanguage; use Tempest\Highlight\Languages\TypeScript\TypeScriptLanguage; @@ -94,6 +95,7 @@ public function __construct( ->addLanguage(new TerminalLanguage()) ->addLanguage(new TextLanguage()) ->addLanguage(new TerraformLanguage()) + ->addLanguage(new TomlLanguage()) ->addLanguage(new TypeScriptLanguage()) ->addLanguage(new XmlLanguage()) ->addLanguage(new YamlLanguage()) diff --git a/src/Languages/Toml/Patterns/TomlBooleanPattern.php b/src/Languages/Toml/Patterns/TomlBooleanPattern.php new file mode 100644 index 00000000..39c627b0 --- /dev/null +++ b/src/Languages/Toml/Patterns/TomlBooleanPattern.php @@ -0,0 +1,25 @@ +true|false)(?![A-Za-z0-9_-])/'; + } + + public function getTokenType(): TokenType + { + return TokenTypeEnum::LITERAL; + } +} diff --git a/src/Languages/Toml/Patterns/TomlCommentPattern.php b/src/Languages/Toml/Patterns/TomlCommentPattern.php new file mode 100644 index 00000000..51fd626d --- /dev/null +++ b/src/Languages/Toml/Patterns/TomlCommentPattern.php @@ -0,0 +1,25 @@ +#[^\r\n]*)/'; + } + + public function getTokenType(): TokenType + { + return TokenTypeEnum::COMMENT; + } +} diff --git a/src/Languages/Toml/Patterns/TomlDateTimePattern.php b/src/Languages/Toml/Patterns/TomlDateTimePattern.php new file mode 100644 index 00000000..09139351 --- /dev/null +++ b/src/Languages/Toml/Patterns/TomlDateTimePattern.php @@ -0,0 +1,25 @@ +(?:\d{4}-\d{2}-\d{2}(?:[Tt ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[Zz]|[+-]\d{2}:\d{2})?)?|\d{2}:\d{2}:\d{2}(?:\.\d+)?))(?![A-Za-z0-9_-])/'; + } + + public function getTokenType(): TokenType + { + return TokenTypeEnum::VALUE; + } +} diff --git a/src/Languages/Toml/Patterns/TomlKeyPattern.php b/src/Languages/Toml/Patterns/TomlKeyPattern.php new file mode 100644 index 00000000..afff89d7 --- /dev/null +++ b/src/Languages/Toml/Patterns/TomlKeyPattern.php @@ -0,0 +1,27 @@ +(?:"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*'|[A-Za-z0-9_-]+)(?:[\t ]*\.[\t ]*(?:"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*'|[A-Za-z0-9_-]+))*)(?=[\t ]*=)/m +REGEX; + } + + public function getTokenType(): TokenType + { + return TokenTypeEnum::PROPERTY; + } +} diff --git a/src/Languages/Toml/Patterns/TomlNumberPattern.php b/src/Languages/Toml/Patterns/TomlNumberPattern.php new file mode 100644 index 00000000..a8a2b90b --- /dev/null +++ b/src/Languages/Toml/Patterns/TomlNumberPattern.php @@ -0,0 +1,27 @@ +[+-]?(?:inf|nan)|0x[0-9A-Fa-f](?:_?[0-9A-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|[+-]?(?:\d(?:_?\d)*\.\d(?:_?\d)*(?:[eE][+-]?\d(?:_?\d)*)?|\d(?:_?\d)*[eE][+-]?\d(?:_?\d)*|\d(?:_?\d)*))(?![A-Za-z0-9_.-])/ +REGEX; + } + + public function getTokenType(): TokenType + { + return TokenTypeEnum::NUMBER; + } +} diff --git a/src/Languages/Toml/Patterns/TomlOperatorPattern.php b/src/Languages/Toml/Patterns/TomlOperatorPattern.php new file mode 100644 index 00000000..dd3d826b --- /dev/null +++ b/src/Languages/Toml/Patterns/TomlOperatorPattern.php @@ -0,0 +1,25 @@ +\[\[|\]\]|\[|\]|\{|\}|=|,)/'; + } + + public function getTokenType(): TokenType + { + return TokenTypeEnum::OPERATOR; + } +} diff --git a/src/Languages/Toml/Patterns/TomlStringPattern.php b/src/Languages/Toml/Patterns/TomlStringPattern.php new file mode 100644 index 00000000..232801b9 --- /dev/null +++ b/src/Languages/Toml/Patterns/TomlStringPattern.php @@ -0,0 +1,27 @@ +"""(?:\\[\s\S]|"{1,2}(?!")|[^"\\])*"""|'''(?:'{1,2}(?!')|[^'])*'''|"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*')/ +REGEX; + } + + public function getTokenType(): TokenType + { + return TokenTypeEnum::VALUE; + } +} diff --git a/src/Languages/Toml/Patterns/TomlTablePattern.php b/src/Languages/Toml/Patterns/TomlTablePattern.php new file mode 100644 index 00000000..f7144c1b --- /dev/null +++ b/src/Languages/Toml/Patterns/TomlTablePattern.php @@ -0,0 +1,27 @@ +(?:"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*'|[A-Za-z0-9_-]+)(?:[\t ]*\.[\t ]*(?:"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*'|[A-Za-z0-9_-]+))*)(?=[\t ]*\]{1,2})/m +REGEX; + } + + public function getTokenType(): TokenType + { + return TokenTypeEnum::TYPE; + } +} diff --git a/src/Languages/Toml/TomlLanguage.php b/src/Languages/Toml/TomlLanguage.php new file mode 100644 index 00000000..45ffea52 --- /dev/null +++ b/src/Languages/Toml/TomlLanguage.php @@ -0,0 +1,40 @@ + 'swift.txt', 'terminal' => 'terminal.txt', 'terraform' => 'terraform.txt', + 'toml' => 'toml.txt', 'typescript' => 'typescript.txt', 'txt' => 'text.txt', 'twig' => 'twig.txt', diff --git a/tests/Languages/Toml/TomlLanguageTest.php b/tests/Languages/Toml/TomlLanguageTest.php new file mode 100644 index 00000000..7bd0405f --- /dev/null +++ b/tests/Languages/Toml/TomlLanguageTest.php @@ -0,0 +1,116 @@ +assertContains('toml', $highlighter->getSupportedLanguageNames()); + + $highlighter->parse('', 'toml'); + + $this->assertInstanceOf(TomlLanguage::class, $highlighter->getCurrentLanguage()); + } + + #[Test] + public function it_escapes_html_and_strips_reserved_markers(): void + { + $source = "title = \"<©> ❷img src=x onerror=alert(1)❸ ❶❹❿\"\r\n" + . "script = \"\"\r" + . "enabled = true\r\n"; + + $highlighted = (new Highlighter())->parse($source, 'toml'); + $renderedSource = html_entity_decode(strip_tags($highlighted), ENT_QUOTES | ENT_HTML5); + + $expectedSource = str_replace(["\r\n", "\r"], "\n", str_replace(['❶', '❷', '❸', '❹', '❿'], '', $source)); + + $this->assertSame($expectedSource, $renderedSource); + $this->assertStringNotContainsString('