138 lines
3.7 KiB
JavaScript
138 lines
3.7 KiB
JavaScript
/**
|
|
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
|
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
|
*/
|
|
window.tinymce.PluginManager.add('joomlaHighlighter', editor => {
|
|
const setContent = html => {
|
|
editor.focus();
|
|
editor.undoManager.transact(() => {
|
|
editor.setContent(html);
|
|
});
|
|
editor.selection.setCursorLocation();
|
|
editor.nodeChanged();
|
|
};
|
|
const getContent = () => editor.getContent({
|
|
source_view: true
|
|
});
|
|
let running = false;
|
|
const showSourceEditor = () => {
|
|
if (running) {
|
|
return;
|
|
}
|
|
running = true;
|
|
|
|
// Create the dialog
|
|
let cmEditor;
|
|
const dialogConfig = {
|
|
title: 'Source code',
|
|
body: {
|
|
type: 'panel',
|
|
classes: ['joomla-highlighter-dialog'],
|
|
items: [{
|
|
type: 'textarea',
|
|
name: 'textarea',
|
|
inputMode: 'text',
|
|
maximized: true
|
|
}]
|
|
},
|
|
size: 'large',
|
|
buttons: [{
|
|
type: 'cancel',
|
|
name: 'cancel',
|
|
text: 'Cancel'
|
|
}, {
|
|
type: 'submit',
|
|
name: 'save',
|
|
text: 'Save',
|
|
buttonType: 'primary'
|
|
}],
|
|
onSubmit: dialogApi => {
|
|
setContent(cmEditor.state.doc.toString());
|
|
dialogApi.close();
|
|
},
|
|
onClose: () => {
|
|
cmEditor.destroy();
|
|
cmEditor = null;
|
|
running = false;
|
|
}
|
|
};
|
|
|
|
// Import codemirror and open the dialog
|
|
// eslint-disable-next-line import/no-unresolved
|
|
Promise.all([import('codemirror'), import('@codemirror/view'), import('@codemirror/commands')]).then(([{
|
|
createFromTextarea
|
|
}, {
|
|
keymap
|
|
}, {
|
|
indentMore
|
|
}]) => {
|
|
editor.windowManager.open(dialogConfig);
|
|
|
|
// Find textarea and move it to shadow DOM to isolate from TinyMCE styling
|
|
const textarea = document.querySelector('.joomla-highlighter-dialog textarea');
|
|
const wrapper = textarea.parentElement;
|
|
const shadow = wrapper.attachShadow({
|
|
mode: 'open'
|
|
});
|
|
textarea.value = getContent();
|
|
shadow.appendChild(textarea);
|
|
|
|
// Move focus out of the codemirror
|
|
const escapeTabTrap = (view, event) => {
|
|
event.preventDefault();
|
|
// Find a Save button
|
|
const dialogEl = wrapper.closest('[role="dialog"]');
|
|
const btnEl = dialogEl.querySelector('.tox-dialog__footer [type="button"]:not(.tox-button--secondary)');
|
|
if (btnEl) {
|
|
btnEl.focus();
|
|
} else {
|
|
dialogEl.focus();
|
|
}
|
|
};
|
|
const cmOptions = {
|
|
mode: 'html',
|
|
lineNumbers: true,
|
|
lineWrapping: true,
|
|
activeLine: true,
|
|
highlightSelection: true,
|
|
foldGutter: true,
|
|
width: '100%',
|
|
height: '100%',
|
|
root: shadow,
|
|
customExtensions: [
|
|
// Enable Tab trapping
|
|
() => keymap.of([{
|
|
key: 'Tab',
|
|
run: indentMore,
|
|
shift: escapeTabTrap
|
|
}])]
|
|
};
|
|
const wrapperheight = wrapper.scrollHeight;
|
|
createFromTextarea(textarea, cmOptions).then(cmView => {
|
|
cmEditor = cmView;
|
|
cmEditor.focus();
|
|
cmEditor.dom.style.maxHeight = `${wrapperheight}px`;
|
|
});
|
|
});
|
|
};
|
|
editor.ui.registry.addButton('code', {
|
|
icon: 'sourcecode',
|
|
title: 'Source code+',
|
|
tooltip: 'Source code+',
|
|
onAction: showSourceEditor
|
|
});
|
|
editor.ui.registry.addMenuItem('code', {
|
|
icon: 'sourcecode',
|
|
text: 'Source code+',
|
|
onAction: showSourceEditor,
|
|
context: 'tools'
|
|
});
|
|
editor.addShortcut('Alt+U', 'Opens the code editor', showSourceEditor);
|
|
return {
|
|
getMetadata: () => ({
|
|
name: 'Source Code Editor (Joomla)',
|
|
url: 'https://www.joomla.org/'
|
|
})
|
|
};
|
|
});
|