bumpcore/editor.php

Editor.js的PHP集成

v1.1.0 2024-06-07 21:01 UTC

README

Editor.php

Editor.php是一个旨在轻松解析和操作Editor.js输出的包。它可以与纯PHP或Laravel一起使用。Laravel提供了一些额外的功能。

目录

版本表

快速入门

通过以下方式安装包

composer require bumpcore/editor.php

Editor.php启动非常简单;

use BumpCore\EditorPhp\EditorPhp;

// Passing Editor.js's output directly to the `make`.
// This will render blocks into html.
echo EditorPhp::make($json)->render();

Editor.php支持以下块:

它们都有默认的验证规则和视图以进行渲染。然而,自定义验证和视图是强烈推荐的。

EditorPhp

EditorPhp类是管理块的主要类。您可以通过此类访问、渲染、转换为数组以及转换为JSON。

创建实例

创建EditorPhp新实例有两种方法

use BumpCore\EditorPhp\EditorPhp;

// Using the `new` syntax.
$editor = new EditorPhp($json);

// Using the `make` syntax.
$editor = EditorPhp::make($json);

两种语法相同,它们之间几乎没有什么区别。

访问块

您可以通过blocks属性访问块。

use BumpCore\EditorPhp\EditorPhp;
use BumpCore\EditorPhp\Block\Block;
use BumpCore\EditorPhp\Blocks\Paragraph;

$editor = EditorPhp::make($json);

// Stripping all tags from paragraph block's text.
$editor->blocks->transform(function(Block $block)
{
    if($block instanceof Paragraph)
    {
        $block->set('text', strip_tags($block->get('text')));
    }

    return $block;
});

块存储为Illuminate\Support\Collection。通过使用集合方法,您可以按需操作块。您可以在Laravel的文档中了解有关集合的更多信息。

渲染HTML

渲染HTML非常直接。有多种方式可以渲染您的实例

use BumpCore\EditorPhp\EditorPhp;

$editor = EditorPhp::make($json);

// Using the `render` function.
echo $editor->render();

// Using the `toHtml` function.
echo $editor->toHtml();

// Or by casting to a string.
echo $editor;

同样,这三种情况都是相同的,没有上下之分。您可以使用您最喜欢的一种。

默认情况下,您有两个用于默认块模板的选项;tailwindcssBootstrap 5。默认使用的模板是tailwindcss。您可以通过以下方式切换模板:

use BumpCore\EditorPhp\EditorPhp;

// Using tailwind.
EditorPhp::useTailwind();

// Using Bootstrap.
EditorPhp::useBootstrapFive();

您可以在创建自定义块部分中了解更多有关渲染的信息。

模拟

您可以使用EditorPhp生成假数据。

use BumpCore\EditorPhp\EditorPhp; 

// This will return a generated fake JSON.
$fake = EditorPhp::fake(); 

// If we pass first argument true, it will return new `EditorPhp` instance with fake data.
$fakeEditor = EditorPhp::fake(true); 

// You can also pass min lenght and max lenght of blocks.
// Below code will generate blocks between 1 and 3.
$fakeEditor = EditorPhp::fake(true, 1, 3);

echo $fakeEditor->render();

您可以在生成假数据部分中了解更多有关为块生成假数据的信息。

附加

转换为数组

您可以使用toArray()方法将实例转换为数组。

use BumpCore\EditorPhp\EditorPhp;

$editor = EditorPhp::make($json);

// This will return ['time' => ..., 'blocks' => [...], 'version' => '...']
$array = $editor->toArray();

转换为JSON

您可以使用toJson(/** 选项 */)方法将实例转换为JSON。此方法在操作实例时非常有用。

use BumpCore\EditorPhp\EditorPhp;

$editor = EditorPhp::make($json);

// This will return encoded JSON.
$json = $editor->toJson(JSON_PRETTY_PRINT);

时间 & 版本

您可以访问时间和版本

use BumpCore\EditorPhp\EditorPhp;

$editor = EditorPhp::make($json);

$editor->time;
$editor->version;

time属性是Carbon实例。您可以在Carbon的文档中了解更多信息。

您可以注册宏并在以后使用它们。宏基于Laravel。

use BumpCore\EditorPhp\EditorPhp;

// Registering new macro.
EditorPhp::macro(
    'getParagraphs',
    fn () => $this->blocks->filter(fn (Block $block) => $block instanceof Paragraph)
);

$editor = EditorPhp::make($json);

