Як змінити конфігурацію спрощених редакторів TinyMCE у Publii

Робоче місце розробника з двома моніторами, що ілюструє налаштування спрощених редакторів TinyMCE у Publii через модуль Miditaur Meta Editor Bridge.
Модуль Miditaur Meta Editor Bridge дозволяє розширювати можливості спрощених редакторів TinyMCE у Publii без внесення змін до ядра системи.
Зображення створене для сайту midiaur.net з використанням технологій штучного інтелекту на основі авторського матеріалу.

У статті розглядається модуль Miditaur Meta Editor Bridge, який дозволяє змінювати конфігурацію спрощених редакторів TinyMCE у Publii без модифікації ядра програми. Показано принцип перехоплення tinymce.init(), розпізнавання редакторів за конфігурацією та застосування окремих параметрів

Редактор TinyMCE використовується в Publii не лише для створення публікацій. Спрощені екземпляри редактора застосовуються також під час редагування описів тегів, авторів та інших службових елементів. На перший погляд усі вони виглядають однаково, однак працюють із різними конфігураціями.

Саме через це багато користувачів стикаються з ситуацією, коли налаштування з tinymce.override.json чудово працюють у редакторі публікацій, але зовсім не впливають на редактори тегів або авторів.

У UTPF Runtime цю проблему вирішує окремий модуль Miditaur Meta Editor Bridge, який дозволяє змінювати конфігурацію спрощених редакторів TinyMCE без модифікації ядра Publii.

Чому виникає ця проблема

Publii використовує різні конфігурації TinyMCE залежно від того, який редактор відкривається.

Основний редактор публікацій отримує повний набір параметрів із tinymce.override.json.

Спрощені редактори створюються окремо і використовують власну конфігурацію. Через це вони не отримують автоматично нові панелі інструментів, додаткові плагіни або інші зміни, внесені для редактора статей.

У результаті сторінки тегів чи авторів залишаються з мінімальним набором можливостей.

Ідея Meta Editor Bridge

Під час запуску будь-якого редактора TinyMCE викликається функція:

tinymce.init(config)

У параметрі config міститься повна конфігурація майбутнього редактора.

Модуль Meta Editor Bridge перехоплює цей виклик, аналізує конфігурацію і, якщо вона відповідає спрощеному редактору Publii, застосовує власні параметри.

Після цього керування повертається стандартній функції TinyMCE.

Таким чином ядро Publii залишається повністю незмінним.

Як модуль визначає потрібний редактор

Одне з найпоширеніших запитань звучить так:

Як модуль розуміє, що зараз відкривається редактор тегів?

Насправді він цього не знає.

Функція tinymce.init() отримує лише об'єкт конфігурації. Вона не містить інформації про сторінку Publii або тип редактора.

Тому використовується інший принцип.

Модуль аналізує саму конфігурацію.

function isPubliiMetaEditor(config) {
    if (!config || typeof config !== 'object') {
        return false;
    }

    const plugins = String(config.plugins || '');
    const toolbar1 = String(config.toolbar1 || '');

    return (
        plugins.includes('autolink') &&
        plugins.includes('link') &&
        plugins.includes('paste') &&
        plugins.includes('code') &&
        toolbar1.includes('forecolor') &&
        toolbar1.includes('removeformat') &&
        !toolbar1.includes('gallery') &&
        !toolbar1.includes('readmore')
    );
}

Зверніть увагу, що функція має назву isPubliiMetaEditor(), а не isTagEditor().

Це зроблено навмисно.

Модуль не визначає сторінку редагування тегів чи авторів. Він шукає конфігурацію, характерну для спрощених редакторів Publii.

Саме тому однакові налаштування можуть застосовуватися до кількох редакторів, якщо вони використовують однакову конфігурацію TinyMCE.

Чому використовується includes()

На перший погляд здається, що простіше було б написати:

config.plugins === 'autolink link paste code'

Проте таке рішення було б дуже крихким.

Достатньо Publii змінити порядок плагінів або додати ще один — і така перевірка перестане працювати.

Тому Meta Editor Bridge перевіряє кожний необхідний елемент окремо.

