ueberdosis/tiptap-php

一个用于处理 Tiptap 输出的 PHP 包

1.4.0 2024-08-12 08:25 UTC

This package is auto-updated.

Last update: 2024-09-12 08:44:29 UTC


README

Latest Version on Packagist GitHub Tests Action Status Total Downloads License Chat Sponsor

一个用于处理 Tiptap 内容的 PHP 包。您可以转换 Tiptap 兼容的 JSON 到 HTML,反之亦然,清理您的内容,或者只是修改它。

安装

您可以通过 composer 安装此包

composer require ueberdosis/tiptap-php

使用方法

该 PHP 包模仿了 JavaScript 包的大部分功能。如果您熟悉 Tiptap,PHP 语法将非常熟悉。

将 Tiptap HTML 转换为 JSON

让我们从一个 HTML 片段开始,将其转换为具有 Tiptap 兼容结构的 PHP 数组

(new \Tiptap\Editor)
    ->setContent('<p>Example Text</p>')
    ->getDocument();

// Returns:
// ['type' => 'doc', 'content' => …]

您也可以在 PHP 中获取 JSON 字符串。

(new \Tiptap\Editor)
    ->setContent('<p>Example Text</p>')
    ->getJSON();

// Returns:
// {"type": "doc", "content": …}

将 Tiptap JSON 转换为 HTML

反之亦然。只需传递一个 JSON 字符串或 PHP 数组以生成 HTML。

(new \Tiptap\Editor)
    ->setContent([
        'type' => 'doc',
        'content' => [
            [
                'type' => 'paragraph',
                'content' => [
                    [
                        'type' => 'text',
                        'text' => 'Example Text',
                    ],
                ]
            ]
        ],
    ])
    ->getHTML();

// Returns:
// <h1>Example Text</h1>

这并不完全符合 ProseMirror 架构。一些功能也得到支持,例如在 CodeBlock 中不允许标记。

如果您需要更好的架构支持,请创建一个包含您缺失功能的 issue。

使用 highlight.php 为代码块提供语法高亮(需要 Node.js)

默认的 CodeBlock 扩展不会为您的代码块添加语法高亮。但是,如果您想为代码块添加语法高亮,有一个特殊的 CodeBlockHighlight 扩展。

替换默认的一个是这样工作的

(new \Tiptap\Editor([
    'extensions' => [
        new \Tiptap\Extensions\StarterKit([
            'codeBlock' => false,
        ]),
        new \Tiptap\Nodes\CodeBlockHighlight(),
    ],
]))
->setContent('<pre><code>&lt;?php phpinfo()</code></pre>')
->getHTML();

// Returns:
// <pre><code class="hljs php"><span class="hljs-meta">&lt;?php</span> phpinfo()</code></pre>

这仍然是未样式的。您需要 加载一个 CSS 文件 以添加颜色到输出,例如这样

<link rel="stylesheet" href="//unpkg.com/@highlightjs/[email protected]/styles/default.min.css">

Boom,语法高亮!顺便说一句,这是由惊人的 scrivo/highlight.php 驱动的。

使用 Shiki 为代码块提供语法高亮(需要 Node.js)

还有一个使用 Shiki 的替代语法高亮器。Shiki 是一个美丽的语法高亮器,由许多代码编辑器使用的相同语言引擎提供支持。与 CodeBlockHighlight 扩展的主要区别是,1) 您必须安装 shiki npm 包,2) Shiki 代码高亮通过注入内联样式来实现,因此不需要引入外部 CSS 文件,3) 您可以使用大多数 VS Code 主题来突出显示您的代码。

要使用 Shiki 扩展,首先安装 npm 包

npm install shiki

然后按照下面的示例进行操作

(new \Tiptap\Editor([
    'extensions' => [
        new \Tiptap\Extensions\StarterKit([
            'codeBlock' => false,
        ]),
        new \Tiptap\Nodes\CodeBlockShiki,
    ],
]))
->setContent('<pre><code>&lt;?php phpinfo()</code></pre>')
->getHTML();

要配置主题或代码块的默认语言,请将附加配置传递给构造函数,如下所示

(new \Tiptap\Editor([
    'extensions' => [
        new \Tiptap\Extensions\StarterKit([
            'codeBlock' => false,
        ]),
        new \Tiptap\Nodes\CodeBlockShiki([
            'theme' => 'github-dark', // default: nord, see https://github.com/shikijs/shiki/blob/main/docs/themes.md
            'defaultLanguage' => 'php' // default: html, see https://github.com/shikijs/shiki/blob/main/docs/languages.md
            'guessLanguage' => true // default: true, if the language isn’t passed, it tries to guess the language with highlight.php
        ]),
    ],
]))
->setContent('<pre><code>&lt;?php phpinfo()</code></pre>')
->getHTML();

在内部,Shiki 扩展使用 Spatie 的 Shiki PHP,因此请参阅文档以获取更多详细信息和注意事项。

将内容转换为纯文本

内容也可以转换为纯文本,例如将其放入搜索索引中。

(new \Tiptap\Editor)
    ->setContent('<h1>Heading</h1><p>Paragraph</p>')
    ->getText();

