Search by

mountainclans / livewire-tiptap

VladimirBazhenov

This is my package livewire-tiptap

Package info

github.com/mountainclans/livewire-tiptap

Language:Blade

pkg:composer/mountainclans/livewire-tiptap

Fund package maintenance!

Mountain Clans

Statistics

Installs: 155

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.8.1 2026-09-30 08:38 UTC

This package is auto-updated.

Last update: 2026-09-30 08:39:24 UTC


README

Установка

Установите пакет при помощи Composer:

composer require mountainclans/livewire-tiptap

Поскольку пакет основан на Tiptap Editor, установите его командой

npm install @tiptap/core @tiptap/pm @tiptap/starter-kit  @tiptap/extension-table@^2.0.0 @tiptap/extension-table-row@^2.0.0 @tiptap/extension-table-header@^2.0.0 @tiptap/extension-table-cell@^2.0.0

Добавьте в app.js следующие строки:

import tiptap from '../../vendor/mountainclans/livewire-tiptap/resources/js/tiptap';
Alpine.data('tiptap', tiptap);

Добавьте в app.css следующие строки:

@import '../../vendor/mountainclans/livewire-tiptap/resources/css/tiptap.css';

Обратите внимание, что для корректной стилизации в вашем проекте должен использоваться TailwindCSS.

Добавьте в tailwind.config.js следующие блоки:

export default {
    content: [
        './vendor/mountainclans/livewire-tiptap/resources/views/**/*.blade.php',
    ],
    plugins: [
        require("flowbite/plugin")({
            wysiwyg: true,
        }),
        require("flowbite-typography"),
    ],
    safelist: [
        'max-w-none',
        'text-xs', 'text-sm', 'text-base', 'text-lg', 'text-xl', 'text-2xl', 'text-3xl', 'text-4xl', 'text-5xl',
        'w-4', 'h-4', 'w-6', 'h-6', "h-9", 'w-fit', 'max-w-full', 'h-auto',
        'block', 'relative', 'absolute', 'flex',
        "w-64", "w-1/2",
        "rounded-l-lg", "rounded-r-lg",
        "bg-gray-200", 'bg-gray-600', 'bg-gray-700', 'bg-gray-900', "bg-opacity-50", "dark:bg-opacity-80",
        "grid-cols-4", "grid-cols-7",
        "leading-6", "leading-9",
        "shadow-lg",
        "lg:format-md",
        'top-1', 'right-1',
        'my-0', 'my-1',
        'hover:bg-gray-400',
        'rounded', 'rounded-lg',
        'text-center', 'text-white', 'text-xs',
        'items-center', 'justify-center',
        'mx-auto',
        'cursor-pointer',
        'border-none', 'select-none',
    ]
}

Если редактор используется для заливки изображений:

Опубликуйте и примените миграцию:

php artisan vendor:publish --tag="livewire-tiptap-migrations"
php artisan migrate

Опционально, Вы можете опубликовать views для их переопределения:

php artisan vendor:publish --tag="livewire-tiptap-views"

Использование

<x-ui.tiptap wire:model="content"
             :with-image="true"
             :with-table="true"
             translatable
             height="700"
             placeholder="{{ __('Content') }}"
             label="{{ __('Page`s content *') }}"
/>

Используйте атрибут translatable, если Вы хотите использовать компонент как translatable поле.

Разрешённые инструменты

По умолчанию доступна вся панель. Атрибут tools ограничивает её явным списком:

<x-ui.tiptap wire:model="description"
             :tools="['bold', 'bullet_list', 'ordered_list']"
             label="{{ __('Description') }}"
/>

Набор управляет не только панелью, но и расширениями редактора: спрятанная кнопка сама по себе не мешает ни горячей клавише, ни вставке из буфера, поэтому неразрешённое форматирование выбрасывается схемой при вводе и вставке.

Ключи: bold, italic, underline, strike, link, bullet_list, ordered_list, blockquote, headings, text_size, align, image, table.

Без tools поведение прежнее — включено всё, поэтому старые поля при открытии ничего не теряют. Если tools задан, image и table показываются только когда есть и соответствующий ключ, и with-image / with-table.

Одна строка

Атрибут single-line делает из редактора замену текстовому полю: заголовок, подпись, короткая фраза.

<x-ui.tiptap wire:model="title"
             single-line
             :shortcodes="[
                 ['code' => 'hl', 'label' => 'Акцент', 'kind' => 'pair'],
                 ['code' => 'br', 'label' => 'Перенос'],
             ]"
             label="{{ __('Title') }}"
