Skip to content

Commit 653222c

Browse files
committed
minor #1863 [Site] CodeBlock with gutter and line pre-slice (smnandre)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [Site] CodeBlock with gutter and line pre-slice | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Issues | Fix #... | License | MIT Improve code blocks style to focus on code and not the container. Add gutters and some pre-slicing that i need to finish this tshirt demos 😅 <img width="495" alt="Capture d’écran 2024-05-22 à 23 36 33" src="https://github.com/symfony/ux/assets/1359581/b3d7a462-5276-492d-83b0-a25a79e5921c"> <img width="444" alt="Capture d’écran 2024-05-22 à 23 36 29" src="https://github.com/symfony/ux/assets/1359581/30809186-f0ef-405e-952c-115da4dbc0d9"> <img width="505" alt="Capture d’écran 2024-05-22 à 23 36 41" src="https://github.com/symfony/ux/assets/1359581/67391708-249e-4555-9d29-fd19d2ffe67c"> <img width="564" alt="Capture d’écran 2024-05-22 à 23 36 37" src="https://github.com/symfony/ux/assets/1359581/c9fa9214-2130-425e-a27a-87f5c32076ff"> Commits ------- dde7117 [Site] CodeBlock with gutter and line pre-slice
2 parents f8f809f + dde7117 commit 653222c

File tree

4 files changed

+100
-4
lines changed

4 files changed

+100
-4
lines changed

ux.symfony.com/assets/styles/components/_Terminal.scss

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
font-size: 12px;
99
}
1010

