Skip to content

Commit

Permalink
Add Dockerfile highlighting
Browse files Browse the repository at this point in the history
  • Loading branch information
Sobak committed Feb 3, 2024
1 parent cba5508 commit 3888dc8
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 4 deletions.
12 changes: 12 additions & 0 deletions Config/metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,18 @@
'standalone' => true,
'injectable' => false,
],
[
'Kadet\\Highlighter\\Language\\Dockerfile',
'name' => [
'dockerfile',
],
'mime' => [],
'extension' => [
'Dockerfile',
],
'standalone' => true,
'injectable' => false,
],
[
'Kadet\\Highlighter\\Language\\Go',
'name' => [
Expand Down
5 changes: 3 additions & 2 deletions Docs/A-languages.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ All alias definitions can be found in [`Config/metadata.php`](../Config/metadata
<!-- aliasbegin -->
Class | Name | MIME | Extension
------|------|------|----------
`Kadet\Highlighter\Language\Apache` | `apache` | `application/xml`, `text/xml` | `.htaccess`
`Kadet\Highlighter\Language\Apache` | `apache` | none | `.htaccess`
`Kadet\Highlighter\Language\Assembler` | `asm`, `assembler` | `text/x-asm` | `*.asm`
`Kadet\Highlighter\Language\C` | `c` | `text/x-csrc`, `text/x-chdr` | `*.c`, `*.h`, `*.idc`
`Kadet\Highlighter\Language\CSharp` | `CSharp`, `C#` | `text/x-csharp` | `*.cs`
Expand All @@ -46,6 +46,7 @@ Class | Name | MIME | Extension
`Kadet\Highlighter\Language\Css\Less` | `less` | `text/x-less` | `*.less`
`Kadet\Highlighter\Language\Css\Sass` | `sass` | `text/x-sass` | `*.sass`
`Kadet\Highlighter\Language\Css\Scss` | `scss` | `text/x-scss` | `*.scss`
`Kadet\Highlighter\Language\Dockerfile` | `dockerfile` | none | `Dockerfile`
`Kadet\Highlighter\Language\Go` | `go`, `golang` | `text/x-go`, `application/x-go`, `text/x-golang`, `application/x-golang` | `*.go`
`Kadet\Highlighter\Language\Haskell` | `haskell` | `text/x-haskell` | `*.hs`
`Kadet\Highlighter\Language\Html` | `html` | `text/html` | `*.html`, `*.htm`
Expand All @@ -70,5 +71,5 @@ Class | Name | MIME | Extension
`Kadet\Highlighter\Language\TypeScript` | `ts`, `typescript` | `application/typescript`, `application/x-typescript`, `text/x-typescript`, `text/typescript` | `*.ts`, `*.tsx`
`Kadet\Highlighter\Language\UnifiedDiff` | `diff`, `patch` | `text/x-diff`, `text/x-patch`, `application/x-patch`, `application/x-diff` | `*.patch`, `*.diff`
`Kadet\Highlighter\Language\Xaml` | `xaml` | none | `*.xaml`
`Kadet\Highlighter\Language\Xml` | `xml` | none | `*.xml`
`Kadet\Highlighter\Language\Xml` | `xml` | `application/xml`, `text/xml` | `*.xml`
<!-- aliasend -->
59 changes: 59 additions & 0 deletions Language/Dockerfile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

/**
* Highlighter
*
* Copyright (C) 2016, Some right reserved.
*
* @author Kacper "Kadet" Donat <[email protected]>
*
* Contact with author:
* Xmpp: [email protected]
* E-mail: [email protected]
*
* From Kadet with love.
*/

namespace Kadet\Highlighter\Language;

use Kadet\Highlighter\Matcher\RegexMatcher;
use Kadet\Highlighter\Parser\Rule;

class Dockerfile extends Shell
{
public function setupRules()
{
parent::setupRules();

$keywords = [
'ADD', 'ARG', 'AS', 'CMD', 'COPY', 'ENTRYPOINT', 'ENV', 'EXPOSE', 'FROM',
'HEALTHCHECK', 'LABEL', 'MAINTAINER', 'ONBUILD', 'RUN', 'SHELL', 'STOPSIGNAL',
'USER', 'VOLUME', 'WORKDIR',
];

$this->rules->add('keyword', new Rule(
new RegexMatcher('/^\s*\b(' . implode('|', $keywords) . ')\b/mi'),
['priority' => 2]
));
}

/**
* Unique language identifier, for example 'php'
*
* @return string
*/
public function getIdentifier()
{
return 'dockerfile';
}

public static function getMetadata()
{
return [
'name' => ['dockerfile'],
'extension' => ['Dockerfile'],
];
}
}
33 changes: 33 additions & 0 deletions Tests/Expected/Test/dockerfile/medium.Dockerfile.tkn
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{language.dockerfile:Kadet\Highlighter\Parser\Token\LanguageToken}{keyword:Kadet\Highlighter\Parser\Token\Token}FROM{/keyword:Kadet\Highlighter\Parser\Token\Token} node:{number:Kadet\Highlighter\Parser\Token\Token}18{/number:Kadet\Highlighter\Parser\Token\Token}-alpine

{keyword:Kadet\Highlighter\Parser\Token\Token}WORKDIR{/keyword:Kadet\Highlighter\Parser\Token\Token} /app

{comment:Kadet\Highlighter\Parser\Token\Token}# Install dependencies based on the preferred package manager{/comment:Kadet\Highlighter\Parser\Token\Token}
{keyword:Kadet\Highlighter\Parser\Token\Token}COPY{/keyword:Kadet\Highlighter\Parser\Token\Token} package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
{keyword:Kadet\Highlighter\Parser\Token\Token}RUN{/keyword:Kadet\Highlighter\Parser\Token\Token} \
{keyword:Kadet\Highlighter\Parser\Token\Token}if{/keyword:Kadet\Highlighter\Parser\Token\Token} [ {symbol.parameter:Kadet\Highlighter\Parser\Token\Token}-f{/symbol.parameter:Kadet\Highlighter\Parser\Token\Token} yarn.lock ]; {keyword:Kadet\Highlighter\Parser\Token\Token}then{/keyword:Kadet\Highlighter\Parser\Token\Token} {call:Kadet\Highlighter\Parser\Token\Token}yarn{/call:Kadet\Highlighter\Parser\Token\Token} {symbol.parameter:Kadet\Highlighter\Parser\Token\Token}--frozen-lockfile{/symbol.parameter:Kadet\Highlighter\Parser\Token\Token}; \
{keyword:Kadet\Highlighter\Parser\Token\Token}elif{/keyword:Kadet\Highlighter\Parser\Token\Token} [ {symbol.parameter:Kadet\Highlighter\Parser\Token\Token}-f{/symbol.parameter:Kadet\Highlighter\Parser\Token\Token} package-lock.json ]; {keyword:Kadet\Highlighter\Parser\Token\Token}then{/keyword:Kadet\Highlighter\Parser\Token\Token} {call:Kadet\Highlighter\Parser\Token\Token}npm{/call:Kadet\Highlighter\Parser\Token\Token} ci; \
{keyword:Kadet\Highlighter\Parser\Token\Token}elif{/keyword:Kadet\Highlighter\Parser\Token\Token} [ {symbol.parameter:Kadet\Highlighter\Parser\Token\Token}-f{/symbol.parameter:Kadet\Highlighter\Parser\Token\Token} pnpm-lock.yaml ]; {keyword:Kadet\Highlighter\Parser\Token\Token}then{/keyword:Kadet\Highlighter\Parser\Token\Token} {call:Kadet\Highlighter\Parser\Token\Token}corepack{/call:Kadet\Highlighter\Parser\Token\Token} enable pnpm && pnpm i; \
{comment:Kadet\Highlighter\Parser\Token\Token}# Allow install without lockfile, so example works even without Node.js installed locally{/comment:Kadet\Highlighter\Parser\Token\Token}
{keyword:Kadet\Highlighter\Parser\Token\Token}else{/keyword:Kadet\Highlighter\Parser\Token\Token} {call:Kadet\Highlighter\Parser\Token\Token}echo{/call:Kadet\Highlighter\Parser\Token\Token} {string.double:Kadet\Highlighter\Parser\Token\ContextualToken}"Warning: Lockfile not found. It is recommended to commit lockfiles to version control."{/string.double:Kadet\Highlighter\Parser\Token\ContextualToken} && yarn install; \
{keyword:Kadet\Highlighter\Parser\Token\Token}fi{/keyword:Kadet\Highlighter\Parser\Token\Token}

{keyword:Kadet\Highlighter\Parser\Token\Token}COPY{/keyword:Kadet\Highlighter\Parser\Token\Token} src ./src
{keyword:Kadet\Highlighter\Parser\Token\Token}COPY{/keyword:Kadet\Highlighter\Parser\Token\Token} public ./public
{keyword:Kadet\Highlighter\Parser\Token\Token}COPY{/keyword:Kadet\Highlighter\Parser\Token\Token} next.config.js .
{keyword:Kadet\Highlighter\Parser\Token\Token}COPY{/keyword:Kadet\Highlighter\Parser\Token\Token} tsconfig.json .

{comment:Kadet\Highlighter\Parser\Token\Token}# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry{/comment:Kadet\Highlighter\Parser\Token\Token}
{comment:Kadet\Highlighter\Parser\Token\Token}# Uncomment the following line to disable telemetry at run time{/comment:Kadet\Highlighter\Parser\Token\Token}
{keyword:Kadet\Highlighter\Parser\Token\Token}ENV{/keyword:Kadet\Highlighter\Parser\Token\Token} NEXT_TELEMETRY_DISABLED {number:Kadet\Highlighter\Parser\Token\Token}1{/number:Kadet\Highlighter\Parser\Token\Token}

{comment:Kadet\Highlighter\Parser\Token\Token}# Note: Don't expose ports here, Compose will handle that for us{/comment:Kadet\Highlighter\Parser\Token\Token}

{comment:Kadet\Highlighter\Parser\Token\Token}# Start Next.js in development mode based on the preferred package manager{/comment:Kadet\Highlighter\Parser\Token\Token}
{keyword:Kadet\Highlighter\Parser\Token\Token}CMD{/keyword:Kadet\Highlighter\Parser\Token\Token} \
{keyword:Kadet\Highlighter\Parser\Token\Token}if{/keyword:Kadet\Highlighter\Parser\Token\Token} [ {symbol.parameter:Kadet\Highlighter\Parser\Token\Token}-f{/symbol.parameter:Kadet\Highlighter\Parser\Token\Token} yarn.lock ]; {keyword:Kadet\Highlighter\Parser\Token\Token}then{/keyword:Kadet\Highlighter\Parser\Token\Token} {call:Kadet\Highlighter\Parser\Token\Token}yarn{/call:Kadet\Highlighter\Parser\Token\Token} dev; \
{keyword:Kadet\Highlighter\Parser\Token\Token}elif{/keyword:Kadet\Highlighter\Parser\Token\Token} [ {symbol.parameter:Kadet\Highlighter\Parser\Token\Token}-f{/symbol.parameter:Kadet\Highlighter\Parser\Token\Token} package-lock.json ]; {keyword:Kadet\Highlighter\Parser\Token\Token}then{/keyword:Kadet\Highlighter\Parser\Token\Token} {call:Kadet\Highlighter\Parser\Token\Token}npm{/call:Kadet\Highlighter\Parser\Token\Token} run dev; \
{keyword:Kadet\Highlighter\Parser\Token\Token}elif{/keyword:Kadet\Highlighter\Parser\Token\Token} [ {symbol.parameter:Kadet\Highlighter\Parser\Token\Token}-f{/symbol.parameter:Kadet\Highlighter\Parser\Token\Token} pnpm-lock.yaml ]; {keyword:Kadet\Highlighter\Parser\Token\Token}then{/keyword:Kadet\Highlighter\Parser\Token\Token} {call:Kadet\Highlighter\Parser\Token\Token}pnpm{/call:Kadet\Highlighter\Parser\Token\Token} dev; \
{keyword:Kadet\Highlighter\Parser\Token\Token}else{/keyword:Kadet\Highlighter\Parser\Token\Token} {call:Kadet\Highlighter\Parser\Token\Token}npm{/call:Kadet\Highlighter\Parser\Token\Token} run dev; \
{keyword:Kadet\Highlighter\Parser\Token\Token}fi{/keyword:Kadet\Highlighter\Parser\Token\Token}
{/language.dockerfile:Kadet\Highlighter\Parser\Token\LanguageToken}
17 changes: 16 additions & 1 deletion Tests/LanguagesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class LanguagesTest extends TestCase
/** @var TestFormatter */
protected $_formatter;

private $_languageOverrides = [
'*.Dockerfile' => 'dockerfile',
];

public function testFileProvider()
{
$dir = realpath(__DIR__ . '/Samples');
Expand All @@ -33,7 +37,7 @@ public function testFileProvider()
/** @var \SplFileInfo $file */
foreach ($iterator as $file) {
$pathname = substr($file->getPathname(), strlen($dir) + 1);
$language = Language::byFilename($pathname);
$language = $this->getLanguageByFilename($pathname);

yield $pathname => [ $language, $file->getPathname(), "$out/$pathname.tkn" ];
}
Expand Down Expand Up @@ -67,4 +71,15 @@ public function testIfLanguageGeneratesValidTokens(Language $language, $input, $
"Normalized"
);
}

private function getLanguageByFilename($filename): Language
{
foreach ($this->_languageOverrides as $pattern => $language) {
if (fnmatch($pattern, $filename)) {
return Language::byName($language);
}
}

return Language::byFilename($filename);
}
}
32 changes: 32 additions & 0 deletions Tests/Samples/dockerfile/medium.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM node:18-alpine

WORKDIR /app

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i; \
# Allow install without lockfile, so example works even without Node.js installed locally
else echo "Warning: Lockfile not found. It is recommended to commit lockfiles to version control." && yarn install; \
fi

COPY src ./src
COPY public ./public
COPY next.config.js .
COPY tsconfig.json .

# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry
# Uncomment the following line to disable telemetry at run time
ENV NEXT_TELEMETRY_DISABLED 1

# Note: Don't expose ports here, Compose will handle that for us

# Start Next.js in development mode based on the preferred package manager
CMD \
if [ -f yarn.lock ]; then yarn dev; \
elif [ -f package-lock.json ]; then npm run dev; \
elif [ -f pnpm-lock.yaml ]; then pnpm dev; \
else npm run dev; \
fi
17 changes: 16 additions & 1 deletion bin/Commands/Test/RegenerateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class RegenerateCommand extends Command
private $_input;
private $_output;

private $_languageOverrides = [
'*.Dockerfile' => 'dockerfile',
];

protected function configure()
{
$this->setName('test:regenerate')
Expand Down Expand Up @@ -69,7 +73,7 @@ protected function execute(InputInterface $input, OutputInterface $output)

$output->writeln("Generating $pathname...", OutputInterface::VERBOSITY_QUIET);

$language = Language::byFilename($pathname);
$language = $this->getLanguageByFilename($pathname);
$tokens = $language->parse(file_get_contents($file->getPathname()));

if ($this->review($input, $output, $tokens, $reviewer)) {
Expand Down Expand Up @@ -120,4 +124,15 @@ private function regenerate(InputInterface $input, $filename)

return false;
}

private function getLanguageByFilename($filename): Language
{
foreach ($this->_languageOverrides as $pattern => $language) {
if (fnmatch($pattern, $filename)) {
return Language::byName($language);
}
}

return Language::byFilename($filename);
}
}
2 changes: 2 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
## Unreleased [0.9.1]

### Added
* **Dockerfile** highlighting via `Kadet\Highlighter\Language\Dockerfile`

### Fixed

## 2024-01-26 [0.9.0]
Expand Down

0 comments on commit 3888dc8

Please sign in to comment.