m6web/draftjs-bundle

此包已被废弃且不再维护。未建议替代包。

将 Draft.js 状态渲染为 HTML

安装量: 1,965

依赖者: 0

建议者: 0

安全: 0

星标: 7

关注者: 12

分叉: 2

开放问题: 5

类型:symfony-bundle

v0.1.1 2017-02-21 08:40 UTC

This package is not auto-updated.

Last update: 2020-01-24 16:33:56 UTC


README

build:started

DraftjsBundle

此 Symfony 扩展旨在将 Draft.js 状态转换为等效的 PHP 对象模型,并提供必要的工具以渲染 HTML。

安装

此库可以通过 composer 轻松安装

composer require m6web/draftjs-bundle

然后注册此包

# app/AppKernel.php

public function registerBundles()
{
    $bundles = array(
        new M6Web\Bundle\DraftjsBundle\M6WebDraftjsBundle(),
    );
}

YAML 配置参考

此配置允许您自定义块、内联样式和文本对齐的类名。

m6_web_draftjs:
    class_names:
        blocks: # overriding class name of block
            atomic: 'custom-atomic'
            default: 'custom-paragraph'
            list: 'custom-list'
            heading: 'custom-heading'
        inline: # define inline styles class name
            <string>: <string>
        text_alignment: # define text alignment class name
            left: 'text-left'
            center: 'text-center'
            right: 'text-right'

内联键允许您对内联样式文本的类名进行任何字符串的定制,例如,如果您想定义加粗样式的类名,只需定义以下配置

m6_web_draftjs:
    class_names:
        inline:
            bold: 'u-bold'

对象模型

DraftjsBundle 遵循 Draft.js 对象模型。

ContentState : Represent the document
ContentBlock : Represent a single block
DraftEntity : Represent a Draft.js entity
CharacterMetadata : Represent a character with style and entity

Draft.js 支持

DraftjsBundle 支持以下 Draft.js 块类型,具体如下

- atomic
- unstyled
- paragraph
- unordered-list-item
- ordered-list-item
- header-one
- header-two
- header-three
- header-four
- header-five
- header-six
- blockquote

您可以通过实现自定义渲染器来扩展此列表,如渲染器部分所示

异常

  • DraftjsException

ContentStateConverter

将 Draft.js 状态转换为 PHP 模型对象。

m6_web_draftjs.content_state_converter

HtmlBuilder

从 ContentState 对象构建 HTML。

m6_web_draftjs.html_builder

HtmlRenderer

用于将 Draft.js 状态转换为 HTML 的对象。

m6_web_draftjs.html_renderer

渲染器

除了全局 HtmlRenderer 之外,我们还提供了通过添加新渲染器来扩展渲染引擎的可能性。

根据您想要定制的类型,我们区分了三种类型的渲染器:

还有另一种未在此列出的渲染器,即 ContentRenderer,它负责从文本和内联样式渲染块内的 HTML。

您需要做的就是创建一个服务,然后将其标记为预期。

添加自定义块渲染器

首先定义您的服务

# block entity renderers
acme_demo.acme_block_renderer:
    class: Acme\Bundle\DemoBundle\Renderer\Block\AcmeBlockRenderer
    parent: m6_web_draft_js.abstract_block_renderer
    calls:
        - [setBlockClassName, ['block-acme']]
    tags:
        - { name: draftjs.block_renderer, alias: draftjs_acme_block_renderer }

为了完全支持我们的渲染引擎,您必须将您的服务标记为 draftjs.block_renderer,并且您必须扩展实现 BlockRendererInterface 接口的 AbstractBlockRenderer。

以 AcmeBlockRenderer 类为例

namespace Acme\Bundle\DemoBundle\Renderer\Block;

use M6Web\Bundle\DraftjsBundle\Renderer\Block\AbstractBlockRenderer;
use M6Web\Bundle\DraftjsBundle\Model\ContentBlock;

class AcmeBlockRenderer extends AbstractBlockRenderer
{
    /**
     * @param \ArrayIterator $iterator
     * @param array          $entities
     *
     * @return string
     */
    public function render(\ArrayIterator &$iterator, array $entities)
    {
        // you have acces to the global iterator of ContentBlock
        // so just get current item by use curent()
        $contentBlock = $iterator->current();

        // if your renderer is handling the current ContentBlock
        // you must inform the iterator to move to the next entry for next iteration
        $iterator->next();

        // By extending the AbstractBlockRenderer, you can use the ContentRenderer who allow to render inline html
        $content = $this->contentRenderer->render(
            $contentBlock->getText(),
            $contentBlock->getCharacterList(),
            $entities
        );

        if (!$this->template) {
            return $content;
        }

        // You also have access to the templating engine
        return $this->templating->render($this->template, [
            'classNames' => $this->buildClassNames($contentBlock),
            'content' => $content,
        ]);
    }

    /**
     * @param string $type
     *
     * @return bool
     */
    public function supports($type)
    {
        return 'acme' === $type;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'acme';
    }
}

添加自定义内联实体渲染器

内联渲染器用于在具有字符串的块内容中显示实体信息。

function createLink() {
    return DraftEntity.__create('LINK', 'MUTABLE', {uri: 'zombo.com'});
}

首先定义您的服务

acme_demo.link_inline_entity_renderer:
    class: Acme\Bundle\DemoBundle\Renderer\Inline\LinkInlineEntityRenderer
    calls:
        - [setClassName, ['u-link']]
    tags:
        - { name: draftjs.inline_entity_renderer, alias: draftjs_link_inline_entity_renderer }

