mirror of
https://github.com/getgrav/grav.git
synced 2026-07-05 20:49:33 +02:00
Added twig tag for links: {% link icon 'theme://images/favicon.png' priority: 20 with { type: 'image/png' } %}
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
1. [](#new)
|
||||
* Added links and modules support to `HtmlBlock` class
|
||||
* Added module support for twig script tag: `{% script module 'theme://js/module.mjs' %}`
|
||||
* Added twig tag for links: `{% link icon 'theme://images/favicon.png' priority: 20 with { type: 'image/png' } %}`
|
||||
|
||||
# v1.7.27.1
|
||||
## 01/12/2022
|
||||
|
||||
@@ -22,6 +22,7 @@ use Grav\Common\Page\Media;
|
||||
use Grav\Common\Scheduler\Cron;
|
||||
use Grav\Common\Security;
|
||||
use Grav\Common\Twig\TokenParser\TwigTokenParserCache;
|
||||
use Grav\Common\Twig\TokenParser\TwigTokenParserLink;
|
||||
use Grav\Common\Twig\TokenParser\TwigTokenParserRender;
|
||||
use Grav\Common\Twig\TokenParser\TwigTokenParserScript;
|
||||
use Grav\Common\Twig\TokenParser\TwigTokenParserStyle;
|
||||
@@ -252,6 +253,7 @@ class GravExtension extends AbstractExtension implements GlobalsInterface
|
||||
new TwigTokenParserTryCatch(),
|
||||
new TwigTokenParserScript(),
|
||||
new TwigTokenParserStyle(),
|
||||
new TwigTokenParserLink(),
|
||||
new TwigTokenParserMarkdown(),
|
||||
new TwigTokenParserSwitch(),
|
||||
new TwigTokenParserCache(),
|
||||
|
||||
98
system/src/Grav/Common/Twig/Node/TwigNodeLink.php
Normal file
98
system/src/Grav/Common/Twig/Node/TwigNodeLink.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Twig
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Twig\Node;
|
||||
|
||||
use LogicException;
|
||||
use Twig\Compiler;
|
||||
use Twig\Node\Expression\AbstractExpression;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Node\NodeCaptureInterface;
|
||||
|
||||
/**
|
||||
* Class TwigNodeLink
|
||||
* @package Grav\Common\Twig\Node
|
||||
*/
|
||||
class TwigNodeLink extends Node implements NodeCaptureInterface
|
||||
{
|
||||
/** @var string */
|
||||
protected $tagName = 'link';
|
||||
|
||||
/**
|
||||
* TwigNodeLink constructor.
|
||||
* @param string|null $rel
|
||||
* @param AbstractExpression|null $file
|
||||
* @param AbstractExpression|null $group
|
||||
* @param AbstractExpression|null $priority
|
||||
* @param AbstractExpression|null $attributes
|
||||
* @param int $lineno
|
||||
* @param string|null $tag
|
||||
*/
|
||||
public function __construct(?string $rel, ?AbstractExpression $file, ?AbstractExpression $group, ?AbstractExpression $priority, ?AbstractExpression $attributes, $lineno = 0, $tag = null)
|
||||
{
|
||||
$nodes = ['file' => $file, 'group' => $group, 'priority' => $priority, 'attributes' => $attributes];
|
||||
$nodes = array_filter($nodes);
|
||||
|
||||
parent::__construct($nodes, ['rel' => $rel], $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Compiler $compiler A Twig Compiler instance
|
||||
* @return void
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
$compiler->addDebugInfo($this);
|
||||
if (!$this->hasNode('file')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$compiler->write("\$assets = \\Grav\\Common\\Grav::instance()['assets'];\n");
|
||||
|
||||
$compiler->write('$attributes = [\'rel\' => \'' . $this->getAttribute('rel') . '\'];' . "\n");
|
||||
if ($this->hasNode('attributes')) {
|
||||
$compiler
|
||||
->write('$attributes += ')
|
||||
->subcompile($this->getNode('attributes'))
|
||||
->raw(";\n")
|
||||
->write("if (!is_array(\$attributes)) {\n")
|
||||
->indent()
|
||||
->write("throw new UnexpectedValueException('{% {$this->tagName} with x %}: x is not an array');\n")
|
||||
->outdent()
|
||||
->write("}\n");
|
||||
}
|
||||
|
||||
if ($this->hasNode('group')) {
|
||||
$compiler
|
||||
->write("\$attributes['group'] = ")
|
||||
->subcompile($this->getNode('group'))
|
||||
->raw(";\n")
|
||||
->write("if (!is_string(\$attributes['group'])) {\n")
|
||||
->indent()
|
||||
->write("throw new UnexpectedValueException('{% {$this->tagName} in x %}: x is not a string');\n")
|
||||
->outdent()
|
||||
->write("}\n");
|
||||
}
|
||||
|
||||
if ($this->hasNode('priority')) {
|
||||
$compiler
|
||||
->write("\$attributes['priority'] = (int)(")
|
||||
->subcompile($this->getNode('priority'))
|
||||
->raw(");\n");
|
||||
}
|
||||
|
||||
$compiler
|
||||
->write('$assets->addLink(')
|
||||
->subcompile($this->getNode('file'))
|
||||
->raw(", \$attributes);\n");
|
||||
}
|
||||
}
|
||||
109
system/src/Grav/Common/Twig/TokenParser/TwigTokenParserLink.php
Normal file
109
system/src/Grav/Common/Twig/TokenParser/TwigTokenParserLink.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Twig
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Twig\TokenParser;
|
||||
|
||||
use Grav\Common\Twig\Node\TwigNodeLink;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Token;
|
||||
use Twig\TokenParser\AbstractTokenParser;
|
||||
|
||||
/**
|
||||
* Adds a link to the document. First parameter is always value of `rel` without quotes.
|
||||
*
|
||||
* {% link icon 'theme://images/favicon.png' priority: 20 with { type: 'image/png' } %}
|
||||
* {% link modulepreload 'plugin://grav-plugin/build/js/vendor.js' %}
|
||||
*/
|
||||
class TwigTokenParserLink extends AbstractTokenParser
|
||||
{
|
||||
protected $rel = [
|
||||
'alternate',
|
||||
'author',
|
||||
'dns-prefetch',
|
||||
'help',
|
||||
'icon',
|
||||
'license',
|
||||
'next',
|
||||
'pingback',
|
||||
'preconnect',
|
||||
'prefetch',
|
||||
'preload',
|
||||
'prerender',
|
||||
'prev',
|
||||
'search',
|
||||
'stylesheet',
|
||||
];
|
||||
|
||||
/**
|
||||
* Parses a token and returns a node.
|
||||
*
|
||||
* @param Token $token
|
||||
* @return TwigNodeLink
|
||||
* @throws SyntaxError
|
||||
*/
|
||||
public function parse(Token $token)
|
||||
{
|
||||
$lineno = $token->getLine();
|
||||
|
||||
[$rel, $file, $group, $priority, $attributes] = $this->parseArguments($token);
|
||||
|
||||
return new TwigNodeLink($rel, $file, $group, $priority, $attributes, $lineno, $this->getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Token $token
|
||||
* @return array
|
||||
*/
|
||||
protected function parseArguments(Token $token): array
|
||||
{
|
||||
$stream = $this->parser->getStream();
|
||||
|
||||
|
||||
$rel = null;
|
||||
if ($stream->test(Token::NAME_TYPE, $this->rel)) {
|
||||
$rel = $stream->getCurrent()->getValue();
|
||||
$stream->next();
|
||||
}
|
||||
|
||||
$file = null;
|
||||
if (!$stream->test(Token::NAME_TYPE) && !$stream->test(Token::BLOCK_END_TYPE)) {
|
||||
$file = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
|
||||
$group = null;
|
||||
if ($stream->nextIf(Token::NAME_TYPE, 'at')) {
|
||||
$group = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
|
||||
$priority = null;
|
||||
if ($stream->nextIf(Token::NAME_TYPE, 'priority')) {
|
||||
$stream->expect(Token::PUNCTUATION_TYPE, ':');
|
||||
$priority = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
|
||||
$attributes = null;
|
||||
if ($stream->nextIf(Token::NAME_TYPE, 'with')) {
|
||||
$attributes = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return [$rel, $file, $group, $priority, $attributes];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tag name associated with this token parser.
|
||||
*
|
||||
* @return string The tag name
|
||||
*/
|
||||
public function getTag(): string
|
||||
{
|
||||
return 'link';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user