PHP code example of rjp2525 / laravel-tiptap

1. Go to this page and download the library: Download rjp2525/laravel-tiptap 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/ */

    

rjp2525 / laravel-tiptap example snippets




return [
    /*
    |--------------------------------------------------------------------------
    | Default Extensions
    |--------------------------------------------------------------------------
    |
    | Default extensions to be loaded when creating a new Tiptap instance.
    | Available extensions: StarterKit, Color, FontFamily, TextAlign
    |
    */
    'extensions' => [
        // Use StarterKit for basic functionality
        \Tiptap\Extensions\StarterKit::class => [],

        // Additional extensions (uncomment as needed)
        // \Tiptap\Extensions\Color::class => [],
        // \Tiptap\Extensions\FontFamily::class => [],
        // \Tiptap\Extensions\TextAlign::class => [],
    ],

    /*
    |--------------------------------------------------------------------------
    | Cache Configuration
    |--------------------------------------------------------------------------
    |
    | Configure caching for parsed content to improve performance.
    |
    */
    'cache' => [
        'enabled' => env('TIPTAP_CACHE_ENABLED', true),
        'store' => env('TIPTAP_CACHE_STORE', null), // null uses default cache store
        'ttl' => env('TIPTAP_CACHE_TTL', 3600), // 1 hour
        'prefix' => 'tiptap',
    ],

    /*
    |--------------------------------------------------------------------------
    | Validation Rules
    |--------------------------------------------------------------------------
    |
    | Default validation rules for content validation
    |
    */
    'validation' => [
        'max_length' => 50000,
        'max_depth' => 10,
        'allowed_tags' => null, // null means all configured extensions are allowed
    ],
];

use RJP\Tiptap\Facades\Tiptap;

// Parse JSON to HTML
$json = [
    'type' => 'doc',
    'content' => [
        [
            'type' => 'paragraph',
            'content' => [
                ['type' => 'text', 'text' => 'Hello '],
                ['type' => 'text', 'marks' => [['type' => 'bold']], 'text' => 'world!'],
            ]
        ]
    ]
];

$html = Tiptap::parseJson($json);
// Output: <p>Hello <strong>world!</strong></p>

// Parse HTML back to JSON
$json = Tiptap::parseHtml('<p>Hello <strong>world!</strong></p>');

// Validate content
$isValid = Tiptap::validate($json, ['max_length' => 1000]);

// Get content statistics
$stats = Tiptap::getStats($json);
// Returns: ['characters' => 12, 'words' => 2, 'paragraphs' => 1, 'reading_time' => 1]

use RJP\Tiptap\Facades\Tiptap;

// Content processing with method chaining
$result = Tiptap::make()
    ->content($jsonContent)
    ->starterKit()
    ->color()
    ->textAlign(['types' => ['heading', 'paragraph']])
    ->maxLength(5000)
    ->maxDepth(10)
    ->validateOrFail()
    ->sanitize()
    ->toHtml();

// Content analysis
$stats = Tiptap::make()
    ->content($content)
    ->stats(); // Returns Collection

$wordCount = Tiptap::make()->content($content)->wordCount();
$readingTime = Tiptap::make()->content($content)->readingTime(); // in minutes
$isEmpty = Tiptap::make()->content($content)->isEmpty();

// In config/tiptap.php or dynamically
$result = Tiptap::make()
    ->content($content)
    ->starterKit([
        'heading' => ['levels' => [1, 2, 3]], // Only H1-H3
        'bold' => false, // Disable bold
        'bulletList' => [],
        'orderedList' => [],
    ])
    ->color()
    ->textAlign([
        'types' => ['heading', 'paragraph'],
        'alignments' => ['left', 'center', 'right'],
    ])
    ->toHtml();

// Custom validation rules
$isValid = Tiptap::make()
    ->content($content)
    ->rules([
        'max_length' => 10000,
        'max_depth' => 8,
        'allowed_tags' => ['paragraph', 'heading', 'text', 'bold', 'italic']
    ])
    ->validate();

// Fluent validation methods
$builder = Tiptap::make()
    ->content($content)
    ->maxLength(5000)
    ->maxDepth(5)
    ->allowedTags(['paragraph', 'text', 'bold'])
    ->validateOrFail(); // Throws InvalidArgumentException if validation fails