为了完全支持我们的渲染引擎,您必须使用 draftjs.inline_entity_renderer 标签您的服务,并且必须扩展实现 InlineEntityRendererInterface 接口的 AbstractInlineEntityRenderer。

以 LinkInlineEntityRenderer 类为例

namespace Acme\Bundle\DemoBundle\Renderer\Inline;

use M6Web\Bundle\DraftjsBundle\Renderer\Inline\AbstractInlineEntityRenderer;
use M6Web\Bundle\DraftjsBundle\Renderer\Helper\InlineRendererHelperTrait;
use M6Web\Bundle\DraftjsBundle\Model\DraftEntity;

class LinkInlineEntityRenderer extends AbstractInlineEntityRenderer
{
    const TAG_NAME = 'a';

    use InlineRendererHelperTrait;

    /**
     * @param DraftEntity $entity
     *
     * @return string
     */
    public function openTag(DraftEntity $entity)
    {
        $data = $entity->getData();

        $attributes = [];

        if (isset($data['url'])) {
            $attributes['href'] = $data['url'];
        }

        if (isset($data['target']) && '_self' !== $data['target']) {
            $attributes['target'] = $data['target'];
        }

        if (isset($data['nofollow']) && true === $data['nofollow']) {
            $attributes['rel'] = 'nofollow';
        }

        if ($this->className) {
            $attributes['class'] = $this->className;
        }

        return $this->openNode(self::TAG_NAME, $attributes);
    }

    /**
     * @return string
     */
    public function closeTag()
    {
        return $this->closeNode(self::TAG_NAME);
    }

    /**
     * @param string $type
     *
     * @return bool
     */
    public function supports($type)
    {
        return 'link' === $type;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'link';
    }
}

注意使用了 InlineRendererHelperTrait

添加自定义块实体渲染器

实体块渲染器用于以块的形式显示实体信息。

首先定义您的服务

acme_demo.acme_block_entity_renderer:
    class: Acme\Bundle\DemoBundle\Renderer\Entity\AcmeBlockEntityRenderer
    parent: m6_web_draft_js.abstract_block_entity_renderer
    calls:
        - [setClassName, ['block-entity-acme']]
    tags:
        - { name: draftjs.block_entity_renderer, alias: draftjs_acme_block_entity_renderer }

为了完全支持我们的渲染引擎,您必须使用 draftjs.block_entity_renderer 标签您的服务,并且必须扩展实现 BlockEntityRendererInterface 接口的 AbstractBlockEntityRenderer。

以 LinkInlineEntityRenderer 类为例

namespace Acme\Bundle\DemoBundle\Renderer\Entity;

use M6Web\Bundle\DraftjsBundle\Renderer\Entity\AbstractBlockEntityRenderer;
use M6Web\Bundle\DraftjsBundle\Model\DraftEntity;

class AcmeBlockEntityRenderer extends AbstractBlockEntityRenderer
{
    /**
     * @param DraftEntity $entity
     *
     * @return string
     */
    public function render(DraftEntity $entity)
    {
        // generate content from the entity data
        $content = 'content of your acme block';

        return $this->templating->render($this->getTemplate(), [
            'className' => $this->getClassName(),
            'content' => $content,
        ]);
    }

    /**
     * @param string $type
     *
     * @return bool
     */
    public function supports($type)
    {
        return 'acme' === $type;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'acme';
    }
}

辅助工具

内联渲染器辅助工具

trait InlineRendererHelperTrait
{
    /**
     * @param $tagName
     * @param array $attributes
     *
     * @return string
     */
    protected function openNode($tagName, array $attributes = [])
    {
        $strAttributes = $this->buildAttributes($attributes);

        return sprintf('<%s%s>', $tagName, $strAttributes);
    }

    /**
     * @param $tagName
     *
     * @return string
     */
    protected function closeNode($tagName)
    {
        return sprintf('</%s>', $tagName);
    }

    /**
     * Convert an array of attributes in string like http_build_query
     *
     * @param array $attributes
     *
     * @return string
     */
    protected function buildAttributes(array $attributes = [])
    {
        $strAttributes = array_map(function ($key) use ($attributes) {
            return sprintf('%s="%s"', $key, $attributes[$key]);
        }, array_keys(array_filter($attributes)));

        if (!$strAttributes) {
            return '';
        }

        return sprintf(' %s', implode(' ', $strAttributes));
    }
}

块渲染器辅助工具

trait BlockRendererHelperTrait
{
    /**
     * Get text alignment from content block data
     *
     * @param ContentBlock $contentBlock
     *
     * @return null
     */
    protected function getTextAlignment(ContentBlock $contentBlock)
    {
        $data = $contentBlock->getData();

        if (isset($data['textAlignment'])) {
            return $data['textAlignment'];
        }

        return null;
    }

    /**
     * Build string class names from block and text alignment class names
     *
     * @param ContentBlock $contentBlock
     *
     * @return string
     */
    protected function buildClassNames(ContentBlock $contentBlock)
    {
        $textAlignment = $this->getTextAlignment($contentBlock);

        $classNames = [
            $this->getBlockClassName(),
        ];

        if ($textAlignment) {
            $classNames[] = $this->getTextAlignmentClassName($textAlignment);
        }

        return implode(' ', $classNames);
    }
}