contentful/rich-text

Contentful Rich Text 工具

4.0.2 2024-06-03 11:36 UTC

README

Packagist PHP minimum version CircleCI License

此库旨在帮助您解析和渲染 Contentful 中的富文本字段类型。它需要 PHP 7.2 或更高版本或 PHP 8.0 或更高版本。

设置

使用 Composer 将此包添加到您的应用程序,并执行以下命令

composer require contentful/rich-text

然后,如果您还没有,请包含 Composer 自动加载器

require_once 'vendor/autoload.php';

解析

Contentful\RichText\Parser::parseLocalized(array $data, string|null $locale) 方法接受有效的未序列化富文本数据结构,并返回一个实现 Contentful\RichText\Node\NodeInterface 的对象。您还需要一个链接解析器来实例化解析器。

$parser = new Contentful\RichText\Parser($linkResolver);

// Fetch some data from an entry field from Contentful

/** @var Contentful\RichText\Node\NodeInterface $node */
$node = $parser->parseLocalized($data, $locale);

解析器还将自动解析任何链接的资产和条目。为此,您需要提供当前区域设置 - 否则,解析器将使用给定空间的默认区域设置解析链接。

根据节点实际类型,可以使用获取方法导航层次结构。请参阅可用节点的完整列表以获取完整参考。

渲染

此库的主要目的是提供一种自动渲染节点的方法。最简单的设置仅涉及创建 Contentful\RichText\Renderer 类的一个实例

$renderer = new Contentful\RichText\Renderer();

$output = $renderer->render($node);

库为所有支持的节点类型提供默认值。但是,您可能需要覆盖其中一些默认值,以自定义输出。为此,您将创建 NodeRenderer 类,这些类实现 Contentful\RichText\NodeRenderer\NodeRendererInterface 接口

namespace Contentful\RichText\NodeRenderer;

use Contentful\RichText\Node\NodeInterface;
use Contentful\RichText\RendererInterface;

/**
 * NodeRendererInterface.
 *
 * A class implementing this interface is responsible for
 * turning a limited subset of objects implementing NodeInterface
 * into a string.
 *
 * The node renderer makes the support for a certain node explicit by
 * implementing the "supports" method.
 *
 * The node renderer can also throw an exception during rendering if
 * the given node is not supported.
 */
interface NodeRendererInterface
{
    /**
     * Returns whether the current renderer
     * supports rendering the given node.
     *
     * @param NodeInterface $node The node which will be tested
     *
     * @return bool
     */
    public function supports(NodeInterface $node): bool;

    /**
     * Renders a node into a string.
     *
     * @param RendererInterface $renderer The generic renderer object, which is used for
     *                                    delegating rendering of nested nodes (such as ListItem in lists)
     * @param NodeInterface     $node     The node which must be rendered
     * @param array             $context  Optionally, extra context variables (useful with custom node renderers)
     *
     * @throws \InvalidArgumentException when the given $node is not supported
     *
     * @return string
     */
    public function render(RendererInterface $renderer, NodeInterface $node, array $context = []): string;
}

例如,如果您想将类添加到所有 h1 标签,您将得到类似下面的内容

use Contentful\RichText\NodeRenderer\NodeRendererInterface;
use Contentful\RichText\Node\NodeInterface;
use Contentful\RichText\Node\Heading1;
use Contentful\RichText\RendererInterface;

class CustomHeading1 implements NodeRendererInterface
{
    public function supports(NodeInterface $node): bool
    {
        return $node instanceof Heading1;
    }

    public function render(RendererInterface $renderer, NodeInterface $node, array $context = []): string
    {
        return '<h1 class="my-custom-class">'.$renderer->renderCollection($node->getContent()).'</h1>';
    }
}

最后,您需要告诉主渲染器使用您的自定义节点渲染器

$renderer->pushNodeRenderer(new CustomHeading1());