$builder = Tiptap::make()
    ->content($content)
    ->starterKit()
    ->when($user->isPremium(), fn($b) => $b->color())
    ->when($user->canUseAdvancedFormatting(), fn($b) => $b->fontFamily())
    ->unless($content->isEmpty(), fn($b) => $b->sanitize())
    ->tap(function ($builder) {
        logger('Processing content', [
            'word_count' => $builder->wordCount(),
            'reading_time' => $builder->readingTime(),
        ]);
    });

// In your .env file
TIPTAP_CACHE_ENABLED=true
TIPTAP_CACHE_TTL=3600
TIPTAP_CACHE_STORE=redis

// Or disable caching for specific operations
$result = Tiptap::make()
    ->content($content)
    ->withoutCache()
    ->toHtml();



namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use RJP\Tiptap\Facades\Tiptap;

class CreateArticleRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => ['oo deeply nested.');
                }
            }],
        ];
    }
}



namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Attribute;
use RJP\Tiptap\Facades\Tiptap;

class Article extends Model
{
    protected $fillable = ['title', 'content'];
    protected $casts = ['content' => 'array'];

    // Automatically generate HTML from JSON content
    protected function contentHtml(): Attribute
    {
        return Attribute::make(
            get: fn () => Tiptap::parseJson($this->content),
        );
    }

    // Get content statistics
    protected function contentStats(): Attribute
    {
        return Attribute::make(
            get: fn () => collect(Tiptap::getStats($this->content)),
        );
    }

    // Get plain text version
    protected function contentText(): Attribute
    {
        return Attribute::make(
            get: fn () => Tiptap::toText($this->content),
        );
    }

    // Sanitize content before saving
    protected static function boot()
    {
        parent::boot();

        static::saving(function ($article) {
            if ($article->isDirty('content')) {
                $article->content = Tiptap::make()
                    ->content($article->content)
                    ->validateOrFail()
                    ->sanitize()
                    ->raw();
            }
        });
    }
}



namespace App\Http\Controllers;

use App\Http\Requests\CreateArticleRequest;
use App\Models\Article;
use RJP\Tiptap\Facades\Tiptap;

class ArticleController extends Controller
{
    public function store(CreateArticleRequest $request)
    {
        $processedContent = Tiptap::make()
            ->content($request->validated('content'))
            ->starterKit()
            ->color()
            ->maxLength(50000)
            ->validateOrFail()
            ->sanitize()
            ->raw();

        $stats = Tiptap::make()
            ->content($processedContent)
            ->stats();

        $article = Article::create([
            'title' => $request->validated('title'),
            'content' => $processedContent,
            'word_count' => $stats['words'],
            'reading_time' => $stats['reading_time'],
        ]);

        return response()->json([
            'article' => $article,
            'stats' => $stats,
            'html_preview' => $article->content_html,
        ]);
    }
}



namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use RJP\Tiptap\Facades\Tiptap;
use App\Models\Article;

class ProcessArticleContentJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        private int $articleId,
        private array $content
    ) {}

    public function handle(): void
    {
        $processed = Tiptap::make()
            ->content($this->content)
            ->starterKit()
            ->color()
            ->textAlign()
            ->maxLength(100000)
            ->sanitize()
            ->raw();

        $stats = Tiptap::make()
            ->content($processed)
            ->stats();

        Article::where('id', $this->articleId)->update([
            'content' => $processed,
            'content_html' => Tiptap::parseJson($processed),
            'content_text' => Tiptap::toText($processed),
            'word_count' => $stats['words'],
            'character_count' => $stats['characters'],
            'reading_time' => $stats['reading_time'],
            'paragraph_count' => $stats['paragraphs'],
            'processed_at' => now(),
        ]);
    }
}



namespace App\View\Components;

use Illuminate\View\Component;
use RJP\Tiptap\Facades\Tiptap;

class TiptapContent extends Component
{
    public function __construct(
        public array|string $content,
        public bool $showStats = false,
        public bool $sanitize = true,
    ) {}

