Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

highlighter tmp commit #254

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
25 changes: 14 additions & 11 deletions app/Docs.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Laravel\Unfenced\UnfencedExtension;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\Yaml\Yaml;
use App\Markdown\GitHubMarkdownConverter;

class Docs
{
Expand Down Expand Up @@ -126,16 +126,12 @@ public function variables(?string $key = null): mixed
*/
public function content(): ?string
{
return once(function () {
return Str::of($this->raw())
$content = Str::of($this->raw())
->replace('{{version}}', $this->version)
->after('---')
->after('---')
->markdown(extensions: [
new UnfencedExtension,
])
->toString();
});
->after('---');

return (new GitHubMarkdownConverter)->convert($content);
}

/**
Expand All @@ -149,11 +145,18 @@ public function content(): ?string
*/
public function view(string $view)
{
$data = Cache::remember('doc-file-view-data'.$this->path, now()->addMinutes(30), fn () => collect()->merge($this->variables())->merge([
// Cache во время разработки не нужен
//$data = Cache::remember('doc-file-view-data'.$this->path, now()->addMinutes(30), fn () => collect()->merge($this->variables())->merge([
// 'docs' => $this,
// 'content' => $this->content(),
// 'edit' => $this->getEditUrl(),
//]));

$data = collect()->merge($this->variables())->merge([
'docs' => $this,
'content' => $this->content(),
'edit' => $this->getEditUrl(),
]));
]);

return view($view, $data);
}
Expand Down
66 changes: 66 additions & 0 deletions app/MarkDown/CustomHL/CommonMark/CustomHighlightExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace App\MarkDown\CustomHL\CommonMark;

use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode;
//use League\CommonMark\Extension\CommonMark\Node\Inline\Code;
use League\CommonMark\Extension\ExtensionInterface;
use Tempest\Highlight\Highlighter;
use Tempest\Highlight\Themes\InlineTheme;
use Tempest\Highlight\CommonMark\CodeBlockRenderer;
//use Tempest\Highlight\CommonMark\InlineCodeBlockRenderer;
use App\MarkDown\CustomHL\Languages\Php\PhpLanguage;
use App\MarkDown\CustomHL\Languages\Shell\ShellLanguage;
//use App\MarkDown\CustomHL\Languages\Bash\BashLanguage;
use App\MarkDown\CustomHL\Languages\Ini\IniLanguage;
use App\MarkDown\CustomHL\Languages\Blade\BladeLanguage;
use App\MarkDown\CustomHL\Languages\Vue\VueLanguage;
use App\MarkDown\CustomHL\Languages\Nginx\NginxLanguage;
use App\MarkDown\CustomHL\Languages\JavaScript\JavaScriptLanguage;
//use App\MarkDown\CustomHL\Languages\Html\HtmlLanguage;
use App\MarkDown\CustomHL\Languages\Xml\XmlLanguage;
use App\MarkDown\CustomHL\Languages\Json\JsonLanguage;
use App\MarkDown\CustomHL\Languages\Sql\SqlLanguage;
use App\MarkDown\CustomHL\Languages\Yaml\YamlLanguage;
use App\MarkDown\CustomHL\Languages\ExtendedCss\ExtendedCssLanguage;

//use App\MarkDown\CustomHL\Languages\ExtendedPhp\ExtendedPhpLanguage;
//use App\MarkDown\CustomHL\Languages\ExtendedXml\ExtendedXmlLanguage;

final class CustomHighlightExtension implements ExtensionInterface
{
public function __construct(
private ?Highlighter $highlighter = new Highlighter(new InlineTheme(__DIR__ . '/../style.css')),
) {
$this->highlighter->addLanguage(new PhpLanguage());
$this->highlighter->addLanguage(new ShellLanguage());
// $this->highlighter->addLanguage(new BashLanguage());
$this->highlighter->addLanguage(new IniLanguage());
$this->highlighter->addLanguage(new BladeLanguage());
$this->highlighter->addLanguage(new VueLanguage());
$this->highlighter->addLanguage(new NginxLanguage());
$this->highlighter->addLanguage(new JavaScriptLanguage());
// $this->highlighter->addLanguage(new HtmlLanguage());
$this->highlighter->addLanguage(new XmlLanguage());
$this->highlighter->addLanguage(new JsonLanguage());
$this->highlighter->addLanguage(new SqlLanguage());
$this->highlighter->addLanguage(new YamlLanguage());
$this->highlighter->addLanguage(new ExtendedCssLanguage());

// $this->highlighter->addLanguage(new ExtendedPhpLanguage());
// $this->highlighter->addLanguage(new ExtendedXmlLanguage());
}

public function register(EnvironmentBuilderInterface $environment): void
{
$environment
->addRenderer(FencedCode::class, new CodeBlockRenderer($this->highlighter), 10)
->addRenderer(IndentedCode::class, new IndentedCodeBlockRenderer($this->highlighter), 10)
//->addRenderer(Code::class, new InlineCodeBlockRenderer($this->highlighter), 10)
;
}
}
52 changes: 52 additions & 0 deletions app/MarkDown/CustomHL/CommonMark/IndentedCodeBlockRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace App\MarkDown\CustomHL\CommonMark;

use InvalidArgumentException;
use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode;
use League\CommonMark\Node\Node;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Renderer\NodeRendererInterface;
use Tempest\Highlight\Highlighter;
use Tempest\Highlight\WebTheme;

final class IndentedCodeBlockRenderer implements NodeRendererInterface
{
public function __construct(
private Highlighter $highlighter = new Highlighter(),
) {
}

public function render(Node $node, ChildNodeRendererInterface $childRenderer)
{
//dd($node); //print_r($node);
if (! $node instanceof IndentedCode) {
//dd($node);
throw new InvalidArgumentException('Block must be instance of ' . IndentedCode::class);
}
//dd($node);

//preg_match('/^(?<language>[\w]+)(\{(?<startAt>[\d]+)\})?/', $node->getInfoWords()[0] ?? 'php', $matches);

$highlighter = $this->highlighter;

//if ($startAt = ($matches['startAt']) ?? null) {
// $highlighter = $highlighter->withGutter((int)$startAt);
//}

//$language = $matches['language'] ?? 'php';
$language = 'php';

$parsed = $highlighter->parse($node->getLiteral(), $language);

$theme = $highlighter->getTheme();

if ($theme instanceof WebTheme) {
return $theme->preBefore($highlighter) . $parsed . $theme->preAfter($highlighter);
} else {
return '<pre data-lang="' . $language . '" class="notranslate">' . $parsed . '</pre>';
}
}
}
54 changes: 54 additions & 0 deletions app/MarkDown/CustomHL/IsInjection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace App\MarkDown\CustomHL;

use Tempest\Highlight\Highlighter;
use Tempest\Highlight\ParsedInjection;

trait IsInjection
{
abstract public function getPattern(): string;

abstract public function parseContent(string $content, Highlighter $highlighter): string;

private function clearContent(string $input):string
{
return preg_replace(
['/❿(.*?)❿/', '/❷span(.*?)span❸/'],
'',
$input,
);
}

public function parse(string $content, Highlighter $highlighter): ParsedInjection
{
$pattern = $this->getPattern();

if (! str_starts_with($pattern, '/')) {
$pattern = "/{$pattern}/";
}

$cc = $this->clearContent($content);
$result = preg_replace_callback(
pattern: $pattern,
callback: function ($matches) use ($highlighter) {
$content = $matches['match'] ?? '';

if (! $content) {
return $matches[0];
}

return str_replace(
search: $content,
replace: $this->parseContent($content, $highlighter),
subject: $matches[0],
);
},
subject: $cc, //$content,
);

return new ParsedInjection($result ?? $content);
}
}
67 changes: 67 additions & 0 deletions app/MarkDown/CustomHL/Languages/Blade/BladeLanguage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace App\MarkDown\CustomHL\Languages\Blade;

use App\MarkDown\CustomHL\Languages\Blade\Injections\BladeEchoInjection;
//use App\Tempest\Highlight\Languages\Blade\Injections\BladeKeywordInjection;
use App\MarkDown\CustomHL\Languages\Blade\Injections\BladePhpInjection;
use App\MarkDown\CustomHL\Languages\Blade\Injections\BladeRawEchoInjection;
use App\MarkDown\CustomHL\Languages\Blade\Patterns\BladeCommentPattern;
use App\MarkDown\CustomHL\Languages\Blade\Patterns\BladeComponentCloseTagPattern;
use App\MarkDown\CustomHL\Languages\Blade\Patterns\BladeComponentOpenTagPattern;
use App\MarkDown\CustomHL\Languages\Blade\Patterns\BladeKeywordPattern;
use App\MarkDown\CustomHL\Languages\Html\HtmlLanguage;
use App\MarkDown\CustomHL\Languages\Blade\Patterns\DelimeterPattern;
use App\MarkDown\CustomHL\Languages\Blade\Patterns\KeywordPattern;
use App\MarkDown\CustomHL\Languages\Blade\Injections\SingleQuoteValueInjection;
use App\MarkDown\CustomHL\Languages\Blade\Patterns\GenericPattern;
use App\MarkDown\CustomHL\Languages\Blade\Patterns\EscapeSymbolPattern;
use App\MarkDown\CustomHL\Languages\Blade\Injections\BladeKeywordParametersInjection;

class BladeLanguage extends HtmlLanguage
{
public function getName(): string
{
return 'blade';
}

public function getAliases(): array
{
return ['html'];
}

public function getInjections(): array
{
return [
...parent::getInjections(),
//new BladeKeywordInjection(),
new BladePhpInjection(),
new BladeKeywordParametersInjection(),
new BladeEchoInjection(),
new BladeRawEchoInjection(),
new SingleQuoteValueInjection(),
];
}

public function getPatterns(): array
{
return [
...parent::getPatterns(),
//new BladeComponentOpenTagPattern(),
//new BladeComponentCloseTagPattern(),
new BladeKeywordPattern(),
new BladeCommentPattern(),

new DelimeterPattern('({!!|!!}|=\>)'), // {{|}}| // /(?<match>({!!|!!}|\<[^!](\/)?|\<(?!\!\--)|\>|=\>))/
new GenericPattern('/(?<match>({{(?!\-\-)))/', 'hl-blade-delimeter'), // /(?<match>({{(?!\-\-)|[^\-]}}|{!!|!!}))/
new GenericPattern('/[^\-](?<match>(}}))/', 'hl-blade-delimeter'), // /(?<match>({{(?!\-\-)|[^\-]}}|{!!|!!}))/
new GenericPattern('/(?<match>(\<(\/)?))[^!]/', 'hl-blade-delimeter'), // /(?<match>({{(?!\-\-)|[^\-]}}|{!!|!!}))/
new GenericPattern('/[^\-](?<match>(\>))/', 'hl-blade-delimeter'), // /(?<match>({{(?!\-\-)|[^\-]}}|{!!|!!}))/
new EscapeSymbolPattern(),

new KeywordPattern('as'),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace App\MarkDown\CustomHL\Languages\Blade\Injections;

use Tempest\Highlight\Highlighter;
use Tempest\Highlight\Injection;
use Tempest\Highlight\IsInjection;
use Tempest\Highlight\Escape;

final readonly class BladeEchoInjection implements Injection
{
use IsInjection;

public function getPattern(): string
{
return '({{(?!--))(?<match>(.|\n)*?)(}})';
}

public function parseContent(string $content, Highlighter $highlighter): string
{
return $highlighter->parse(Escape::terminal($content), 'php');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\MarkDown\CustomHL\Languages\Blade\Injections;

use Tempest\Highlight\Highlighter;
use Tempest\Highlight\Injection;
use Tempest\Highlight\IsInjection;

final readonly class BladeKeywordParametersInjection implements Injection
{
use IsInjection;

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

public function parseContent(string $content, Highlighter $highlighter): string
{
return $highlighter->parse($content, 'php');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\MarkDown\CustomHL\Languages\Blade\Injections;

use Tempest\Highlight\Highlighter;
use Tempest\Highlight\Injection;
use Tempest\Highlight\IsInjection;

final readonly class BladePhpInjection implements Injection
{
use IsInjection;

public function getPattern(): string
{
return '/(?<match>(\@php|<\?php)(.|\n)*?(\@endphp|\?>))/';
}

public function parseContent(string $content, Highlighter $highlighter): string
{
return $highlighter->parse($content, 'php');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\MarkDown\CustomHL\Languages\Blade\Injections;

use Tempest\Highlight\Highlighter;
use Tempest\Highlight\Injection;
use Tempest\Highlight\IsInjection;
use Tempest\Highlight\Escape;

final readonly class BladeRawEchoInjection implements Injection
{
use IsInjection;

public function getPattern(): string
{
return '({!!)(?<match>.*)(!!})';
}

public function parseContent(string $content, Highlighter $highlighter): string
{
$clear_content = Escape::terminal($content);
return $highlighter->parse($clear_content, 'php');
}
}
Loading