// This will return a collection that only contains paragraphs.
$paragraphs = $editor->getParagraphs();

块是 EditorPhp 编辑器的主要构建部分。您可以随心所欲地操作它们,最好的部分是您可以使用它们来存储块逻辑。例如,图片 块需要一个上传器才能工作。您可以在 BumpCore\EditorPhp\Blocks\Image 类中实现相应的功能。

注册块

在我们学习如何自定义块之前,这里是如何注册您的块的方法。

use BumpCore\EditorPhp\EditorPhp;

// This will merge without erasing already registered blocks. Other blocks will still remain with the recently registered `image` and `paragraph` blocks.
EditorPhp::register([
    'image' => \Blocks\MyCustomImageBlock::class,
    'paragraph' => \Blocks\MyCustomParagraphBlock::class,
]);

// This will override already registered blocks. We now only have `image` and `paragraph` blocks.
EditorPhp::register([
    'image' => \Blocks\MyCustomImageBlock::class,
    'paragraph' => \Blocks\MyCustomParagraphBlock::class,
], true);

在注册块时,使用正确的键非常重要。键必须与 Editor.jstype 键相同。为了澄清:

{
    "time": 1672852569662,
    "blocks": [
        {
            "type": "paragraph",
            "data": {
                "text": "..."
            }
        }
    ],
    "version": "2.26.4"
}

在这个输出中,我们的类型键是 paragraph,因此我们应该将其注册为 'paragraph' => Paragraph::class。这可能会根据您在 Editor.js 中注册块的方式而有所不同。EditorPhp 的默认块使用 camelCase 进行注册。

扩展块

如前所述,EditorPhp 几乎支持所有块。然而,它们主要处理块数据的验证和渲染。为了使 Image 块正常工作,它需要一个上传。我们可以在 Image 类中实现这个上传逻辑。

use BumpCore\EditorPhp\Blocks\Image;

class MyImageBlock extends Image
{
    public static function uploadTemp(string $fileName = 'image'): array
    {
        // ...

        // Temporary upload logic.

        return [
            'success' => ...,
            'file' => [
                'url' => ...,
            ],
        ];
    }

    public function upload(): void
    {
        $file = $this->get('file.url');

        // Your logic.

        // ...
        
        // Altering the current block's data.
        $this->set('file.url', ...);
    }
}

// ...

// Registering customized block.
EditorPhp::register([
    'image' => MyImageBlock::class
]);

如您所见,我们已经扩展了 Image 块并添加了两个处理上传的函数。

uploadTemp 函数执行临时文件上传。这是一个静态方法,可以通过 Image::uploadTemp() 在任何地方使用。它返回由 图片 工具所需的数据。

upload 函数有不同的用途。它代表块的最终上传,但不是静态的。此方法假定图像已经临时上传,并且 $json 已加载并解析。因此,我们可以像这样使用此函数:

use BumpCore\EditorPhp\EditorPhp;
use Blocks\MyImageBlock;

$editor = EditorPhp::make($json);

$editor->blocks->each(function(Block $block)
{
    if ($block instanceof MyImageBlock)
    {
        $block->upload();
    }
});

return $editor->toJson();

现在,块执行最终上传,并作为 JSON 保存。

创建自定义块

无法支持所有块,因此我们可以轻松实现自己的块。一个标准的块看起来如下:

use BumpCore\EditorPhp\Block\Block;

class MyCustomBlock extends Block
{
    public function render(): string
    {
        return view('blocks.my-custom-block', ['data' => $this->data]);
    }
}

如您所见,默认情况下,我们只需要实现渲染逻辑。然而,不仅仅是渲染。

访问块的数据

有多种方法可以访问块的数据。在下面的示例中,您可以看到访问块数据的不同方法。

public function render(): string
{
    // ...

    // Method 1: Accessing through the data object.
    $data = $this->data;
    $data->get('custom.data');
    $data->set('custom.data', 'Hello World!');

    // Method 2: Accessing by invoking the data object.
    $data('custom.data'); // Hello World!

    // Method 3: Using shortcuts.
    $this->get('custom.data');
    $this->set('custom.data', 'Nice!');

    // ...
}

您可以选择上述任何方法来访问和操作块的数据。此外,您还可以使用以下方法检查数据是否存在或不存在:

$data->has('custom.data');
// or
$this->has('custom.data');

验证块数据