现在所有 Heading1 节点的实例都将使用自定义节点渲染器进行渲染。您可以在 supports 方法中实现任何逻辑,因为只需要一个接口,所以您可以在构造函数中注入任何类型的依赖项。例如,这样做是为了允许使用模板引擎,如 Twig 或 Plates

use Twig\Environment;
use Contentful\RichText\NodeRenderer\NodeRendererInterface;
use Contentful\RichText\Node\NodeInterface;
use Contentful\RichText\Node\Heading1;
use Contentful\RichText\RendererInterface;

class TwigCustomHeading1 implements NodeRendererInterface
{
    /**
     * @var Environment
     */
    private $twig;

    public function __construct(Environment $twig)
    {
        $this->twig = $twig;
    }

    public function supports(NodeInterface $node): bool
    {
        return $node instanceof Heading1;
    }

    public function render(RendererInterface $renderer, NodeInterface $node, array $context = []): string
    {
        $context['node'] = $node;

        return $this->twig->render('heading1.html.twig', $context);
    }
}

此库为 Twig 和 Plates 提供开箱即用的支持,允许您从模板中调用 RenderInterface::render()RenderInterface::renderCollection() 方法。要启用适当的扩展,只需让 Twig 环境或 Plates 引擎知道即可,如下所述。

Twig 集成

设置

$renderer = new Contentful\RichText\Renderer();

// Register the Twig extension, which will provide functions
// rich_text_render() and rich_text_render_collection()
// in a Twig template
$extension = new Contentful\RichText\Bridge\TwigExtension($renderer);

/** @var Twig\Environment $twig */
$twig->addExtension($extension);

// Finally, tell the main renderer about your custom node renderer
$customTwigHeading1NodeRenderer = new TwigCustomHeading1($twig);
$renderer->pushNodeRenderer($customTwigHeading1NodeRenderer);

模板

<h1 class="my-custom-class">{{ rich_text_render_collection(node.content) }}</h1>  

有关基于 Twig 的渲染过程的示例实现,请参阅测试节点渲染器完整的集成测试

Plates 集成

设置

$renderer = new \Contentful\RichText\Renderer();

// Register the Plates extension, which will provide functions
// $this->richTextRender() and $this->richTextRenderCollection()
// in a Plates template
$extension = new \Contentful\RichText\Bridge\PlatesExtension($renderer);

/** @var League\Plates\Engine $plates */
$plates->loadExtension($extension);

// Finally, tell the main renderer about your custom node renderer
$customPlatesHeading1NodeRenderer = new PlatesCustomHeading1($plates);
$renderer->pushNodeRenderer($customPlatesHeading1NodeRenderer);

模板

// The function will output HTML, so remember *not* to escape it using $this->e()
<?= $this->richTextRenderCollection($node->getContent()) ?>

有关基于Plates的渲染过程的示例实现,请查看测试节点渲染器完整的集成测试

如何避免主渲染器在遇到未知节点时抛出异常

默认情况下,当渲染器找不到合适的节点渲染器时,会抛出异常。为了避免这种情况,您必须将其设置为使用特殊的通用节点渲染器。

$renderer = new Contentful\RichText\Renderer();
$renderer->appendNodeRenderer(new Contentful\RichText\NodeRenderer\CatchAll());

特殊的Contentful\RichText\NodeRenderer\CatchAll节点渲染器无论节点类型如何都会返回空字符串。重要的是使用appendNodeRenderer而不是通常的pushNodeRenderer方法,以便让这个特殊的节点渲染器具有最低的优先级,从而避免它拦截常规节点渲染器。

术语表

关于Contentful

Contentful是一个面向网络应用程序、移动应用程序和互联设备的云内容管理系统。它允许您在云中创建、编辑和管理内容,并通过强大的API在任何地方发布。Contentful提供管理编辑团队和促进组织间协作的工具。

许可证

版权所有(c)2015-2019 Contentful GmbH。代码在MIT许可证下发布。有关详细信息,请参阅LICENSE