PHP code example of ptnghia / laravel-tiptap-editor

1. Go to this page and download the library: Download ptnghia/laravel-tiptap-editor library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

ptnghia / laravel-tiptap-editor example snippets


public function store(Request $request)
{
    $request->validate(['content' => '),
    ]);
}

use Suspended\TiptapEditor\Facades\TiptapEditor;

$html = TiptapEditor::render($post->content_json);
// or pass an array directly
$html = TiptapEditor::render($post->content_array);

use Suspended\TiptapEditor\Traits\HasTiptapContent;

class Post extends Model
{
    use HasTiptapContent;

    // Expects a 'content_json' column (override with $tiptapColumn)
}

$post->renderContent();          // JSON → safe HTML string
$post->getExcerpt(200);          // Plain-text excerpt, 200 chars
$post->getPlainText();           // All text, no markup
$post->getHeadings();            // [['level' => 1, 'text' => '...']]
$post->hasContent();             // bool
$post->getTiptapContent();       // Raw content as array
$post->setTiptapContent($json);  // Set from array or JSON string

'extensions' => [
    // Text formatting
    'paragraph', 'heading', 'bold', 'italic', 'underline', 'strike',
    'subscript', 'superscript', 'blockquote', 'codeBlock', 'horizontalRule',
    'hardBreak', 'link', 'textAlign', 'color', 'highlight', 'characterCount',

    // Bootstrap layout & components
    'bootstrapRow', 'bootstrapCol',
    'bootstrapAlert', 'bootstrapCard', 'bootstrapButton',

    // Media
    'customImage', 'customVideo', 'gallery',

    // Table
    'table', 'tableRow', 'tableCell', 'tableHeader',

    // UX features
    'slashCommands',
],

'toolbar' => [
    'groups' => [
        'text'      => ['bold', 'italic', 'underline', 'strike'],
        'heading'   => ['h1', 'h2', 'h3', 'h4'],
        'alignment' => ['alignLeft', 'alignCenter', 'alignRight', 'alignJustify'],
        'list'      => ['bulletList', 'orderedList'],
        'insert'    => ['link', 'image', 'video', 'table', 'horizontalRule'],
        'block'     => ['blockquote', 'codeBlock'],
        'layout'    => ['row'],
        'component' => ['alert', 'card', 'button'],
        'format'    => ['color', 'highlight', 'subscript', 'superscript'],
        'history'   => ['undo', 'redo'],
        'utils'     => ['gallery', 'darkMode', 'shortcuts'],
    ],
],

'theme' => 'auto',  // 'auto' | 'light' | 'dark'

// config/tiptap-editor.php
'rendering' => [
    'output_theme' => 'tailwind',  // 'bootstrap' (default) | 'tailwind'

    // Auto-inject a pre-built fallback stylesheet if your project
    // does not have Tailwind CSS installed/built:
    'tailwind_fallback_css' => true,

    // Override specific component classes:
    'class_overrides' => [
        'card'      => 'my-card rounded-xl shadow-lg',
        'card.body' => 'p-8',
    ],
],

'media' => [
    'disk'          => env('TIPTAP_MEDIA_DISK', 'public'),
    'path'          => 'tiptap-media',
    'max_file_size' => 5120,  // KB (5 MB)

    'allowed_types' => [
        'image/jpeg', 'image/png', 'image/gif',
        'image/webp', 'image/svg+xml',
        'video/mp4', 'video/webm',
    ],

    // Requires: composer    ],
],

'media' => [
    // Upload directory organization
    'directory_strategy' => env('TIPTAP_MEDIA_DIR_STRATEGY', 'default'),
    // 'default' — tiptap-media/YYYY/MM/
    // 'user'    — tiptap-media/user-{id}/YYYY/MM/
    // 'custom'  — use directory_resolver callback

    'directory_resolver' => null,
    // Example:  fn($basePath, $datePath, $user) => "{$basePath}/team-{$user->team_id}/{$datePath}"

    // Permission gate (Laravel Gate name, null = no gate check)
    'permissions' => [
        'gate'  => env('TIPTAP_UPLOAD_GATE', null),    // e.g. 'upload-media'
        'roles' => [],                                   // e.g. ['admin', 'editor']
        // Compatible with Spatie/Permission (hasAnyRole) or a simple 'role' attribute
    ],

    // File extensions that will always be rejected
    'blocked_extensions' => [
        'php', 'php3', 'php4', 'php5', 'php7', 'php8', 'phtml', 'phar',
        'exe', 'bat', 'cmd', 'com', 'msi', 'dll',
        'sh', 'bash', 'csh', 'ksh', 'zsh',
        'js', 'jsx', 'ts', 'tsx',
        'py', 'pyc', 'rb', 'pl', 'cgi',
        'asp', 'aspx', 'jsp', 'jspx',
        'htaccess', 'htpasswd',
        'env', 'ini', 'yml', 'yaml', 'toml',
    ],
],

// In AuthServiceProvider or a Gate definition
Gate::define('upload-media', function ($user) {
    return $user->is_editor || $user->is_admin;
});

// config/tiptap-editor.php
'media' => [
    'permissions' => [
        'roles' => ['admin', 'editor', 'contributor'],
    ],
],

'sanitization' => [
    'allowed_attributes' => [
        // Link attributes
        'href', 'target', 'rel', 'title',

        // Image attributes
        'src', 'alt', 'width', 'height', 'loading',

        // Layout & component attributes
        'class', 'data-type', 'data-alert-type', 'data-col-class',

        // Table attributes
        'role', 'colspan', 'rowspan',

        // Style (limited to color/background-color via the sanitizer)
        'style',
    ],
    'max_nesting_depth' => 10,
    'max_content_size'  => 512000,  // bytes (500 KB)
],

