import EditorJS from '../../vendor/editorjs/editorjs.mjs'; import { warnOnce } from '../core/app-dom.js'; const form = document.querySelector('[data-page-editor]'); if (form) { const holder = form.querySelector('[data-editor-holder]'); if (!holder) { warnOnce('UI_EL_MISSING', 'Missing editor holder', { module: 'page-editor' }); } else { const contentField = form.querySelector('#page-content'); if (!contentField) { warnOnce('UI_EL_MISSING', 'Missing #page-content input', { module: 'page-editor' }); } const toggleButton = document.querySelector('[data-editor-toggle]'); const saveButton = document.querySelector('[data-editor-save]'); const canEdit = form.dataset.canEdit === '1'; const parseData = (value) => { if (!value) { return { blocks: [] }; } try { const parsed = JSON.parse(value); if (parsed && typeof parsed === 'object') { if (!Array.isArray(parsed.blocks)) { parsed.blocks = []; } return parsed; } } catch (error) { // ignore invalid JSON } return { blocks: [] }; }; const setToggleLabel = (mode) => { if (!toggleButton) { return; } const viewLabel = toggleButton.dataset.viewLabel || ''; const editLabel = toggleButton.dataset.editLabel || ''; const text = mode === 'edit' ? viewLabel : editLabel; const icon = toggleButton.querySelector('[data-editor-icon]'); if (icon) { icon.className = mode === 'edit' ? 'bi bi-eye-fill' : 'bi bi-pencil-square'; } toggleButton.setAttribute('aria-label', text); toggleButton.dataset.tooltip = text; }; let mode = form.dataset.editMode === 'edit' && canEdit ? 'edit' : 'view'; form.dataset.editMode = mode; setToggleLabel(mode); const HeaderTool = window.Header || window.EditorJSHeader || null; const ListTool = window.EditorjsList || window.List || null; const ChecklistTool = window.Checklist || window.EditorJSChecklist || null; const TableTool = window.Table || window.EditorJSTable || null; const ColumnsTool = window.editorjsColumns || window.Columns || null; const MarkerTool = window.Marker || null; const tools = {}; if (HeaderTool) { tools.header = { class: HeaderTool, inlineToolbar: true, config: { placeholder: form.dataset.headerPlaceholder || 'Heading', levels: [1, 2, 3, 4], defaultLevel: 1, }, }; } if (ListTool) { tools.list = { class: ListTool, inlineToolbar: true, config: { defaultStyle: 'unordered', }, }; } if (ChecklistTool) { tools.checklist = { class: ChecklistTool, inlineToolbar: true, }; } if (TableTool) { tools.table = { class: TableTool, inlineToolbar: true, config: { rows: 2, cols: 2, }, }; } if (ColumnsTool) { const innerTools = { ...tools }; tools.columns = { class: ColumnsTool, config: { EditorJsLibrary: EditorJS, tools: innerTools, }, }; } if (MarkerTool) { tools.marker = { class: MarkerTool, shortcut: 'CMD+SHIFT+M', }; } const inlineTools = ['bold', 'italic', 'link']; if (MarkerTool) { inlineTools.unshift('marker'); } const editor = new EditorJS({ holder, data: parseData(contentField ? contentField.value : ''), readOnly: mode !== 'edit', autofocus: mode === 'edit', placeholder: form.dataset.placeholder || undefined, tools, inlineToolbar: inlineTools, }); const toggleMode = async (nextMode) => { if (!canEdit || mode === nextMode) { return; } mode = nextMode; form.dataset.editMode = mode; setToggleLabel(mode); if (editor.readOnly && editor.readOnly.toggle) { await editor.readOnly.toggle(mode !== 'edit'); } if (saveButton) { saveButton.disabled = mode !== 'edit'; } }; if (toggleButton && canEdit) { toggleButton.addEventListener('click', () => { toggleMode(mode === 'edit' ? 'view' : 'edit'); }); } if (form && contentField && canEdit) { form.addEventListener('submit', async (event) => { if (form.dataset.submitting === '1') { return; } event.preventDefault(); const output = await editor.save(); contentField.value = JSON.stringify(output); form.dataset.submitting = '1'; try { const formData = new FormData(form); const response = await fetch(form.action || window.location.pathname, { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest', Accept: 'application/json', }, body: formData, }); if (response.redirected) { window.location.href = response.url; return; } const data = await response.json().catch(() => null); if (data && data.redirect) { window.location.href = data.redirect; return; } window.location.reload(); } catch (error) { form.submit(); } }); } } }