Release v2.5.6

This commit is contained in:
2026-08-05 19:38:16 +01:00
parent a8ef35b287
commit 9f831f04bc
161 changed files with 8487 additions and 1295 deletions
+158 -46
View File
@@ -68,6 +68,32 @@ export function createSlideFormEditorController(options) {
return card ? card.querySelector('input[name="region_font_size_' + regionId + '"]') : null;
}
function getTinymce() {
return window.tinymce || null;
}
function getThemeName() {
var theme = String(document.documentElement && document.documentElement.dataset && document.documentElement.dataset.bsTheme || 'light').trim().toLowerCase();
if (theme === 'auto') {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
return theme === 'dark' ? 'dark' : 'light';
}
function getTinyMceThemeAssets() {
var themeName = getThemeName();
var skinName = themeName === 'dark' ? 'oxide-dark' : 'oxide';
var skinBase = '/assets/vendor/tinymce/skins/ui/' + skinName;
return {
themeName: themeName,
skinName: skinName,
skinUrl: skinBase,
contentCss: skinBase + '/content.css',
bodyClass: themeName === 'dark' ? 'tinymce-theme-dark' : 'tinymce-theme-light'
};
}
function getEditorRegionType(card) {
if (!card) {
return '';
@@ -99,31 +125,6 @@ export function createSlideFormEditorController(options) {
fontSizeHidden.value = normalizeFontSizeValue(fontSizeHidden.value) || String(defaultFontSize);
}
function getTinymce() {
return window.tinymce || null;
}
function getThemeName() {
var theme = String(document.documentElement && document.documentElement.dataset && document.documentElement.dataset.bsTheme || 'light').trim().toLowerCase();
if (theme === 'auto') {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
return theme === 'dark' ? 'dark' : 'light';
}
function getTinyMceThemeAssets() {
var themeName = getThemeName();
var skinName = themeName === 'dark' ? 'oxide-dark' : 'oxide';
var skinBase = '/assets/vendor/tinymce/skins/ui/' + skinName;
return {
themeName: themeName,
skinName: skinName,
skinUrl: skinBase,
contentCss: skinBase + '/content.css',
bodyClass: themeName === 'dark' ? 'tinymce-theme-dark' : 'tinymce-theme-light'
};
}
function getEditorBackgroundColorValue() {
var value = String(getEditorBackgroundColor() || '').trim();
return value || '#111111';
@@ -161,28 +162,19 @@ export function createSlideFormEditorController(options) {
function attachEditorEvents(regionId, editor) {
var hidden = getEditorHiddenInput(regionId);
var source = editor && editor.targetElm ? editor.targetElm : null;
var hydrated = false;
function syncState() {
function syncState(shouldLock) {
var currentEditor = editorInstances.get(regionId);
if (currentEditor !== editor) {
return;
}
if (typeof editor.save === 'function') {
editor.save();
syncEditorState(regionId, editor, shouldLock, hydrated);
if (!hydrated) {
requestPreviewRender();
return;
}
var content = editor.getContent({ format: 'html' });
content = isEmptyRichTextValue(content) ? '' : content;
if (hidden) {
hidden.value = content;
}
if (source) {
source.value = content;
}
if (templateSelectorLock && typeof templateSelectorLock.markEdited === 'function') {
templateSelectorLock.markEdited();
}
requestPreviewRender();
}
editor.on('init', function () {
@@ -195,11 +187,14 @@ export function createSlideFormEditorController(options) {
source.value = content;
}
syncEditorFontSizeHidden(regionId);
syncState();
hydrated = true;
requestPreviewRender();
});
['change', 'keyup', 'undo', 'redo', 'SetContent', 'Paste', 'input', 'NodeChange'].forEach(function (eventName) {
editor.on(eventName, syncState);
['change', 'keyup', 'undo', 'redo', 'Paste', 'input'].forEach(function (eventName) {
editor.on(eventName, function () {
syncState(true);
});
});
}
@@ -226,15 +221,74 @@ export function createSlideFormEditorController(options) {
source.id = 'slide-editor-region-' + regionId;
}
function registerInlineFormat(editor, formatName, styles) {
editor.formatter.register(formatName, {
inline: 'span',
styles: styles
});
}
function syncEditorState(regionId, editor, shouldLock, hydrated) {
if (editor && typeof editor.save === 'function') {
editor.save();
}
var content = editor.getContent({ format: 'html' });
content = isEmptyRichTextValue(content) ? '' : content;
var hidden = getEditorHiddenInput(regionId);
var sourceElm = editor && editor.targetElm ? editor.targetElm : null;
if (hidden) {
hidden.value = content;
}
if (sourceElm) {
sourceElm.value = content;
}
if (typeof editor.nodeChanged === 'function') {
editor.nodeChanged();
}
if (typeof editor.setDirty === 'function') {
editor.setDirty(true);
}
if (shouldLock && templateSelectorLock && typeof templateSelectorLock.arm === 'function') {
templateSelectorLock.arm();
}
if (shouldLock && templateSelectorLock && typeof templateSelectorLock.markEdited === 'function') {
templateSelectorLock.markEdited();
}
if (hydrated) {
requestPreviewRender();
}
}
function applyInlineFormat(regionId, editor, formatName) {
if (editor && editor.undoManager && typeof editor.undoManager.transact === 'function') {
editor.undoManager.transact(function () {
editor.formatter.apply(formatName);
});
} else {
editor.formatter.apply(formatName);
}
syncEditorState(regionId, editor, false, true);
}
function applyEditorCommand(regionId, editor, commandName) {
if (editor && editor.undoManager && typeof editor.undoManager.transact === 'function') {
editor.undoManager.transact(function () {
editor.execCommand(commandName);
});
} else {
editor.execCommand(commandName);
}
syncEditorState(regionId, editor, false, true);
}
return tinymce.init({
target: source,
menubar: false,
branding: false,
promotion: false,
statusbar: true,
resize: true,
plugins: 'lists code advlist fullscreen table',
toolbar: 'undo redo | fontfamily fontsizeinput | forecolor backcolor bold italic underline strikethrough subscript superscript removeformat | align lineheight indent outdent bullist numlist table | fullscreen',
toolbar: 'undo redo | fontfamily fontsizeinput | forecolor backcolor bold italic underlineformats removeformat | align lineheight indent outdent bullist numlist table chip | fullscreen',
toolbar_mode: 'sliding',
license_key: 'gpl',
skin: themeAssets.skinName,
@@ -251,6 +305,64 @@ export function createSlideFormEditorController(options) {
placeholder: String(source.getAttribute('placeholder') || '').trim(),
setup: function (editor) {
editorInstances.set(regionId, editor);
editor.ui.registry.addButton('chip', {
icon: 'addtag',
tooltip: 'Chip style',
onAction: function () {
applyInlineFormat(regionId, editor, 'chip');
}
});
editor.ui.registry.addSplitButton('underlineformats', {
icon: 'underline',
tooltip: 'Text formats',
onAction: function () {
applyEditorCommand(regionId, editor, 'Underline');
},
onItemAction: function (_api, value) {
if (value === 'strikethrough') {
applyEditorCommand(regionId, editor, 'Strikethrough');
return;
}
if (value === 'subscript') {
applyEditorCommand(regionId, editor, 'Subscript');
return;
}
if (value === 'superscript') {
applyEditorCommand(regionId, editor, 'Superscript');
}
},
fetch: function (callback) {
callback([
{
type: 'choiceitem',
value: 'strikethrough',
icon: 'strikethrough',
text: 'Strikethrough',
},
{
type: 'choiceitem',
value: 'subscript',
icon: 'subscript',
text: 'Subscript',
},
{
type: 'choiceitem',
value: 'superscript',
icon: 'superscript',
text: 'Superscript',
}
]);
}
});
editor.on('init', function () {
registerInlineFormat(editor, 'chip', {
display: 'inline-block',
padding: '0.2em 0.6em',
borderRadius: '999px',
fontWeight: '700',
letterSpacing: '0.02em'
});
});
attachEditorEvents(regionId, editor);
}
}).then(function (editors) {