plugins.includes('autolink')
plugins.includes('link')
plugins.includes('paste')
plugins.includes('code')

Такий підхід значно стійкіший до майбутніх змін.

Перехоплення ініціалізації TinyMCE

Після завантаження модуль зберігає оригінальну функцію:

const originalInit = window.tinymce.init;

Потім створюється власна обгортка.

window.tinymce.init = function (config) {

    if (isPubliiMetaEditor(config)) {
        config = extendMetaEditor(config);
    }

    return originalInit.call(this, config);
};

Таким способом усі редактори проходять через одну точку контролю.

Якщо редактор не відповідає ознакам спрощеної конфігурації Publii, він запускається без будь-яких змін.

Окрема конфігурація metaEditor

Для спрощених редакторів використовується власний розділ конфігурації.

{
    "metaEditor": {
        "enabled": true,
        "plugins": [...],
        "toolbar1": [...],
        "toolbar2": [...],
        "toolbar3": [...]
    }
}

Саме цей об'єкт використовує модуль.

State.config.metaEditor

Завдяки цьому параметри редактора публікацій і редакторів метаданих не змішуються між собою.

Кожен редактор може мати власний набір плагінів, панелей інструментів і режимів роботи.

Підтримка JSON-масивів

UTPF Runtime дозволяє записувати конфігурацію у вигляді масивів.

Наприклад:

"toolbar1": [
    "undo redo",
    "bold italic",
    "forecolor backcolor"
]

Перед передаванням у TinyMCE модуль автоматично перетворює масив на звичайний рядок.

Це робить функція normalizeOption().

У результаті конфігурацію значно простіше читати й підтримувати, особливо коли панелі інструментів містять десятки кнопок.

Чому модуль не змінює setup

У конфігурації TinyMCE існує параметр setup, який створює сам Publii.

Саме він відповідає за:

  • взаємодію TinyMCE з інтерфейсом Publii;
  • синхронізацію редактора з компонентами Vue;
  • внутрішню ініціалізацію редактора.

Meta Editor Bridge принципово не змінює цей callback.

Модуль коригує лише параметри:

  • plugins;
  • toolbar_mode;
  • toolbar1;
  • toolbar2;
  • toolbar3.

Усі інші властивості залишаються без змін, що забезпечує повну сумісність із внутрішньою логікою Publii.

Захист від повторного підключення

Модуль може бути завантажений лише один раз.

Для цього використовується спеціальний прапорець:

window.__UTPF_META_EDITOR_BRIDGE_INSTALLED__

Якщо модуль уже працює, повторне підключення не виконується.

Це запобігає багаторазовому перехопленню tinymce.init() і забезпечує стабільну роботу редактора.

Діагностика

Під час роботи Meta Editor Bridge записує повідомлення до консолі.

Наприклад:

[Meta Editor Bridge] Version 1.0.0 installed.

або

[Meta Editor Bridge] Publii meta editor detected.

Такі повідомлення допомагають швидко перевірити, чи був модуль завантажений і чи застосовано нову конфігурацію.

Практичні висновки

  • Спрощені редактори TinyMCE використовують окрему конфігурацію.
  • tinymce.override.json не налаштовує їх автоматично.
  • Meta Editor Bridge перехоплює виклик tinymce.init().
  • Модуль розпізнає не сторінку Publii, а характерну конфігурацію редактора.
  • Для спрощених редакторів використовується окремий розділ metaEditor.
  • Оригінальний callback setup залишається недоторканим.
  • Конфігурація може записуватися як рядками, так і JSON-масивами.
  • Модуль безпечно інтегрується в архітектуру UTPF Runtime.

Висновок

Miditaur Meta Editor Bridge демонструє, що навіть без змін ядра Publii можна суттєво розширити можливості спрощених редакторів TinyMCE. Замість втручання у внутрішній код програми модуль перехоплює процес ініціалізації редактора, аналізує його конфігурацію та застосовує окремі параметри лише тоді, коли це справді необхідно.

Такий підхід робить налаштування редакторів тегів, авторів та інших службових полів більш гнучким, зберігаючи сумісність із Publii та повністю відповідаючи модульній архітектурі UTPF Runtime.