11+
.Terminal_light {
12+
--header-opacity: .25;
13+
}
14+
1115
.Terminal_header {
1216
display: flex;
1317
background-color: var(--bg-header, #0D0D0DBA);
@@ -21,6 +25,7 @@
2125

2226
.Terminal:hover & {
2327
opacity: 1;
28+
transition: all 350ms ease-out;
2429
}
2530

2631
.nav-tabs {
@@ -58,6 +63,11 @@
5863
code {
5964
font-size: inherit;
6065
opacity: .8;
66+
67+
em {
68+
font-style: normal;
69+
color: #77d1e0 !important;
70+
}
6171
}
6272
}
6373

@@ -197,3 +207,17 @@
197207
color: #fff !important;
198208
opacity: 1;
199209
}
210+
211+
.Terminal .hl-gutter {
212+
display: inline-flex;
213+
font-size: 0.8em;
214+
color: #474747;
215+
padding: 0 1ch 0 0;
216+
user-select: none;
217+
margin-inline-start: -1ch;
218+
opacity: 0;
219+
transition: all 250ms;
220+
}
221+
.Terminal:hover .hl-gutter {
222+
opacity: 1;
223+
}

ux.symfony.com/src/Twig/Components/Code/CodeBlock.php

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,39 @@ class CodeBlock
3838
*/
3939
public bool $stripExcessHtml = false;
4040

41+
public ?int $lineStart = null;
42+
public ?int $lineEnd = null;
43+
4144
public function __construct(
4245
#[Autowire('%kernel.project_dir%')] private string $rootDir,
4346
) {
4447
}
4548

49+
public function mount(string $filename): void
50+
{
51+
if (str_contains($filename, '#')) {
52+
[$filename, $lines] = explode('#', $filename, 2);
53+
if (str_contains($lines, '#')) {
54+
throw new \InvalidArgumentException(sprintf('Invalid filename "%s": only one "#" is allowed.', $filename));
55+
}
56+
57+
if (!preg_match('/^L(\d+)(?:-L(\d+))?$/', $lines, $matches)) {
58+
throw new \InvalidArgumentException(sprintf('Invalid filename "%s": the line range is not valid.', $filename));
59+
}
60+
61+
$lineStart = (int) $matches[1];
62+
$lineEnd = (int) ($matches[2] ?? $matches[1]);
63+
if ($lineStart > $lineEnd) {
64+
throw new \InvalidArgumentException(sprintf('Invalid filename "%s": the line range is not valid.', $filename));
65+
}
66+
67+
$this->lineStart = $lineStart;
68+
$this->lineEnd = $lineEnd;
69+
}
70+
71+
$this->filename = $filename;
72+
}
73+
4674
/**
4775
* Returns a list of source code pieces, extracted from the filename
4876
* argument, ready to be renderer in the template.
@@ -74,6 +102,8 @@ public function getRawSource(): string
74102

75103
if ($this->targetTwigBlock) {
76104
$content = SourceCleaner::extractTwigBlock($content, $this->targetTwigBlock, $this->showTwigExtends);
105+
} elseif (null !== $this->getLineAnchor()) {
106+
$content = $this->extractLines($content, $this->lineStart, $this->lineEnd);
77107
}
78108

79109
if ($this->stripExcessHtml) {
@@ -83,9 +113,35 @@ public function getRawSource(): string
83113
return $content;
84114
}
85115

116+
private function extractLines(string $content, int $lineStart, int $lineEnd): string
117+
{
118+
$lines = explode("\n", $content);
119+
$lines = \array_slice($lines, $lineStart - 1, $lineEnd - $lineStart + 1);
120+
121+
return implode("\n", $lines);
122+
}
123+
124+
public function getLineAnchor(): ?string
125+
{
126+
if (null === $this->lineStart) {
127+
return null;
128+
}
129+
130+
$anchor = sprintf('L%d', $this->lineStart);
131+
if (null === $this->lineEnd) {
132+
return $anchor;
133+
}
134+
135+
if ($this->lineStart !== $this->lineEnd) {
136+
$anchor .= sprintf('-L%d', $this->lineEnd);
137+
}
138+
139+
return $anchor;
140+
}
141+
86142
public function getClassString(): string
87143
{
88-
return 'terminal-code'.($this->showFilename ? '' : ' terminal-code-no-filename');
144+
return 'terminal-code';
89145
}
90146

91147
public function getGithubLink(): string

ux.symfony.com/src/Twig/Extension/HighlightExtension.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,24 @@
2020
*/
2121
final class HighlightExtension extends AbstractExtension
2222
{
23+
public function __construct(
24+
private readonly Highlighter $highlighter,
25+
) {
26+
}
27+
2328
public function getFilters(): array
2429
{
2530
return [
26-
new TwigFilter('highlight', [Highlighter::class, 'parse'], ['is_safe' => ['html']]),
31+
new TwigFilter('highlight', $this->highlight(...), ['is_safe' => ['html']]),
2732
];
2833
}
34+
35+
public function highlight(string $code, string $language, ?int $startAt = null): string
36+
{
37+
if (null !== $startAt) {
38+
return $this->highlighter->withGutter($startAt)->parse($code, $language);
39+
}
40+
41+
return $this->highlighter->parse($code, $language);
42+
}
2943
}

ux.symfony.com/templates/components/Code/CodeBlock.html.twig

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
{% if showFilename %}
66
<div class="Terminal_header py-2 px-3 mb-0 d-flex justify-content-between align-items-center">
7-
<a id="{{ this.elementId }}" href="#{{ this.elementId }}" class="Terminal_title"><code>{{ filename }}</code></a>
7+
<a id="{{ this.elementId }}" href="#{{ this.elementId }}" class="Terminal_title">
8+
<code>{{ filename }}{% if this.lineStart %}<em>{{ '#%s'|format(this.lineAnchor) }}</em>{% endif %}</code>
9+
</a>
810
<div class="Terminal_actions">
911
<twig:Code:CodeBlockButtons source="{{ this.rawSource }}" link="{{ this.githubLink }}"/>
1012
</div>
@@ -23,7 +25,7 @@
2325
{% for piece in this.prepareSource %}
2426
{% if piece.highlight ?? true %}
2527
<pre><code class="language-{{ this.language }}">
26-
{{- piece.content|highlight(this.language) -}}
28+
{{- piece.content|highlight(this.language, this.lineStart) -}}
2729
</code></pre>
2830
{% else %}
2931
{{- piece.content|raw -}}

0 commit comments

Comments
 (0)