Upgrade all packages

PHP to 8.4
Twig 3
Sculpin 3.3.0-alpha4 (to support Twig 3)
CommonMark 2
spatie/commonmark-highlighter v3 (to support CommonMark v2)
aptoma/twig-markdown dropped and ported inside the project
This commit is contained in:
Alessandro Lai
2025-02-25 15:37:17 +01:00
parent e207cbfeea
commit 0ad1361ebe
15 changed files with 1421 additions and 831 deletions

View File

@@ -40,12 +40,12 @@ services:
tags:
- { name: twig.extension }
aptoma.twig.markdown_extension:
class: Aptoma\Twig\Extension\MarkdownExtension
markdown_extension:
class: \Fig\Website\MarkdownExtension
arguments:
$markdownEngine: '@Aptoma\Twig\Extension\MarkdownEngineInterface'
$markdownConverter: '@League\CommonMark\GithubFlavoredMarkdownConverter'
tags:
- { name: twig.extension }
Aptoma\Twig\Extension\MarkdownEngineInterface:
factory: ['Fig\Website\CommonMarkEngineFactory', 'create']
League\CommonMark\GithubFlavoredMarkdownConverter:
factory: ['Fig\Website\MarkdownConverterFactory', 'create']

View File

@@ -1,48 +0,0 @@
<?php
namespace Fig\Website;
use Aptoma\Twig\Extension\MarkdownEngine\PHPLeagueCommonMarkEngine;
use Aptoma\Twig\Extension\MarkdownEngineInterface;
use League\CommonMark\Block\Element\FencedCode;
use League\CommonMark\Block\Element\IndentedCode;
use League\CommonMark\Environment;
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\GithubFlavoredMarkdownConverter;
use Spatie\CommonMarkHighlighter\FencedCodeRenderer;
use Spatie\CommonMarkHighlighter\IndentedCodeRenderer;
class CommonMarkEngineFactory
{
public static function create(): MarkdownEngineInterface
{
$supportedLanguages = [
'php',
'http', # inside PSR-7
];
$config = [
'heading_permalink' => [
'id_prefix' => '',
'fragment_prefix' => '',
'insert' => 'after',
],
];
$environment = Environment::createCommonMarkEnvironment();
$environment->mergeConfig($config);
$environment
->addExtension(new TableExtension())
->addExtension(new HeadingPermalinkExtension())
->addBlockRenderer(FencedCode::class, new FencedCodeRenderer($supportedLanguages))
->addBlockRenderer(IndentedCode::class, new IndentedCodeRenderer($supportedLanguages))
;
return new NullSafeCommonMarkEngine(
new PHPLeagueCommonMarkEngine(
new GithubFlavoredMarkdownConverter([], $environment)
)
);
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace Fig\Website;
use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode;
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\GithubFlavoredMarkdownConverter;
use Spatie\CommonMarkHighlighter\FencedCodeRenderer;
use Spatie\CommonMarkHighlighter\IndentedCodeRenderer;
class MarkdownConverterFactory
{
public static function create(): GithubFlavoredMarkdownConverter
{
$supportedLanguages = [
'php',
'http', # inside PSR-7
];
$config = [
'heading_permalink' => [
'id_prefix' => '',
'fragment_prefix' => '',
'insert' => 'after',
],
];
$converter = new GithubFlavoredMarkdownConverter($config);
$environment = $converter->getEnvironment();
$environment
->addExtension(new TableExtension())
->addExtension(new HeadingPermalinkExtension())
->addRenderer(FencedCode::class, new FencedCodeRenderer($supportedLanguages))
->addRenderer(IndentedCode::class, new IndentedCodeRenderer($supportedLanguages))
;
return $converter;
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace Fig\Website;
use League\CommonMark\GithubFlavoredMarkdownConverter;
/**
* MarkdownExtension provides support for Markdown.
* Ported from \Aptoma\Twig\Extension\MarkdownExtension
*/
class MarkdownExtension extends \Twig\Extension\AbstractExtension
{
public function __construct(
private readonly GithubFlavoredMarkdownConverter $markdownConverter,
) {}
/**
* {@inheritdoc}
*/
public function getFilters(): array
{
return [
new \Twig\TwigFilter(
'markdown',
$this->parseMarkdown(...),
['is_safe' => ['html']]
)
];
}
/**
* Transform Markdown content to HTML
*
* @param string|null $content The Markdown content to be transformed, coming from Twig
* @return string The result of the Markdown engine transformation into HTML
*/
public function parseMarkdown(?string $content): string
{
if (null === $content) {
return '';
}
return $this->markdownConverter->convert($content);
}
/**
* {@inheritdoc}
*/
public function getTokenParsers(): array
{
return [new MarkdownTokenParser()];
}
}

34
app/lib/MarkdownNode.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
namespace Fig\Website;
/**
* Represents a markdown node.
* Ported from \Aptoma\Twig\Node\MarkdownNode
*/
class MarkdownNode extends \Twig\Node\Node
{
public function __construct(\Twig\Node\Node $body, $lineno, $tag = 'markdown')
{
parent::__construct(array('body' => $body), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param \Twig\Compiler A Twig\Compiler instance
*/
public function compile(\Twig\Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write('ob_start();' . PHP_EOL)
->subcompile($this->getNode('body'))
->write('$content = ob_get_clean();' . PHP_EOL)
->write('preg_match("/^\s*/", $content, $matches);' . PHP_EOL)
->write('$lines = explode("\n", $content);' . PHP_EOL)
->write('$content = preg_replace(\'/^\' . $matches[0]. \'/\', "", $lines);' . PHP_EOL)
->write('$content = join("\n", $content);' . PHP_EOL)
->write('echo $this->env->getExtension(\'Fig\Website\MarkdownExtension\')->parseMarkdown($content);' . PHP_EOL);
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace Fig\Website;
/**
* Ported from \Aptoma\Twig\TokenParser\MarkdownTokenParser
*/
class MarkdownTokenParser extends \Twig\TokenParser\AbstractTokenParser
{
/**
* {@inheritdoc}
*/
public function parse(\Twig\Token $token): MarkdownNode
{
$lineno = $token->getLine();
$this->parser->getStream()->expect(\Twig\Token::BLOCK_END_TYPE);
$body = $this->parser->subparse(array($this, 'decideMarkdownEnd'), true);
$this->parser->getStream()->expect(\Twig\Token::BLOCK_END_TYPE);
return new MarkdownNode($body, $lineno, $this->getTag());
}
/**
* Decide if current token marks end of Markdown block.
*/
public function decideMarkdownEnd(\Twig\Token $token): bool
{
return $token->test('endmarkdown');
}
/**
* {@inheritdoc}
*/
public function getTag(): string
{
return 'markdown';
}
}

View File

@@ -1,26 +0,0 @@
<?php
namespace Fig\Website;
use Aptoma\Twig\Extension\MarkdownEngineInterface;
class NullSafeCommonMarkEngine implements MarkdownEngineInterface
{
/** @var MarkdownEngineInterface */
private $engine;
public function __construct(MarkdownEngineInterface $engine)
{
$this->engine = $engine;
}
public function transform($content): string
{
return $this->engine->transform((string) $content);
}
public function getName(): string
{
return $this->engine->getName();
}
}

View File

@@ -2,13 +2,13 @@
"name": "fig/www.php-fig.org",
"description": "The static official site of PHP-FIG",
"require": {
"php": "~8.1",
"aptoma/twig-markdown": "^3.3",
"league/commonmark": "^1.4",
"sculpin/sculpin": "^3.2.0",
"spatie/commonmark-highlighter": "^2.1",
"symfony/flex": "^2.2",
"symfony/polyfill-iconv": "^1.23"
"php": "~8.4",
"league/commonmark": "^2",
"sculpin/sculpin": "^3.3.0-alpha4",
"spatie/commonmark-highlighter": "^3",
"symfony/flex": "^2.4",
"symfony/polyfill-iconv": "^1.23",
"twig/twig": "^3"
},
"replace": {
"sculpin/sculpin-theme-composer-plugin": "1.0.2"

1953
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
FROM php:8.1-cli-alpine
FROM php:8.4-cli-alpine
RUN apk add --no-cache \
bash \

View File

@@ -10,8 +10,10 @@
{{ post.date|date('F jS Y') }}
</span>
{% if skipAuthor is empty %}
{% for author in data.authors if post.author and author.identifier is same as(post.author) %}
{% for author in data.authors %}
{% if post.author and author.identifier is same as(post.author) %}
- <a class="blog-list__meta__author" href="{{ author.url }}">{{ author.title }}</a>
{% endif %}
{% endfor %}
{% endif %}

View File

@@ -31,8 +31,10 @@
<div class="author__posts">
<h2 class="author__posts__subtitle">Articles by {{ page.title }}</h2>
{% for post in data.posts if post.author and page.identifier == post.author %}
{% for post in data.posts %}
{% if post.author and page.identifier == post.author %}
{% include 'post-preview.twig' with {skipAuthor: true} %}
{% endif %}
{% endfor %}
</div>
</div>

View File

@@ -14,12 +14,14 @@
</span>
</div>
{% for author in data.authors if page.author and author.identifier == page.author %}
{% for author in data.authors %}
{% if page.author and author.identifier == page.author %}
<div class="columns__column columns__column--4 columns__column--padding_left">
<nav class="sidebar">
{% include 'post-author.twig' %}
</nav>
</div>
{% endif %}
{% endfor %}
{% endblock %}

View File

@@ -23,12 +23,12 @@ use:
<id>{{ site.host }}{{ post.url }}</id>
<content type="html"><![CDATA[{{ post.blocks.content|striptags('<p><br><em><strong><blockquote><ul><ol><li><img><pre><code><a><h1><h2><h3><h4><h5><h6>')|raw }}]]></content>
{% for author in data.authors if post.author and author.identifier is same as(post.author) %}
{% for author in data.authors %}{% if post.author and author.identifier is same as(post.author) %}
<author>
<name><![CDATA[{{ author.title }}]]></name>
<uri>{{ site.host }}{{ author.url }}</uri>
</author>
{% endfor %}
{% endif %}{% endfor %}
</entry>
{% endfor %}

View File

@@ -37,7 +37,7 @@ title: PHP-FIG — PHP Framework Interop Group
<div class="home_features__chrome_dot"></div>
</div>
<div class="home_features__code">
{% filter markdown %}
{% markdown %}
~~~php
<?php
@@ -45,7 +45,7 @@ use Vendor\Package\ClassName;
$object = new ClassName();
~~~
{% endfilter %}
{% endmarkdown %}
</div>
</div>
</div>
@@ -72,7 +72,7 @@ $object = new ClassName();
<div class="home_features__chrome_dot"></div>
</div>
<div class="home_features__code">
{% filter markdown %}
{% markdown %}
~~~php
<?php
@@ -84,7 +84,7 @@ namespace Psr\Log;
interface LoggerInterface
{
~~~
{% endfilter %}
{% endmarkdown %}
</div>
</div>
</div>
@@ -108,7 +108,7 @@ interface LoggerInterface
<div class="home_features__chrome_dot"></div>
</div>
<div class="home_features__code">
{% filter markdown %}
{% markdown %}
~~~php
<?php
@@ -120,7 +120,7 @@ namespace Psr\Http\Message;
interface RequestInterface extends MessageInterface
{
~~~
{% endfilter %}
{% endmarkdown %}
</div>
</div>
</div>
@@ -142,7 +142,7 @@ interface RequestInterface extends MessageInterface
<div class="home_features__chrome_dot"></div>
</div>
<div class="home_features__code">
{% filter markdown %}
{% markdown %}
~~~php
<?php
@@ -156,7 +156,7 @@ class ClassName
}
}
~~~
{% endfilter %}
{% endmarkdown %}
</div>
</div>
</div>