{"id":13770827,"url":"https://github.com/bumpcore/editor.php","last_synced_at":"2026-03-17T20:06:43.370Z","repository":{"id":64878567,"uuid":"579156015","full_name":"bumpcore/editor.php","owner":"bumpcore","description":"Editor.php is a package designed to assist in parsing and manipulating the output of Editor.js with ease.","archived":false,"fork":false,"pushed_at":"2025-03-15T09:13:25.000Z","size":550,"stargazers_count":34,"open_issues_count":11,"forks_count":7,"subscribers_count":2,"default_branch":"1.x","last_synced_at":"2025-04-16T19:22:28.298Z","etag":null,"topics":["editor","editorjs","editorjs-parser","laravel","laravel-package","php","php-library"],"latest_commit_sha":null,"homepage":"https://bumpcore.com/docs/editorphp","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bumpcore.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-16T20:03:37.000Z","updated_at":"2025-03-15T09:12:13.000Z","dependencies_parsed_at":"2023-09-29T00:43:52.139Z","dependency_job_id":"9986992f-5e2d-451b-96a1-070ab34b4112","html_url":"https://github.com/bumpcore/editor.php","commit_stats":{"total_commits":64,"total_committers":3,"mean_commits":"21.333333333333332","dds":0.125,"last_synced_commit":"00ea45540ee1648f15958b87856f26332a578369"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Feditor.php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Feditor.php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Feditor.php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Feditor.php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bumpcore","download_url":"https://codeload.github.com/bumpcore/editor.php/tar.gz/refs/heads/1.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253514352,"owners_count":21920327,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["editor","editorjs","editorjs-parser","laravel","laravel-package","php","php-library"],"created_at":"2024-08-03T17:00:42.586Z","updated_at":"2025-12-12T23:03:15.485Z","avatar_url":"https://github.com/bumpcore.png","language":"PHP","funding_links":[],"categories":["Libraries"],"sub_categories":["PHP"],"readme":"# Editor.php\n\nEditor.php is a package designed to assist in parsing and manipulating the output of [Editor.js](https://editorjs.io/) with ease. It can be used with either vanilla PHP or with Larave. Laravel offers few additional features.\n\n## Table Of Contents\n\n* [Version Table](#version-table)\n* [Quick Start](#quick-start)\n* [EditorPhp](#editorphp)\n  + [Creating Instance](#creating-instance)\n  + [Accessing Blocks](#accessing-blocks)\n  + [Rendering HTML](#rendering-html)\n  + [Faking](#faking)\n  + [Additional](#additional)\n    + [Converting to an array](#converting-to-an-array)\n    + [Converting to JSON](#converting-to-json)\n    + [Time \u0026 Version](#time--version)\n    + [Macros](#macros)\n* [Blocks](#blocks)\n  + [Registering Blocks](#registering-blocks)\n  + [Extending Blocks](#extending-blocks)\n  + [Creating Custom Blocks](#creating-custom-blocks)\n  + [Accessing Block's Data](#accessing-blocks-data)\n  + [Validating Block Data](#validating-block-data)\n  + [Sanitizing Block Data](#sanitizing-block-data)\n  + [Fake Data Generation](#fake-data-generation)\n* [Laravel Only Features](#laravel-only-features)\n  + [Cast](#cast)\n  + [Response](#response)\n  + [Views](#views)\n  + [Publishing Views and Configuration](#publishing-views-and-configuration)\n  + [Commands](#commands)\n* [Contribution](#contribution)\n\n# Version Table\n| Editor.php | Laravel | PHP |\n| --- | --- | --- |\n| 1.x | 10.x | 8.1 ~ 8.3 |\n| 1.x | 11.x | 8.2 ~ 8.4 |\n| 1.x | 12.x | 8.2 ~ 8.4 |\n\n# Quick Start\n\nInstall package by:\n\n```bash\ncomposer require bumpcore/editor.php\n```\n\nEditor.php is really simple to get started; \n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n// Passing Editor.js's output directly to the `make`.\n// This will render blocks into html.\necho EditorPhp::make($json)-\u003erender();\n```\n\nEditor.php supports following blocks; \n\n* [Attaches](https://github.com/editor-js/attaches)\n* [Checklist](https://github.com/editor-js/checklist)\n* [Code](https://github.com/editor-js/code)\n* [Delimiter](https://github.com/editor-js/delimiter)\n* [Embed](https://github.com/editor-js/embed)\n* [Header](https://github.com/editor-js/header)\n* [Image](https://github.com/editor-js/image)\n* [Link Tool](https://github.com/editor-js/link)\n* [List](https://github.com/editor-js/list)\n* [Paragraph](https://github.com/editor-js/paragraph)\n* [Personality](https://github.com/editor-js/personality)\n* [Quote](https://github.com/editor-js/quote)\n* [Table](https://github.com/editor-js/table)\n* [Warning](https://github.com/editor-js/warning)\n\nAll of them have default validation rules and views to render. However, customizing validation and views is highly recommended.\n\n# EditorPhp\n\nThe `EditorPhp` class is the main class for managing blocks. You can access, render, convert to an array, and convert to JSON through this class.\n\n## Creating Instance\n\nThere are two ways to create a new instance of EditorPhp:\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n// Using the `new` syntax.\n$editor = new EditorPhp($json);\n\n// Using the `make` syntax.\n$editor = EditorPhp::make($json);\n```\n\nBoth syntaxes are equal, and there's almost no difference between them.\n\n## Accessing Blocks\n\nYou can access blocks through the blocks property.\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\nuse BumpCore\\EditorPhp\\Block\\Block;\nuse BumpCore\\EditorPhp\\Blocks\\Paragraph;\n\n$editor = EditorPhp::make($json);\n\n// Stripping all tags from paragraph block's text.\n$editor-\u003eblocks-\u003etransform(function(Block $block)\n{\n    if($block instanceof Paragraph)\n    {\n        $block-\u003eset('text', strip_tags($block-\u003eget('text')));\n    }\n\n    return $block;\n});\n```\n\nBlocks are stored as `Illuminate\\Support\\Collection` . By using collection methods, you can manipulate blocks as you wish. You can learn about collections in [Laravel's documentation](https://laravel.com/docs/10.x/collections).\n\n## Rendering HTML\n\nRendering HTML is very straightforward. There are multiple ways to render your instance:\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n$editor = EditorPhp::make($json);\n\n// Using the `render` function.\necho $editor-\u003erender();\n\n// Using the `toHtml` function.\necho $editor-\u003etoHtml();\n\n// Or by casting to a string.\necho $editor;\n```\n\nAgain, all three cases are the same, with no one above another. You can use whichever one you like the most.\n\nBy the default, you have two options for the default block's templates; `tailwindcss` and `Bootstrap 5` . Default used template is `tailwindcss` You may switch templates by:\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n// Using tailwind.\nEditorPhp::useTailwind();\n\n// Using Bootstrap.\nEditorPhp::useBootstrapFive();\n```\n\nYou can learn more about rendering in [creating custom blocks](#creating-custom-blocks) section.\n\n## Faking\n\nYou can generate fake data with `EditorPhp` .\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp; \n\n// This will return a generated fake JSON.\n$fake = EditorPhp::fake(); \n\n// If we pass first argument true, it will return new `EditorPhp` instance with fake data.\n$fakeEditor = EditorPhp::fake(true); \n\n// You can also pass min lenght and max lenght of blocks.\n// Below code will generate blocks between 1 and 3.\n$fakeEditor = EditorPhp::fake(true, 1, 3);\n\necho $fakeEditor-\u003erender();\n```\n\nYou can learn more about generating fake data for the blocks in [fake data generation](#fake-data-generation).\n\n## Additional\n\n### Converting to an array \n\nYou can convert your instance to an array using the `toArray()` method.\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n$editor = EditorPhp::make($json);\n\n// This will return ['time' =\u003e ..., 'blocks' =\u003e [...], 'version' =\u003e '...']\n$array = $editor-\u003etoArray();\n```\n\n### Converting to JSON\n\nYou can convert your instance to JSON using the `toJson(/** options */)` method. This method is useful when you manipulate your instance.\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n$editor = EditorPhp::make($json);\n\n// This will return encoded JSON.\n$json = $editor-\u003etoJson(JSON_PRETTY_PRINT);\n```\n\n### Time \u0026 Version\n\nYou can access time and version:\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n$editor = EditorPhp::make($json);\n\n$editor-\u003etime;\n$editor-\u003eversion;\n```\n\nThe `time` property is a `Carbon` instance. You can learn more about it in [Carbon's documentation](https://carbon.nesbot.com/docs/).\n\n### Macros\n\nYou can register macros and use them later. Macros are based on Laravel.\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n// Registering new macro.\nEditorPhp::macro(\n    'getParagraphs',\n    fn () =\u003e $this-\u003eblocks-\u003efilter(fn (Block $block) =\u003e $block instanceof Paragraph)\n);\n\n$editor = EditorPhp::make($json);\n\n// This will return a collection that only contains paragraphs.\n$paragraphs = $editor-\u003egetParagraphs();\n```\n\n# Blocks\n\nBlocks are the main building parts of the `EditorPhp` editor. You can manipulate them as you wish, and the best part is that you can use them to store your block's logic. For example, the [image](https://github.com/editor-js/image) block requires an uploader to work. You can implement the corresponding functionality in the `BumpCore\\EditorPhp\\Blocks\\Image` class.\n\n## Registering Blocks\n\nBefore we jump into learning how to customize blocks, here's how you can register your blocks:\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\n\n// This will merge without erasing already registered blocks. Other blocks will still remain with the recently registered `image` and `paragraph` blocks.\nEditorPhp::register([\n    'image' =\u003e \\Blocks\\MyCustomImageBlock::class,\n    'paragraph' =\u003e \\Blocks\\MyCustomParagraphBlock::class,\n]);\n\n// This will override already registered blocks. We now only have `image` and `paragraph` blocks.\nEditorPhp::register([\n    'image' =\u003e \\Blocks\\MyCustomImageBlock::class,\n    'paragraph' =\u003e \\Blocks\\MyCustomParagraphBlock::class,\n], true);\n```\n\nWhen registering blocks, it's important to use the correct key. The key must be the same as the `Editor.js` 's `type` key. To clarify:\n\n```json\n{\n    \"time\": 1672852569662,\n    \"blocks\": [\n        {\n            \"type\": \"paragraph\",\n            \"data\": {\n                \"text\": \"...\"\n            }\n        }\n    ],\n    \"version\": \"2.26.4\"\n}\n```\n\nIn this output, our type key is `paragraph` , so we should register it as `'paragraph' =\u003e Paragraph::class` . This might vary depending on how you register your blocks in `Editor.js` . Default blocks in `EditorPhp` are registered using `camelCase` .\n\n## Extending Blocks\n\nAs mentioned previously, almost all blocks are supported in `EditorPhp` . However, they mostly handle the validation of block data and rendering. For the `Image` block to work properly, it requires an upload. We can implement this upload logic in the `Image` class:\n\n```php\nuse BumpCore\\EditorPhp\\Blocks\\Image;\n\nclass MyImageBlock extends Image\n{\n    public static function uploadTemp(string $fileName = 'image'): array\n    {\n        // ...\n\n        // Temporary upload logic.\n\n        return [\n            'success' =\u003e ...,\n            'file' =\u003e [\n                'url' =\u003e ...,\n            ],\n        ];\n    }\n\n    public function upload(): void\n    {\n        $file = $this-\u003eget('file.url');\n\n        // Your logic.\n\n        // ...\n        \n        // Altering the current block's data.\n        $this-\u003eset('file.url', ...);\n    }\n}\n\n// ...\n\n// Registering customized block.\nEditorPhp::register([\n    'image' =\u003e MyImageBlock::class\n]);\n```\n\nAs you can see, we have extended the `Image` block and added two functions to handle our uploads.\n\nThe `uploadTemp` function performs a temporary file upload. This method is static and can be used anywhere using `Image::uploadTemp()` . It returns the data required by the [image](https://github.com/editor-js/image) tool.\n\nThe `upload` function serves a different purpose. It represents the final upload for the block but is not static. This method assumes that the image has already been uploaded temporarily and the `$json` has been loaded and parsed. Therefore, we can use this function as follows:\n\n```php\nuse BumpCore\\EditorPhp\\EditorPhp;\nuse Blocks\\MyImageBlock;\n\n$editor = EditorPhp::make($json);\n\n$editor-\u003eblocks-\u003eeach(function(Block $block)\n{\n    if ($block instanceof MyImageBlock)\n    {\n        $block-\u003eupload();\n    }\n});\n\nreturn $editor-\u003etoJson();\n```\n\nNow the block performs the final upload and is saved as JSON.\n\n## Creating Custom Blocks\n\nIt is impossible to support all blocks out there, so we can implement our own blocks in an easy way. A standard block looks like the following:\n\n```php\nuse BumpCore\\EditorPhp\\Block\\Block;\n\nclass MyCustomBlock extends Block\n{\n    public function render(): string\n    {\n        return view('blocks.my-custom-block', ['data' =\u003e $this-\u003edata]);\n    }\n}\n```\n\nAs you can see, by default, we just need to implement the rendering logic. However, there's more than just rendering.\n\n## Accessing Block's Data\n\nThere are multiple ways to access a block's data. In the example below, you can see different methods for accessing block data:\n\n```php\npublic function render(): string\n{\n    // ...\n\n    // Method 1: Accessing through the data object.\n    $data = $this-\u003edata;\n    $data-\u003eget('custom.data');\n    $data-\u003eset('custom.data', 'Hello World!');\n\n    // Method 2: Accessing by invoking the data object.\n    $data('custom.data'); // Hello World!\n\n    // Method 3: Using shortcuts.\n    $this-\u003eget('custom.data');\n    $this-\u003eset('custom.data', 'Nice!');\n\n    // ...\n}\n```\n\nYou can choose any of the above methods to access and manipulate the block's data. Additionally, you can also check whether the data exists or not using the following methods:\n\n```php\n$data-\u003ehas('custom.data');\n// or\n$this-\u003ehas('custom.data');\n```\n\n## Validating Block Data\n\nValidating data is not required, but it can make your data safer. Validating block data is quite easy. We just have to add a `rules` method to our block:\n\n```php\nuse BumpCore\\EditorPhp\\Block\\Block;\n\nclass MyCustomBlock extends Block\n{\n    // ...\n\n    public function rules(): array\n    {\n        return [\n            'text' =\u003e 'required|string|max:255',\n            'items' =\u003e 'sometimes|array',\n            'items.*.name' =\u003e 'required|string|max:255',\n            'items.*.html' =\u003e 'required|string|min:255',\n        ];\n    }\n\n    // ...\n}\n```\n\nWhen validating the block's data fails, the data will be empty. Data validation is performed using Laravel's validation library. You can learn more about it in [Laravel's documentation](https://laravel.com/docs/10.x/validation).\n\n## Sanitizing Block Data\n\nYou can purify the HTML of your data if you wish. It's important to prevent injections. Purifying data looks much like validation:\n\n```php\nuse BumpCore\\EditorPhp\\Block\\Block;\n\nclass MyCustomBlock extends Block\n{\n    // ...\n\n    public function allow(): array|string\n    {\n        // Specifying one by one.\n        return [\n            'text' =\u003e [\n                'a:href,target,title', // Will allow `a` tag and href, target, and title attributes.\n                'b', // Will only allow `b` tag with no attributes.\n            ],\n            'items.*.name' =\u003e 'b:*', // Will allow `b` tag with all attributes.\n            'items.*.html' =\u003e '*', // Will allow every tag and every attribute.\n        ];\n\n        // Or just allowing all attributes and tags for all data.\n        return '*';\n    }\n\n    // ...\n}\n```\n\nUnlike validation, purifying will only strip unwanted tags and attributes.\n\n## Fake Data Generation\n\nAs we mentioned earlier, we can generate fake data with `EditorPhp` . But it requires to generate each block's own fake data. To generate fake data we should add static method to our block:\n\n```php\nuse BumpCore\\EditorPhp\\Block\\Block;\n\nclass MyCustomBlock extends Block\n{\n    // ...\n\n    public static function fake(\\Faker\\Generator $faker): array\n    {\n        $items = [];\n\n        foreach (range(0, $faker-\u003enumberBetween(0, 10)) as $index)\n        {\n            $items[] = [\n                'name' =\u003e fake()-\u003ename(),\n                'html' =\u003e $faker-\u003erandomHtml(),\n            ];\n        }\n\n        return [\n            'text' =\u003e fake()-\u003etext(255),\n            'items' =\u003e $items,\n        ];\n    }\n\n    // ...\n}\n```\n\nBy adding `fake` method to our block, now `EditorPhp` will also include `MyCustomBlock` when generating fake data. You can learn more about at [FakerPHP's documentation](https://fakerphp.github.io/).\n\n# Laravel Only Features\n\nThere's few Laravel features that will make your life little bit easier.\n\n## Cast\n\nYou can use `EditorPhpCast` to cast your model's attribute to `EditorPhp` instance.\n\n```php\nuse BumpCore\\EditorPhp\\Casts\\EditorPhpCast;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Post extends Model\n{\n    protected $casts = [\n        'content' =\u003e EditorPhpCast::class,\n    ];\n}\n\n// ...\n\n$post = Post::find(1);\n\n// Content is `EditorPhp` instance in here.\necho $post-\u003econtent-\u003erender();\n```\n\nAlso if you are using cast, you may access your model within block instances:\n\n```php\nuse BumpCore\\EditorPhp\\Block\\Block;\nuse App\\Models\\Post;\n\nclass MyBlock extends Block\n{\n    // ...\n\n    public static function render(): string\n    {\n        if($this-\u003eroot-\u003emodel instanceof Post)\n        {\n            // Do the other thing.\n        }\n    }\n\n    // ...\n}\n```\n\nYou can also alter the model from the block.\n\n## Response\n\n`EditorPhp` instance can be returned as response. If request expects JSON it will encode it self to JSON. Otherwise it will be rendered into html.\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Models\\Post;\n\nclass ShowPostController extends Controller\n{\n    public function __invoke(Post $post)\n    {\n        // Depending on the request it will return json or rendered html.\n        return $post-\u003econtent;\n    }\n}\n```\n\n## Views\n\nYou may also use `EditorPhp` instance to render inside view directly:\n\n```blade\n{{-- blog.show.blade.php --}}\n\n\u003carticle\u003e\n    \u003ch1\u003e{{ $post-\u003etitle }}\u003c/h1\u003e\n    \u003cdiv\u003e{{ $post-\u003econtent }}\u003c/div\u003e\n\u003c/article\u003e\n```\n\n## Publishing Views and Configuration\n\nGot to check this before documenting it.\n\n## Commands\n\nYou can create brand new block with `block:make \u003cname\u003e` command:\n\n```bash\nphp artisan make:block CustomImageBlock\n```\n\nNew block will be placed under `app/Blocks` directory.\n\n# Contribution\n\nContributions are welcome! If you find a bug or have a suggestion for improvement, please open an issue or create a pull request. Below are some guidelines to follow:\n\n* Fork the repository and clone it to your local machine.\n* Create a new branch for your contribution.\n* Make your changes and test them thoroughly.\n* Ensure that your code adheres to the existing coding style and conventions.\n* Commit your changes and push them to your forked repository.\n* Submit a pull request to the main repository.\n\nPlease provide a detailed description of your changes and the problem they solve. Your contribution will be reviewed, and feedback may be provided. Thank you for your help in making this project better!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbumpcore%2Feditor.php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbumpcore%2Feditor.php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbumpcore%2Feditor.php/lists"}