// Returns:
// "Heading
//
// Paragraph"

在块之间可以配置什么。

(new \Tiptap\Editor)
    ->setContent('<h1>Heading</h1><p>Paragraph</p>')
    ->getText([
        'blockSeparator' => "\n",
    ]);

// Returns:
// "Heading
// Paragraph"

清理内容

PHP 包的一个很好的用途是清理(或“清理”)内容。您可以使用 sanitize() 方法完成此操作。它支持 JSON 字符串、PHP 数组和 HTML。

它将返回与输入格式相同的格式。

(new \Tiptap\Editor)
    ->sanitize('<p>Example Text<script>alert("HACKED!")</script></p>');

// Returns:
// '<p>Example Text</p>'

修改内容

使用descendants()方法,您可以递归地遍历所有节点,就像您从JavaScript包中习惯的那样。但在PHP中,您甚至可以修改节点以更新属性等。

警告:您需要将&添加到参数中。这会保持对原始项目的引用,并允许您修改原始项目,而不是仅仅修改一个副本。

$editor->descendants(function (&$node) {
    if ($node->type !== 'heading') {
        return;
    }

    $node->attrs->level = 1;
});

配置

将配置传递给编辑器的构造函数。可配置的内容不多,但至少您可以传递初始内容和加载特定扩展。

new \Tiptap\Editor([
    'content' => '<p>Example Text</p>',
    'extensions' => [
        new \Tiptap\Extensions\StarterKit,
    ],
])

默认情况下将加载StarterKit。如果您只想使用它,则无需设置。

扩展

默认情况下将加载StarterKit,但您也可以传递一个自定义的扩展数组。

new \Tiptap\Editor([
    'extensions' => [
        new \Tiptap\Extensions\StarterKit,
        new \Tiptap\Marks\Link,
    ],
])

配置扩展

某些扩展可以进行配置。只需将一个数组传递给构造函数即可。我们旨在支持与JavaScript包相同的配置。

new \Tiptap\Editor([
    'extensions' => [
        // …
        new \Tiptap\Nodes\Heading([
            'levels' => [1, 2, 3],
        ]),
    ],
])

您也可以通过配置传递自定义HTML属性。

new \Tiptap\Editor([
    'extensions' => [
        // …
        new \Tiptap\Nodes\Heading([
            'HTMLAttributes' => [
                'class' => 'my-custom-class',
            ],
        ]),
    ],
])

对于StarterKit,虽然略有不同,但工作方式与您从JavaScript包中习惯的那样相同。

new \Tiptap\Editor([
    'extensions' => [
        new Tiptap\Extensions\StarterKit([
            'codeBlock' => false,
            'heading' => [
                'HTMLAttributes' => [
                    'class' => 'my-custom-class',
                ],
            ]
        ]),
    ],
])

扩展现有扩展

如果您需要更改支持扩展的细微细节,则可以简单地扩展一个扩展。

<?php

class CustomBold extends \Tiptap\Marks\Bold
{
    public function renderHTML($mark)
    {
        // Renders <b> instead of <strong>
        return ['b', 0]
    }
}

new \Tiptap\Editor([
    'extensions' => [
        new Paragraph,
        new Text,
        new CustomBold,
    ],
])

自定义扩展

您甚至可以构建自定义扩展。如果您习惯了JavaScript API,您会惊讶地发现PHP中也有很多这样的功能。🤯以下是一个简单的示例。

请务必查阅此存储库中的扩展,以了解有关PHP扩展API的更多信息。

<?php

use Tiptap\Core\Node;

class CustomNode extends Node
{
    public static $name = 'customNode';
    
    public static $priority = 100;

    public function addOptions()
    {
        return [
            'HTMLAttributes' => [],
        ];
    }

    public function parseHTML()
    {
        return [
            [
                'tag' => 'my-custom-tag[data-id]',
            ],
            [
                'tag' => 'my-custom-tag',
                'getAttrs' => function ($DOMNode) {
                    return ! \Tiptap\Utils\InlineStyle::hasAttribute($DOMNode, [
                        'background-color' => '#000000',
                    ]) ? null : false;
                },
            ],
            [
                'style' => 'background-color',
                'getAttrs' => function ($value) {
                    return (bool) preg_match('/^(black)$/', $value) ? null : false;
                },
            ],
        ];
    }

    public function renderHTML($node)
    {
        return ['my-custom-tag', ['class' => 'foobar'], 0]
    }
}

扩展优先级

扩展将按降序优先级进行评估。默认情况下,所有节点、标记和扩展都具有100的优先级值。

当创建节点扩展以匹配可能被其他节点匹配的标记时,应定义优先级。例如,TaskItem节点具有比ListItem节点更高的评估优先级。

测试

composer test

您可以使用nodemon(npm install -g nodemon)安装测试套件,并监视文件更改以保持其运行。

composer test-watch

贡献

有关详细信息,请参阅CONTRIBUTING

安全漏洞

请参阅我们的安全策略,了解如何报告安全漏洞。

致谢

许可

MIT许可(MIT)。有关更多信息,请参阅许可文件