Tiptap for PHP

repository·main·Indexed 42 days ago

https://github.com/ueberdosis/tiptap-php

A tool for transforming, sanitizing, and modifying Tiptap-compatible JSON and HTML content within PHP applications. It mimics the Tiptap JavaScript library API, providing the Editor class to convert between HTML, JSON, and plain text, as well as support for custom extensions, marks, and syntax highlighting via highlight.php or Shiki.

Tokens
4.4K
Snippets
21
Records
21
Agent score
44%

What's inside Tiptap PHP

  1. Create custom extensions

    main

    You can extend existing extensions to change their behavior (e.g., changing the rendered HTML tag) or build entirely new ones by extending Tiptap\Core\Node.

    When building custom nodes, you can implement:

    • addOptions(): Define configuration options.
    • parseHTML(): Define how HTML is converted to the node.
    • renderHTML(): Define how the node is rendered to HTML.

    Extension Priority: Extensions are evaluated in descending order of priority. The default priority is 100. If a node needs to take precedence over another (e.g., TaskItem over ListItem), set a higher public static $priority value.

    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']];
        }
    
        public function renderHTML($node)
        {
            return ['my-custom-tag', ['class' => 'foobar'], 0];
        }
    }
  2. Add syntax highlighting with Shiki

    main

    Shiki provides high-quality syntax highlighting by injecting inline styles, meaning no external CSS is required.

    Requirements:

    1. Install the shiki npm package: npm install shiki.
    2. Use the CodeBlockShiki extension.

    Configuration: You can configure the theme, defaultLanguage, and guessLanguage options in the extension constructor.

    (new \Tiptap\Editor([
        'extensions' => [
            new \Tiptap\Extensions\StarterKit([
                'codeBlock' => false,
            ]),
            new \Tiptap\Nodes\CodeBlockShiki([
                'theme' => 'github-dark', // default: nord
                'defaultLanguage' => 'php', // default: html
                'guessLanguage' => true, // default: true
            ]),
        ],
    ]))
    ->setContent('<pre><code>&lt;?php phpinfo()</code></pre>')
    ->getHTML();
  3. Configure the Editor and Extensions

    main

    The Editor constructor accepts an array of configuration options.

    • content: Initial content (HTML, JSON, or array).
    • extensions: An array of extension instances.

    StarterKit is loaded by default. You can configure specific extensions (like Heading) by passing options to their constructors, including HTMLAttributes for custom CSS classes.

    new \Tiptap\Editor([
        'content' => '<p>Example Text</p>',
        'extensions' => [
            new \Tiptap\Extensions\StarterKit([
                'heading' => [
                    'HTMLAttributes' => [
                        'class' => 'my-custom-class',
                    ],
                ],
            ]),
        ],
    ]);
  4. Add syntax highlighting with highlight.php

    main

    The default CodeBlock extension does not provide syntax highlighting. To add it using highlight.php, you must disable the default codeBlock in StarterKit and add the CodeBlockHighlight extension.

    Note: This produces unstyled HTML classes (e.g., hljs php). You must include a CSS file from highlight.js in your frontend to see colors.

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

    main

    Generate HTML from a Tiptap-compatible JSON string or PHP array using the setContent() and getHTML() methods.

    (new \Tiptap\Editor)
        ->setContent([
            'type' => 'doc',
            'content' => [
                [
                    'type' => 'paragraph',
                    'content' => [
                        [
                            'type' => 'text',
                            'text' => 'Example Text',
                        ],
                    ]
                ]
            ],
        ])
        ->getHTML();
    
    // Returns: <p>Example Text</p>
  6. Modify content using descendants()

    main

    The descendants() method allows you to loop through all nodes recursively.

    CRITICAL: You must pass the node parameter by reference using &$node in the callback. This ensures you are modifying the original node object rather than a copy.

    $editor->descendants(function (&$node) {
        if ($node->type !== 'heading') {
            return;
        }
    
        $node->attrs->level = 1;
    });
  7. Convert Tiptap HTML to JSON

    main

    Transform an HTML snippet into a Tiptap-compatible PHP array or a JSON string using the Editor class.

    To get a PHP array:

    (new \Tiptap\Editor)->setContent('<p>Example Text</p>')->getDocument();
    // Returns: ['type' => 'doc', 'content' => ...]

    To get a JSON string:

    (new \Tiptap\Editor)->setContent('<p>Example Text</p>')->getJSON();
    // Returns: {"type": "doc", "content": ...}
    (new \Tiptap\Editor)
        ->setContent('<p>Example Text</p>')
        ->getDocument();
  8. Convert content to plain text

    main

    Use the getText() method to strip HTML/JSON formatting and get plain text. This is useful for search indexing.

    You can configure the blockSeparator to define what character is placed between blocks.

    (new \Tiptap\Editor)
        ->setContent('<h1>Heading</h1><p>Paragraph</p>')
        ->getText(['blockSeparator' => "\n"]);
    
    // Returns: "Heading\nParagraph"
  9. Sanitize content

    main

    The sanitize() method cleans content by removing unsafe elements (like <script> tags). It accepts HTML, JSON strings, or PHP arrays and returns the same format as the input.

    (new \Tiptap\Editor)
        ->sanitize('<p>Example Text<script>alert("HACKED!")</script></p>');
    
    // Returns: '<p>Example Text</p>'
  10. Configure the Tiptap Schema

    main

    The Tiptap\Core\Schema class is used to define the structure of a Tiptap document by managing allowed nodes, marks, and extensions. When instantiating a Schema, you pass an array of extension classes. The schema automatically sorts these extensions by their $priority property and categorizes them into nodes, marks, and general extensions.

    Key properties available on a Schema instance:

    • $nodes: An array of extensions that are subclasses of Tiptap\Core\Node.
    • $marks: An array of extensions that are subclasses of Tiptap\Core\Mark.
    • $extensions: An array of extensions that are subclasses of Tiptap\Core\Extension.
    • $defaultNode: The first node found in the sorted extensions list.
    • $topNode: The first node in the list marked as a $topNode.
    • $globalAttributes: Attributes that are applied globally to specific node types.
    use Tiptap\Core\Schema;
    use Your\Namespace\StarterKitExtension;
    
    $schema = new Schema([
        StarterKitExtension::class,
        // Add other extension classes here
    ]);
  11. Retrieve attribute configurations for a node or mark

    main

    To determine which attributes are valid for a specific node or mark type, use the getAttributeConfigurations($class) method. This method merges attributes defined locally within the extension's addAttributes() method with any global attributes registered via addGlobalAttributes() that apply to that specific class name.

    // Assuming $schema is an instance of Tiptap\Core\Schema
    // and $nodeClass is a class name extending Node or Mark
    $attributes = $schema->getAttributeConfigurations($nodeClass);