验证数据不是必需的,但它可以使您的数据更安全。验证块数据非常简单。我们只需要在我们的块中添加一个 rules 方法。

use BumpCore\EditorPhp\Block\Block;

class MyCustomBlock extends Block
{
    // ...

    public function rules(): array
    {
        return [
            'text' => 'required|string|max:255',
            'items' => 'sometimes|array',
            'items.*.name' => 'required|string|max:255',
            'items.*.html' => 'required|string|min:255',
        ];
    }

    // ...
}

当验证块数据失败时,数据将为空。数据验证使用 Laravel 的验证库执行。您可以在 Laravel 文档 中了解更多信息。

清理块数据

如果您愿意,可以净化您数据中的 HTML。防止注入非常重要。净化数据看起来与验证类似。

use BumpCore\EditorPhp\Block\Block;

class MyCustomBlock extends Block
{
    // ...

    public function allow(): array|string
    {
        // Specifying one by one.
        return [
            'text' => [
                'a:href,target,title', // Will allow `a` tag and href, target, and title attributes.
                'b', // Will only allow `b` tag with no attributes.
            ],
            'items.*.name' => 'b:*', // Will allow `b` tag with all attributes.
            'items.*.html' => '*', // Will allow every tag and every attribute.
        ];

        // Or just allowing all attributes and tags for all data.
        return '*';
    }

    // ...
}

与验证不同,净化将仅删除不需要的标签和属性。

生成假数据

如我们之前提到的,我们可以使用 EditorPhp 生成假数据。但这需要为每个块生成自己的假数据。要生成假数据,我们应该向我们的块添加静态方法。

use BumpCore\EditorPhp\Block\Block;

class MyCustomBlock extends Block
{
    // ...

    public static function fake(\Faker\Generator $faker): array
    {
        $items = [];

        foreach (range(0, $faker->numberBetween(0, 10)) as $index)
        {
            $items[] = [
                'name' => fake()->name(),
                'html' => $faker->randomHtml(),
            ];
        }

        return [
            'text' => fake()->text(255),
            'items' => $items,
        ];
    }

    // ...
}

通过向我们的块添加 fake 方法,现在 EditorPhp 生成假数据时也会包括 MyCustomBlock。您可以在 FakerPHP 文档 中了解更多信息。

Laravel特有功能

有几个 Laravel 功能可以使您的生活更加轻松。

类型转换

您可以使用 EditorPhpCast 将您模型的属性转换为 EditorPhp 实例。

use BumpCore\EditorPhp\Casts\EditorPhpCast;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $casts = [
        'content' => EditorPhpCast::class,
    ];
}

// ...

$post = Post::find(1);

// Content is `EditorPhp` instance in here.
echo $post->content->render();

此外,如果您使用 cast,您也可以在块实例中访问您的模型。

use BumpCore\EditorPhp\Block\Block;
use App\Models\Post;

class MyBlock extends Block
{
    // ...

    public static function render(): string
    {
        if($this->root->model instanceof Post)
        {
            // Do the other thing.
        }
    }

    // ...
}

您还可以从块中修改模型。

响应

EditorPhp 实例可以作为响应返回。如果请求期望 JSON,它将自动编码为 JSON。否则,它将被渲染为 HTML。

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Post;

class ShowPostController extends Controller
{
    public function __invoke(Post $post)
    {
        // Depending on the request it will return json or rendered html.
        return $post->content;
    }
}

视图

您还可以使用 EditorPhp 实例直接在视图中渲染。

{{-- blog.show.blade.php --}}

<article>
    <h1>{{ $post->title }}</h1>
    <div>{{ $post->content }}</div>
</article>

发布视图和配置

在编写文档之前需要检查这一点。

命令

您可以使用 block:make <name> 命令创建全新的块。

php artisan make:block CustomImageBlock

新块将被放置在 app/Blocks 目录下。

贡献

欢迎贡献力量!如果您发现了一个错误或对改进有建议,请打开一个问题或创建一个 pull 请求。以下是一些遵循的指南:

  • 将仓库 Fork 并克隆到您的本地计算机。
  • 为您的贡献创建一个新的分支。
  • 进行更改并彻底测试它们。
  • 确保您的代码遵循现有的编码风格和约定。
  • 提交您的更改并将它们推送到您 Fork 的仓库。
  • 向主仓库提交一个 pull 请求。

请提供您更改的详细描述和它们解决的问题。您的贡献将被审查,并可能提供反馈。感谢您为使此项目更好而提供的帮助!