mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
WYSIWYG: Improved a range of text direction/alignment scenarios
- Removes 'span' from being a valid part of alignment formats so it's not used to align contents, since it's going to mostly be an inline format, wheras you'd really want alignment on the parent block. - Adds direction cleaning to all direction change events, to remove direction styles and child direction controls which may complicate matters and cause direction changes not to show. - Makes text direction controls work with table cell range selections, which TinyMCE does not consider by default, via manual handling. For #4843
This commit is contained in:
parent
16327cf40c
commit
c290d01adb
@ -14,7 +14,11 @@ import {getPlugin as getAboutPlugin} from './plugins-about';
|
|||||||
import {getPlugin as getDetailsPlugin} from './plugins-details';
|
import {getPlugin as getDetailsPlugin} from './plugins-details';
|
||||||
import {getPlugin as getTableAdditionsPlugin} from './plugins-table-additions';
|
import {getPlugin as getTableAdditionsPlugin} from './plugins-table-additions';
|
||||||
import {getPlugin as getTasklistPlugin} from './plugins-tasklist';
|
import {getPlugin as getTasklistPlugin} from './plugins-tasklist';
|
||||||
import {handleClearFormattingOnTableCells, handleEmbedAlignmentChanges} from './fixes';
|
import {
|
||||||
|
handleTableCellRangeEvents,
|
||||||
|
handleEmbedAlignmentChanges,
|
||||||
|
handleTextDirectionCleaning,
|
||||||
|
} from './fixes';
|
||||||
|
|
||||||
const styleFormats = [
|
const styleFormats = [
|
||||||
{title: 'Large Header', format: 'h2', preview: 'color: blue;'},
|
{title: 'Large Header', format: 'h2', preview: 'color: blue;'},
|
||||||
@ -37,9 +41,9 @@ const styleFormats = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const formats = {
|
const formats = {
|
||||||
alignleft: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img,iframe,video,span', classes: 'align-left'},
|
alignleft: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img,iframe,video', classes: 'align-left'},
|
||||||
aligncenter: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img,iframe,video,span', classes: 'align-center'},
|
aligncenter: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img,iframe,video', classes: 'align-center'},
|
||||||
alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img,iframe,video,span', classes: 'align-right'},
|
alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img,iframe,video', classes: 'align-right'},
|
||||||
calloutsuccess: {block: 'p', exact: true, attributes: {class: 'callout success'}},
|
calloutsuccess: {block: 'p', exact: true, attributes: {class: 'callout success'}},
|
||||||
calloutinfo: {block: 'p', exact: true, attributes: {class: 'callout info'}},
|
calloutinfo: {block: 'p', exact: true, attributes: {class: 'callout info'}},
|
||||||
calloutwarning: {block: 'p', exact: true, attributes: {class: 'callout warning'}},
|
calloutwarning: {block: 'p', exact: true, attributes: {class: 'callout warning'}},
|
||||||
@ -194,7 +198,8 @@ function getSetupCallback(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
handleEmbedAlignmentChanges(editor);
|
handleEmbedAlignmentChanges(editor);
|
||||||
handleClearFormattingOnTableCells(editor);
|
handleTableCellRangeEvents(editor);
|
||||||
|
handleTextDirectionCleaning(editor);
|
||||||
|
|
||||||
// Custom handler hook
|
// Custom handler hook
|
||||||
window.$events.emitPublic(options.containerElement, 'editor-tinymce::setup', {editor});
|
window.$events.emitPublic(options.containerElement, 'editor-tinymce::setup', {editor});
|
||||||
|
@ -55,16 +55,30 @@ export function handleEmbedAlignmentChanges(editor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TinyMCE does not seem to do a great job on clearing styles in complex
|
* Cleans up the direction property for an element.
|
||||||
* scenarios (like copied word content) when a range of table cells
|
* Removes all inline direction control from child elements.
|
||||||
* are selected. This tracks the selected table cells, and watches
|
* Removes non "dir" attribute direction control from provided element.
|
||||||
* for clear formatting events, so some manual cleanup can be performed.
|
* @param {HTMLElement} element
|
||||||
*
|
*/
|
||||||
|
function cleanElementDirection(element) {
|
||||||
|
const directionChildren = element.querySelectorAll('[dir],[style*="direction"],[style*="text-align"]');
|
||||||
|
for (const child of directionChildren) {
|
||||||
|
child.removeAttribute('dir');
|
||||||
|
child.style.direction = null;
|
||||||
|
child.style.textAlign = null;
|
||||||
|
}
|
||||||
|
element.style.direction = null;
|
||||||
|
element.style.textAlign = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This tracks table cell range selection, so we can apply custom handling where
|
||||||
|
* required to actions applied to such selections.
|
||||||
* The events used don't seem to be advertised by TinyMCE.
|
* The events used don't seem to be advertised by TinyMCE.
|
||||||
* Found at https://github.com/tinymce/tinymce/blob/6.8.3/modules/tinymce/src/models/dom/main/ts/table/api/Events.ts
|
* Found at https://github.com/tinymce/tinymce/blob/6.8.3/modules/tinymce/src/models/dom/main/ts/table/api/Events.ts
|
||||||
* @param {Editor} editor
|
* @param {Editor} editor
|
||||||
*/
|
*/
|
||||||
export function handleClearFormattingOnTableCells(editor) {
|
export function handleTableCellRangeEvents(editor) {
|
||||||
/** @var {HTMLTableCellElement[]} * */
|
/** @var {HTMLTableCellElement[]} * */
|
||||||
let selectedCells = [];
|
let selectedCells = [];
|
||||||
|
|
||||||
@ -75,6 +89,10 @@ export function handleClearFormattingOnTableCells(editor) {
|
|||||||
selectedCells = [];
|
selectedCells = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TinyMCE does not seem to do a great job on clearing styles in complex
|
||||||
|
// scenarios (like copied word content) when a range of table cells
|
||||||
|
// are selected. Here we watch for clear formatting events, so some manual
|
||||||
|
// cleanup can be performed.
|
||||||
const attrsToRemove = ['class', 'style', 'width', 'height'];
|
const attrsToRemove = ['class', 'style', 'width', 'height'];
|
||||||
editor.on('FormatRemove', () => {
|
editor.on('FormatRemove', () => {
|
||||||
for (const cell of selectedCells) {
|
for (const cell of selectedCells) {
|
||||||
@ -83,4 +101,41 @@ export function handleClearFormattingOnTableCells(editor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TinyMCE does not apply direction events to table cell range selections
|
||||||
|
// so here we hastily patch in that ability by setting the direction ourselves
|
||||||
|
// when a direction event is fired.
|
||||||
|
editor.on('ExecCommand', event => {
|
||||||
|
const command = event.command;
|
||||||
|
if (command !== 'mceDirectionLTR' && command !== 'mceDirectionRTL') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dir = command === 'mceDirectionLTR' ? 'ltr' : 'rtl';
|
||||||
|
for (const cell of selectedCells) {
|
||||||
|
cell.setAttribute('dir', dir);
|
||||||
|
cleanElementDirection(cell);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Direction control might not work if there are other unexpected direction-handling styles
|
||||||
|
* or attributes involved nearby. This watches for direction change events to clean
|
||||||
|
* up direction controls, removing non-dir-attr direction controls, while removing
|
||||||
|
* directions from child elements that may be involved.
|
||||||
|
* @param {Editor} editor
|
||||||
|
*/
|
||||||
|
export function handleTextDirectionCleaning(editor) {
|
||||||
|
editor.on('ExecCommand', event => {
|
||||||
|
const command = event.command;
|
||||||
|
if (command !== 'mceDirectionLTR' && command !== 'mceDirectionRTL') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const blocks = editor.selection.getSelectedBlocks();
|
||||||
|
for (const block of blocks) {
|
||||||
|
cleanElementDirection(block);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user