diff --git a/ux.symfony.com/assets/controllers/code-highlighter-controller.js b/ux.symfony.com/assets/controllers/code-highlighter-controller.js new file mode 100644 index 00000000000..1d59929259c --- /dev/null +++ b/ux.symfony.com/assets/controllers/code-highlighter-controller.js @@ -0,0 +1,27 @@ +import { Controller } from '@hotwired/stimulus'; +import hljs from 'highlight.js/lib/core'; +import hljs_javascript from 'highlight.js/lib/languages/javascript'; +import hljs_php from 'highlight.js/lib/languages/php'; +import hljs_xml from 'highlight.js/lib/languages/xml'; +import hljs_twig from 'highlight.js/lib/languages/twig'; + +hljs.registerLanguage('javascript', hljs_javascript); +hljs.registerLanguage('php', hljs_php); +hljs.registerLanguage('twig', hljs_twig); +// xml is the language used for HTML +hljs.registerLanguage('xml', hljs_xml); + +export default class extends Controller { + static targets = ['codeBlock']; + + codeBlockTargetConnected() { + this.codeBlockTargets.forEach(this.#highlightCodeBlock) + } + + #highlightCodeBlock(codeBlock) { + if (codeBlock.dataset.highlighted) { + return; + } + hljs.highlightElement(codeBlock); + } +} diff --git a/ux.symfony.com/assets/styles/components/_Terminal.scss b/ux.symfony.com/assets/styles/components/_Terminal.scss index d28222a1c9b..a51d9ce79d0 100644 --- a/ux.symfony.com/assets/styles/components/_Terminal.scss +++ b/ux.symfony.com/assets/styles/components/_Terminal.scss @@ -140,10 +140,16 @@ overflow-inline: auto; } .Terminal_body pre { - padding: 1rem; + padding: 0; margin: 0; } - .Terminal_content { font-size: .9rem; + overflow-x: auto; + overflow-y: auto; + padding: 1rem; + + pre { + overflow: visible; + } } diff --git a/ux.symfony.com/composer.json b/ux.symfony.com/composer.json index 2c0ca6da93b..9c68c893d14 100644 --- a/ux.symfony.com/composer.json +++ b/ux.symfony.com/composer.json @@ -16,7 +16,6 @@ "kornrunner/blurhash": "^1.2.2", "league/commonmark": "^2.4", "pagerfanta/twig": "^3.8", - "scrivo/highlight.php": "^9.18.1.10", "symfony/asset": "6.4.*", "symfony/asset-mapper": "6.4.*", "symfony/console": "6.4.*", diff --git a/ux.symfony.com/composer.lock b/ux.symfony.com/composer.lock index 52f0383c0c8..07868631162 100644 --- a/ux.symfony.com/composer.lock +++ b/ux.symfony.com/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5926673d04364246c83d5f4fb82e7246", + "content-hash": "4a3652b42255ce0490a8b3f688ec4c15", "packages": [ { "name": "babdev/pagerfanta-bundle", @@ -3012,84 +3012,6 @@ }, "time": "2019-03-08T08:55:37+00:00" }, - { - "name": "scrivo/highlight.php", - "version": "v9.18.1.10", - "source": { - "type": "git", - "url": "https://github.com/scrivo/highlight.php.git", - "reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/850f4b44697a2552e892ffe71490ba2733c2fc6e", - "reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": ">=5.4" - }, - "require-dev": { - "phpunit/phpunit": "^4.8|^5.7", - "sabberworm/php-css-parser": "^8.3", - "symfony/finder": "^2.8|^3.4|^5.4", - "symfony/var-dumper": "^2.8|^3.4|^5.4" - }, - "suggest": { - "ext-mbstring": "Allows highlighting code with unicode characters and supports language with unicode keywords" - }, - "type": "library", - "autoload": { - "files": [ - "HighlightUtilities/functions.php" - ], - "psr-0": { - "Highlight\\": "", - "HighlightUtilities\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Geert Bergman", - "homepage": "http://www.scrivo.org/", - "role": "Project Author" - }, - { - "name": "Vladimir Jimenez", - "homepage": "https://allejo.io", - "role": "Maintainer" - }, - { - "name": "Martin Folkers", - "homepage": "https://twobrain.io", - "role": "Contributor" - } - ], - "description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js", - "keywords": [ - "code", - "highlight", - "highlight.js", - "highlight.php", - "syntax" - ], - "support": { - "issues": "https://github.com/scrivo/highlight.php/issues", - "source": "https://github.com/scrivo/highlight.php" - }, - "funding": [ - { - "url": "https://github.com/allejo", - "type": "github" - } - ], - "time": "2022-12-17T21:53:22+00:00" - }, { "name": "symfony/asset", "version": "v6.4.0-BETA3", diff --git a/ux.symfony.com/importmap.php b/ux.symfony.com/importmap.php index 4e0dfc5c0d1..b84aaebc916 100644 --- a/ux.symfony.com/importmap.php +++ b/ux.symfony.com/importmap.php @@ -115,6 +115,15 @@ 'highlight.js/lib/languages/javascript' => [ 'version' => '11.7.0', ], + 'highlight.js/lib/languages/php' => [ + 'version' => '11.7.0', + ], + 'highlight.js/lib/languages/twig' => [ + 'version' => '11.7.0', + ], + 'highlight.js/lib/languages/xml' => [ + 'version' => '11.7.0', + ], 'intl-messageformat' => [ 'version' => '10.3.5', ], diff --git a/ux.symfony.com/src/Twig/CodeBlock.php b/ux.symfony.com/src/Twig/CodeBlock.php index a3b9d62a492..13fb2d7c0d8 100644 --- a/ux.symfony.com/src/Twig/CodeBlock.php +++ b/ux.symfony.com/src/Twig/CodeBlock.php @@ -13,7 +13,6 @@ use App\Util\FilenameHelper; use App\Util\SourceCleaner; -use Highlight\Highlighter; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; @@ -40,30 +39,28 @@ class CodeBlock public bool $stripExcessHtml = false; public function __construct( - private Highlighter $highlighter, #[Autowire('%kernel.project_dir%')] private string $rootDir, ) { } - public function highlightSource(): string + /** + * Returns a list of source code pieces, extracted from the filename + * argument, ready to be renderer in the template. + * + * Every piece is composed as an array {content, highlight} with + * content: the raw source code (after cleaning) + * highlight: whether they must be syntax-highlighted or not + * + * @return list + */ + public function prepareSource(): array { $content = $this->getRawSource(); if ('php' === $this->getLanguage()) { $content = SourceCleaner::cleanupPhpFile($content); } - $pieces = $this->splitAndProcessSource($content); - - $highlighted = []; - foreach ($pieces as $piece) { - if ($piece['highlight']) { - $highlighted[] = $this->highlighter->highlight($this->getLanguage(), $piece['content'])->value; - } else { - $highlighted[] = $piece['content']; - } - } - - return implode('', $highlighted); + return $this->splitAndProcessSource($content); } public function getRawSource(): string @@ -96,15 +93,17 @@ public function getGithubLink(): string return sprintf('https://github.com/symfony/ux/blob/2.x/ux.symfony.com/%s', $this->filename); } - private function getLanguage(): string + public function getLanguage(): string { if (null !== $this->language) { return $this->language; } - $parts = explode('.', $this->filename); + if ($ext = strrchr($this->filename, '.')) { + return $this->language = substr($ext, 1); + } - return array_pop($parts); + throw new \RuntimeException('Unable to detect the code language'); } public function getElementId(): ?string @@ -151,7 +150,8 @@ private function splitAndProcessSource(string $content): array // the use statements + surrounding span $parts[] = [ - 'content' => '// ... use statements hidden - click to show ', + 'content' => ' +
// ... use statements hidden - click to show
', 'highlight' => false, ]; $parts[] = [ diff --git a/ux.symfony.com/src/Util/SourceCleaner.php b/ux.symfony.com/src/Util/SourceCleaner.php index 9f79f2e9320..86d988990ab 100644 --- a/ux.symfony.com/src/Util/SourceCleaner.php +++ b/ux.symfony.com/src/Util/SourceCleaner.php @@ -17,22 +17,25 @@ class SourceCleaner { public static function cleanupPhpFile(string $contents, bool $removeClass = false): string { + // Remove replace("indexOf('* This file is part of the Symfony package')) { - $contents = $contents->after(' */'); + $contents = $contents->before('/*')->trim()->append($contents->after(' */')->trim()); } + // Remove namespace(s) $contents = $contents->replaceMatches('/namespace[^\n]*/', ''); + // Remove class declaration if ($removeClass) { $contents = $contents->replaceMatches('/class[^\n]*\n{/', '') ->trim('{}') - // remove use statements + // Remove use statements ->replaceMatches('/^use [^\n]*$/m', ''); - // unindent all lines by 4 spaces + // Unindent all lines by 4 spaces $lines = explode("\n", $contents); $lines = array_map(function (string $line) { return substr($line, 4); diff --git a/ux.symfony.com/symfony.lock b/ux.symfony.com/symfony.lock index 4523dea4334..20eb3dacec3 100644 --- a/ux.symfony.com/symfony.lock +++ b/ux.symfony.com/symfony.lock @@ -181,9 +181,6 @@ "ralouphie/getallheaders": { "version": "3.0.3" }, - "scrivo/highlight.php": { - "version": "v9.18.1.9" - }, "sebastian/cli-parser": { "version": "1.0.1" }, diff --git a/ux.symfony.com/templates/components/CodeBlock.html.twig b/ux.symfony.com/templates/components/CodeBlock.html.twig index 3f0a724f45a..61e7c85a08f 100644 --- a/ux.symfony.com/templates/components/CodeBlock.html.twig +++ b/ux.symfony.com/templates/components/CodeBlock.html.twig @@ -1,23 +1,36 @@
+ {% if showFilename %} {% endif %} +
{% if not showFilename %}
{% endif %} -

-            {{- this.highlightSource()|raw -}}
-        
+
+ {% for piece in this.prepareSource %} + {% if piece.highlight ?? true %} +

+                        {{- piece.content -}}
+                    
+ {% else %} + {{- piece.content|raw -}} + {% endif %} + {% endfor %} +
{% block code_content_bottom %}