'video_providers' => [
    'youtube' => [
        'regex'     => '/(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]+)/',
        'embed_url' => 'https://www.youtube-nocookie.com/embed/{id}',
    ],
    'vimeo' => [
        'regex'     => '/vimeo\.com\/(\d+)/',
        'embed_url' => 'https://player.vimeo.com/video/{id}',
    ],
],

'routes' => [
    'prefix'     => 'tiptap-editor',
    'middleware' => ['web', 'auth'],
],

'ai' => [
    'enabled'          => env('TIPTAP_AI_ENABLED', false),
    'default_provider' => env('TIPTAP_AI_PROVIDER', 'openai'),

    'providers' => [
        'openai' => [
            'api_key'     => env('OPENAI_API_KEY'),
            'model'       => env('TIPTAP_AI_OPENAI_MODEL', 'gpt-4o-mini'),
            'max_tokens'  => 4096,
            'temperature' => 0.7,
        ],
        'claude' => [
            'api_key'    => env('ANTHROPIC_API_KEY'),
            'model'      => env('TIPTAP_AI_CLAUDE_MODEL', 'claude-sonnet-4-20250514'),
            'max_tokens' => 4096,
        ],
    ],

    'rate_limit' => [
        'max_requests' => 20,
        'per_minutes'  => 60,
    ],

    'capabilities' => [
        'generate'  => true,
        'refine'    => true,
        'summarize' => true,
        'translate' => true,
    ],
],

use Suspended\TiptapEditor\Services\AiContentService;

$ai = app(AiContentService::class);

$response = $ai->generate('Write a blog post about Laravel packages');
echo $response->content;     // HTML string
echo $response->tokensUsed;  // int

$refined   = $ai->refine($existingHtml, 'Make it more concise');
$summary   = $ai->summarize($longContent, maxLength: 300);
$translated = $ai->translate($content, 'vi');

use Suspended\TiptapEditor\Facades\TiptapEditor;

// Sanitize before storing
$cleanJson = TiptapEditor::sanitize($request->input('content'));
$post->content_json = $cleanJson;

use Suspended\TiptapEditor\Support\NodeRegistry;
use Suspended\TiptapEditor\Services\HtmlRenderer;

// In a ServiceProvider boot()
$registry = app(NodeRegistry::class);

$registry->registerSchema('myBlock', [
    'allowed_attributes' => ['class', 'data-type'],
    'allowed_children'   => ['paragraph'],
]);

$registry->register('myBlock', function (array $node, HtmlRenderer $renderer): string {
    $content = $renderer->renderChildren($node);
    return "<div class=\"my-block\">{$content}</div>";
});

use Suspended\TiptapEditor\Contracts\AiProviderInterface;
use Suspended\TiptapEditor\Services\Ai\AiResponse;

class MyProvider implements AiProviderInterface
{
    public function generate(string $prompt, array $options = []): AiResponse
    {
        $content = '...'; // call your API
        return new AiResponse(
            content: $content,
            tiptapJson: null,
            tokensUsed: 0,
            provider: 'my-provider',
            model: 'my-model',
        );
    }

    public function supports(string $capability): bool
    {
        return in_array($capability, ['generate', 'refine']);
    }

    public function getName(): string { return 'my-provider'; }
}

app(AiContentService::class)->registerProvider('my-provider', new MyProvider());
bash
# JS + CSS assets → public/vendor/tiptap-editor/
php artisan vendor:publish --tag=tiptap-editor-assets

# Config file → config/tiptap-editor.php
php artisan vendor:publish --tag=tiptap-editor-config

# Database migrations (tiptap_media table)
php artisan vendor:publish --tag=tiptap-editor-migrations
php artisan migrate
bash
# Blade views (for customizing rendered HTML)
php artisan vendor:publish --tag=tiptap-editor-views

# Language files
php artisan vendor:publish --tag=tiptap-editor-lang
bash
php artisan vendor:publish --tag=tiptap-editor-lang
# lang/vendor/tiptap-editor/{locale}/editor.php

src/
├── EditorServiceProvider.php
├── Facades/TiptapEditor.php
├── Contracts/AiProviderInterface.php
├── Http/Controllers/  (MediaUploadController, AiContentController)
├── Http/Middleware/   (ValidateMediaUpload, AiRateLimiter)
├── Http/Requests/     (MediaUploadRequest, AiContentRequest)
├── Models/Media.php
├── Services/
│   ├── HtmlRenderer.php
│   ├── JsonSanitizer.php
│   ├── ContentValidator.php
│   ├── MediaManager.php
│   ├── AiContentService.php
│   └── Ai/ (OpenAiProvider, ClaudeProvider, AiResponse)
├── Support/ (NodeRegistry, AiPromptTemplates)
├── Traits/HasTiptapContent.php
└── View/Components/TiptapEditor.php

resources/js/editor/
├── index.js            Editor.js            Toolbar.js
├── extensions/         (9 Tiptap extensions)
├── MediaBrowser.js     AiPanel.js           BlockMenu.js
├── KeyboardShortcuts.js AccessibilityManager.js ResponsivePreview.js
└── utils/              (helpers.js, sanitizer.js)

dist/
├── js/tiptap-editor.es.js   (685 KB / 180 KB gzipped)
├── js/tiptap-editor.umd.js  (449 KB / 136 KB gzipped)
└── css/tiptap-editor.css    (27 KB / 5 KB gzipped)