/>
  • В поле уходит не HTML, а чистый текст с шорткодами: Wine[br][hl]boutique[/hl]. Сущностей и абзаца в нём нет, поэтому поле можно перевести на редактор без правки данных и кода, который его выводит. Экранирует текст, как и раньше, сайт.
  • Строка одна и без оформления: tools, with-image и with-table не действуют, Enter ничего не делает. Перенос ставится шорткодом, если он есть в наборе.
  • Переводы строк в сохранённом тексте при открытии становятся пробелами. Вставка нескольких абзацев попадает в строку целиком, через пробел.
  • Блочные шорткоды здесь запрещены: kind => block даст исключение.
  • Без шорткодов и без with-html панель не показывается.

Исходный код

Атрибут with-html добавляет в панель кнопку «HTML». Она заменяет редактор полем с исходным кодом: его можно прочитать и поправить руками.

<x-ui.tiptap wire:model="description"
             with-html
             label="{{ __('Description') }}"
/>
  • Код показан так, как он лежит в поле: шорткоды — текстом [code]. Для чтения между блоками расставлены переносы строк.
  • Правки попадают в поле сразу, по мере набора.
  • При возврате в редактор текст проходит через его схему: разметка, которой нет в наборе tools, отбрасывается, и поле получает то, что видно в редакторе. Если сохранить форму, не выходя из режима кода, текст сохранится как набран.
  • Просмотр кода без правок значение поля не меняет.

Шорткоды

Шорткод — служебная метка вида [code], которую разбирает сайт, а не редактор: место для блока, разрыв «под кат», особый перенос. Пакет не знает ни одного кода заранее — набор задаёт приложение атрибутом shortcodes:

<x-ui.tiptap wire:model="description"
             :shortcodes="[
                 ['code' => 'CUT', 'label' => 'Под кат', 'kind' => 'block', 'hint' => 'Всё ниже свёрнуто под кнопкой'],
                 ['code' => 'br', 'label' => 'Перенос'],
                 ['code' => 'hl', 'label' => 'Акцент', 'kind' => 'pair'],
             ]"
             label="{{ __('Description') }}"
/>
Ключ Значение
code Текст между скобками: латиница, цифры, _ и -. Регистр учитывается.
label Подпись на кнопке панели и на плашке рядом с меткой. По умолчанию сама метка.
kind block — отдельной строкой между блоками; inline (по умолчанию) — в строке; pair — вокруг текста.
hint Подсказка у кнопки. По умолчанию подпись.
color Цвет метки: gray, green, yellow, blue, red, purple. У парной по умолчанию yellow, у остальных gray.

В сохранённом HTML метка остаётся текстом [code], поэтому код сайта, который её разбирает, менять не нужно, а давние тексты с метками открываются как есть. В редакторе метка показана неделимой плашкой, на которой написаны сам код и подпись — [CUT] — Под кат: её нельзя испортить набором или оформлением. Блочная метка не может оказаться посреди абзаца — при открытии и при вставке абзац делится на два, а в сохранённом HTML она стоит между блоками без обёртки: <p>…</p>[CUT]<p>…</p>.

Парная метка pair обнимает текст: [hl]слово[/hl]. В редакторе это выделение — кнопка в панели включает и выключает его на выбранном тексте, как жирный. Текст внутри подсвечен, по краям видны сами метки. Разные пары можно вкладывать друг в друга, а пара вокруг жирного или курсива в сохранённом HTML не рвётся на куски. Открывающая метка без закрывающей остаётся обычным текстом. Если курсор стоит внутри пары без выделения, кнопка снимает пару целиком. Пара не тянется за курсором: текст, набранный сразу за ней, остаётся снаружи, а стрелка вправо в её конце выводит курсор наружу.

Метка, набранная руками, превращается в плашку сразу, набранная пара — в выделение. Коды, которых нет в наборе, остаются обычным текстом. Набор не зависит от tools.

Неверное определение (недопустимый код, незнакомый kind, повтор кода) — исключение InvalidArgumentException при выводе компонента.

Настройка модели для обработки изображений

Если Вы заливаете картинки в контент текстового редактора, необходимо настроить их обработку в модели.

Используйте трейт:

class YourModel extends Model
{
    use MountainClans\LivewireTiptap\Traits\HasEditorMedia;
}

После сохранения модели с новым полем (в примере content), вызовите метод processUploadedImages:

public function saveBlog(): void
{
    $this->validateInput();
    $this->blog->setTranslations('content', $this->content);
    // или $this->blog->content = $this->content, если поле не переводимое
    $this->blog->save();
    
    $this->blog->processUploadedImages('content');
}

Авторы

License

The MIT License (MIT). Please see License File for more information.