    public function render()
    {
        $builder = Tiptap::make()->content($this->content);

        if ($this->sanitize) {
            $builder->sanitize();
        }

        $html = is_array($this->content)
            ? $builder->toHtml()
            : $this->content;

        $stats = $this->showStats
            ? $builder->stats()
            : null;

        return view('components.tiptap-content', [
            'html' => $html,
            'stats' => $stats,
        ]);
    }
}

// In a service provider
use RJP\Tiptap\Tiptap;

$this->app->extend(TiptapInterface::class, function (Tiptap $service) {
    // Add your custom extension logic here
    // Note: This 



namespace App\Services;

use RJP\Tiptap\Contracts\TiptapInterface;
use RJP\Tiptap\Tiptap;

class CustomTiptap implements TiptapInterface
{
    public function __construct(private Tiptap $tiptap) {}

    // Delegate to original service
    public function parseJson(array|string $json, array $extensions = []): string
    {
        return $this->tiptap->parseJson($json, $extensions);
    }

    // Add custom methods
    public function parseMarkdown(string $markdown): array
    {
        // Your markdown parsing logic
        $json = $this->convertMarkdownToTiptapJson($markdown);
        return $json;
    }

    public function extractImages(array|string $content): array
    {
        // Extract image nodes from content
        return $this->findImageNodes($content);
    }

    // Implement other interface methods...
}

// Register in AppServiceProvider
$this->app->bind(TiptapInterface::class, CustomTiptap::class);



namespace App\Services;

use RJP\Tiptap\Builders\TiptapBuilder;

class CustomTiptapBuilder extends TiptapBuilder
{
    /**
     * Add markdown support to the fluent interface.
     */
    public function markdown(string $markdown): self
    {
        $json = $this->convertMarkdownToJson($markdown);
        return $this->content($json);
    }

    /**
     * Enforce word limit validation.
     */
    public function wordLimit(int $limit): self
    {
        return $this->tap(function ($builder) use ($limit) {
            if ($builder->wordCount() > $limit) {
                throw new InvalidArgumentException("Content exceeds {$limit} word limit");
            }
        });
    }

    /**
     * Add reading level analysis.
     */
    public function readingLevel(): array
    {
        $text = $this->toText();
        return $this->calculateReadingLevel($text);
    }

    private function convertMarkdownToJson(string $markdown): array
    {
        // Your markdown to Tiptap JSON conversion logic
        return [];
    }

    private function calculateReadingLevel(string $text): array
    {
        // Your reading level calculation logic
        return ['grade' => 8, 'difficulty' => 'medium'];
    }
}



namespace App\Services;

use RJP\Tiptap\Tiptap;

class ExtendedTiptap extends Tiptap
{
    public function make(): CustomTiptapBuilder
    {
        return new CustomTiptapBuilder($this);
    }
}

// In a service provider boot method
use RJP\Tiptap\Builders\TiptapBuilder;

TiptapBuilder::macro('seoAnalysis', function () {
    return [
        'word_count' => $this->wordCount(),
        'reading_time' => $this->readingTime(),
        'headings' => $this->extractHeadings(),
        'images' => $this->extractImages(),
    ];
});

// Usage
$seoData = Tiptap::make()
    ->content($content)
    ->seoAnalysis();

// Direct methods
Tiptap::parseJson(array|string $json, array $extensions = []): string
Tiptap::parseHtml(string $html, array $extensions = []): array
Tiptap::validate(array|string $content, array $rules = []): bool
Tiptap::sanitize(array|string $content, array $extensions = []): array|string
Tiptap::toText(array|string $content): string
Tiptap::getStats(array|string $content): array

// Builder factory
Tiptap::make(): TiptapBuilder

// Content and extensions
->content(array|string $content)
->extensions(array $extensions)
->starterKit(array $options = [])
->color()
->fontFamily()
->textAlign(array $options = [])

// Validation
->rules(array $rules)
->maxLength(int $length)
->maxDepth(int $depth)
->allowedTags(array $tags)
->validate(): bool
->validateOrFail(): self

// Processing
->sanitize(): self
->withCache() / ->withoutCache()

// Output
->toHtml(): string
->toJson(): array
->toText(): string
->stats(): Collection
->wordCount(): int
->characterCount(bool $
bash
php artisan vendor:publish --tag="tiptap-config"
bash
php artisan vendor:publish --tag="laravel-tiptap-views"