diff --git a/src/Highlighter.php b/src/Highlighter.php index 7f97a2c..461e85a 100644 --- a/src/Highlighter.php +++ b/src/Highlighter.php @@ -21,6 +21,7 @@ use Tempest\Highlight\Languages\JavaScript\JavaScriptLanguage; use Tempest\Highlight\Languages\Json\JsonLanguage; use Tempest\Highlight\Languages\Markdown\MarkdownLanguage; +use Tempest\Highlight\Languages\Nginx\NginxLanguage; use Tempest\Highlight\Languages\Php\PhpLanguage; use Tempest\Highlight\Languages\Python\PythonLanguage; use Tempest\Highlight\Languages\Scss\ScssLanguage; @@ -69,6 +70,7 @@ public function __construct(private readonly Theme $theme = new CssTheme()) ->addLanguage(new JavaScriptLanguage()) ->addLanguage(new JsonLanguage()) ->addLanguage(new MarkdownLanguage()) + ->addLanguage(new NginxLanguage()) ->addLanguage(new PhpLanguage()) ->addLanguage(new PythonLanguage()) ->addLanguage(new ScssLanguage()) diff --git a/src/Languages/Nginx/NginxLanguage.php b/src/Languages/Nginx/NginxLanguage.php new file mode 100644 index 0000000..cda7ade --- /dev/null +++ b/src/Languages/Nginx/NginxLanguage.php @@ -0,0 +1,68 @@ +on|off)\b'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::VALUE; + } +} diff --git a/src/Languages/Nginx/Patterns/NginxDirectivePattern.php b/src/Languages/Nginx/Patterns/NginxDirectivePattern.php new file mode 100644 index 0000000..1e4a5f0 --- /dev/null +++ b/src/Languages/Nginx/Patterns/NginxDirectivePattern.php @@ -0,0 +1,45 @@ +(?:{$directives}))\b"; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::KEYWORD; + } +} diff --git a/src/Languages/Nginx/Patterns/NginxOperatorPattern.php b/src/Languages/Nginx/Patterns/NginxOperatorPattern.php new file mode 100644 index 0000000..b1a05a5 --- /dev/null +++ b/src/Languages/Nginx/Patterns/NginxOperatorPattern.php @@ -0,0 +1,27 @@ +~\*|[;{}~=^])'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::OPERATOR; + } +} diff --git a/src/Languages/Nginx/Patterns/NginxVariablePattern.php b/src/Languages/Nginx/Patterns/NginxVariablePattern.php new file mode 100644 index 0000000..ed69d68 --- /dev/null +++ b/src/Languages/Nginx/Patterns/NginxVariablePattern.php @@ -0,0 +1,27 @@ +\$[a-zA-Z_]\w*)'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::VARIABLE; + } +} diff --git a/tests/Bench/Fixtures/nginx.txt b/tests/Bench/Fixtures/nginx.txt new file mode 100644 index 0000000..f49cdac --- /dev/null +++ b/tests/Bench/Fixtures/nginx.txt @@ -0,0 +1,74 @@ +# Main Nginx configuration +worker_processes auto; +error_log /var/log/nginx/error.log; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + gzip on; + gzip_types text/plain application/json; + + log_format main '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent'; + + upstream backend { + server 127.0.0.1:8080; + server 127.0.0.1:8081; + } + + server { + listen 80; + server_name example.com www.example.com; + return 301 https://$host$request_uri; + } + + server { + listen 443 ssl; + server_name example.com; + + ssl_certificate /etc/ssl/certs/example.pem; + ssl_certificate_key /etc/ssl/private/example.key; + ssl_protocols TLSv1.2 TLSv1.3; + + root /var/www/html; + index index.html index.htm; + + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options "nosniff"; + + location / { + try_files $uri $uri/ =404; + } + + location /api { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + } + + location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { + expires 30d; + access_log off; + } + + location = /health { + stub_status; + allow 127.0.0.1; + deny all; + } + + if ($request_uri ~* "^/old-path") { + rewrite ^/old-path(.*)$ /new-path$1 permanent; + } + } +} diff --git a/tests/Bench/HighlighterBench.php b/tests/Bench/HighlighterBench.php index 23685c5..ef4f42d 100644 --- a/tests/Bench/HighlighterBench.php +++ b/tests/Bench/HighlighterBench.php @@ -31,6 +31,7 @@ final class HighlighterBench 'javascript' => 'javascript.txt', 'json' => 'json.txt', 'markdown' => 'markdown.txt', + 'nginx' => 'nginx.txt', 'php' => 'php.txt', 'python' => 'python.txt', 'scss' => 'scss.txt', diff --git a/tests/Languages/Nginx/NginxLanguageTest.php b/tests/Languages/Nginx/NginxLanguageTest.php new file mode 100644 index 0000000..a970b90 --- /dev/null +++ b/tests/Languages/Nginx/NginxLanguageTest.php @@ -0,0 +1,108 @@ +assertSame( + $expected, + $highlighter->parse($content, 'nginx'), + ); + + $this->assertSame( + $expected, + $highlighter->parse($content, 'nginxconf'), + ); + } + + public static function provide_highlight_cases(): iterable + { + return [ + [<<<'TXT' +# Reverse proxy configuration +server { + listen 80; + server_name example.com; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + } + + location ~* \.(jpg|css|js)$ { + expires 30d; + gzip on; + } +} +TXT, + <<<'TXT' +# Reverse proxy configuration +server { + listen 80; + server_name example.com; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + } + + location ~* \.(jpg|css|js)$ { + expires 30d; + gzip on; + } +} +TXT], + [<<<'TXT' +upstream backend { + server 127.0.0.1:8080; + server 127.0.0.1:8081; + keepalive_timeout 65; +} +TXT, + <<<'TXT' +upstream backend { + server 127.0.0.1:8080; + server 127.0.0.1:8081; + keepalive_timeout 65; +} +TXT], + [<<<'TXT' +server { + listen 443 ssl; + ssl_certificate /etc/ssl/cert.pem; + ssl_certificate_key /etc/ssl/key.pem; + + add_header X-Frame-Options "SAMEORIGIN"; + + if ($request_uri ~* "^/old") { + return 301 $scheme://example.com/new; + } +} +TXT, + <<<'TXT' +server { + listen 443 ssl; + ssl_certificate /etc/ssl/cert.pem; + ssl_certificate_key /etc/ssl/key.pem; + + add_header X-Frame-Options "SAMEORIGIN"; + + if ($request_uri ~* "^/old") { + return 301 $scheme://example.com/new; + } +} +TXT], + ]; + } +}