From 017f9351a738d980c175fb82c12521b38537f969 Mon Sep 17 00:00:00 2001 From: DorZuberi Date: Sun, 29 Mar 2026 18:10:34 +0300 Subject: [PATCH] Add SCSS language support with patterns and tests --- src/Highlighter.php | 2 + .../Scss/Patterns/ScssCommentPattern.php | 27 +++++ .../Patterns/ScssInterpolationPattern.php | 27 +++++ .../Scss/Patterns/ScssKeywordPattern.php | 33 ++++++ .../Scss/Patterns/ScssSelectorPattern.php | 28 +++++ .../Scss/Patterns/ScssVariablePattern.php | 28 +++++ src/Languages/Scss/ScssLanguage.php | 42 ++++++++ tests/Bench/Fixtures/scss.txt | 100 ++++++++++++++++++ tests/Bench/HighlighterBench.php | 1 + tests/Languages/Scss/ScssLanguageTest.php | 79 ++++++++++++++ 10 files changed, 367 insertions(+) create mode 100644 src/Languages/Scss/Patterns/ScssCommentPattern.php create mode 100644 src/Languages/Scss/Patterns/ScssInterpolationPattern.php create mode 100644 src/Languages/Scss/Patterns/ScssKeywordPattern.php create mode 100644 src/Languages/Scss/Patterns/ScssSelectorPattern.php create mode 100644 src/Languages/Scss/Patterns/ScssVariablePattern.php create mode 100644 src/Languages/Scss/ScssLanguage.php create mode 100644 tests/Bench/Fixtures/scss.txt create mode 100644 tests/Languages/Scss/ScssLanguageTest.php diff --git a/src/Highlighter.php b/src/Highlighter.php index 1374bd4..19c8413 100644 --- a/src/Highlighter.php +++ b/src/Highlighter.php @@ -21,6 +21,7 @@ use Tempest\Highlight\Languages\Markdown\MarkdownLanguage; use Tempest\Highlight\Languages\Php\PhpLanguage; use Tempest\Highlight\Languages\Python\PythonLanguage; +use Tempest\Highlight\Languages\Scss\ScssLanguage; use Tempest\Highlight\Languages\Sql\SqlLanguage; use Tempest\Highlight\Languages\Text\TextLanguage; use Tempest\Highlight\Languages\Twig\TwigLanguage; @@ -64,6 +65,7 @@ public function __construct(private readonly Theme $theme = new CssTheme()) ->addLanguage(new MarkdownLanguage()) ->addLanguage(new PhpLanguage()) ->addLanguage(new PythonLanguage()) + ->addLanguage(new ScssLanguage()) ->addLanguage(new SqlLanguage()) ->addLanguage(new XmlLanguage()) ->addLanguage(new YamlLanguage()) diff --git a/src/Languages/Scss/Patterns/ScssCommentPattern.php b/src/Languages/Scss/Patterns/ScssCommentPattern.php new file mode 100644 index 0000000..7bcaf6d --- /dev/null +++ b/src/Languages/Scss/Patterns/ScssCommentPattern.php @@ -0,0 +1,27 @@ +\/\/.*)/'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::COMMENT; + } +} diff --git a/src/Languages/Scss/Patterns/ScssInterpolationPattern.php b/src/Languages/Scss/Patterns/ScssInterpolationPattern.php new file mode 100644 index 0000000..bebcdfc --- /dev/null +++ b/src/Languages/Scss/Patterns/ScssInterpolationPattern.php @@ -0,0 +1,27 @@ +#\{\$[\w\-]+\})'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::VARIABLE; + } +} diff --git a/src/Languages/Scss/Patterns/ScssKeywordPattern.php b/src/Languages/Scss/Patterns/ScssKeywordPattern.php new file mode 100644 index 0000000..23a07ff --- /dev/null +++ b/src/Languages/Scss/Patterns/ScssKeywordPattern.php @@ -0,0 +1,33 @@ +@(?:mixin|include|extend|function|return|if|else|for|each|while|use|forward|at-root|debug|warn|error))\b'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::KEYWORD; + } +} diff --git a/src/Languages/Scss/Patterns/ScssSelectorPattern.php b/src/Languages/Scss/Patterns/ScssSelectorPattern.php new file mode 100644 index 0000000..42b0976 --- /dev/null +++ b/src/Languages/Scss/Patterns/ScssSelectorPattern.php @@ -0,0 +1,28 @@ +[\[\]\'\"\=\@\-\#\.\w\s,\n\+\:\(\)\*\&\%]+)\{'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::KEYWORD; + } +} diff --git a/src/Languages/Scss/Patterns/ScssVariablePattern.php b/src/Languages/Scss/Patterns/ScssVariablePattern.php new file mode 100644 index 0000000..cd5105c --- /dev/null +++ b/src/Languages/Scss/Patterns/ScssVariablePattern.php @@ -0,0 +1,28 @@ +\$[\w\-]+)'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::VARIABLE; + } +} diff --git a/src/Languages/Scss/ScssLanguage.php b/src/Languages/Scss/ScssLanguage.php new file mode 100644 index 0000000..19acf39 --- /dev/null +++ b/src/Languages/Scss/ScssLanguage.php @@ -0,0 +1,42 @@ + 'markdown.txt', 'php' => 'php.txt', 'python' => 'python.txt', + 'scss' => 'scss.txt', 'sql' => 'sql.txt', 'twig' => 'twig.txt', 'xml' => 'xml.txt', diff --git a/tests/Languages/Scss/ScssLanguageTest.php b/tests/Languages/Scss/ScssLanguageTest.php new file mode 100644 index 0000000..9de3735 --- /dev/null +++ b/tests/Languages/Scss/ScssLanguageTest.php @@ -0,0 +1,79 @@ +assertSame( + $expected, + $highlighter->parse($content, 'scss'), + ); + } + + public static function provide_highlight_cases(): iterable + { + return [ + // SCSS variable + [ + '$primary: #333;', + '$primary: #333;', + ], + // Single-line comment + [ + '// this is a comment', + '// this is a comment', + ], + // Mixin definition + [ + '@mixin rounded {', + '@mixin rounded {', + ], + // @include + [ + '@include rounded;', + '@include rounded;', + ], + // Parent selector (& is HTML-encoded) + [ + '&:hover {', + '&:hover {', + ], + // Placeholder selector + [ + '%placeholder {', + '%placeholder {', + ], + // @each keyword with variables + [ + '@each $color in $colors {', + '@each $color in $colors {', + ], + // CSS features still work + [ + '@media only screen and (max-width: 500px) {}', + '@media only screen and (max-width: 500px) {}', + ], + // CSS property + [ + 'color: $primary;', + 'color: $primary;', + ], + // SCSS function + [ + 'background: darken($color, 10%);', + 'background: darken($color, 10%);', + ], + ]; + } +}