import {register as registerShortcuts} from "./shortcuts";
import {listen as listenForCommonEvents} from "./common-events";
-import {scrollToQueryString, fixScrollForMobile} from "./scrolling";
+import {scrollToQueryString} from "./scrolling";
import {listenForDragAndPaste} from "./drop-paste-handling";
+import {getPrimaryToolbar, registerAdditionalToolbars} from "./toolbars";
import {getPlugin as getCodeeditorPlugin} from "./plugin-codeeditor";
import {getPlugin as getDrawioPlugin} from "./plugin-drawio";
import {getPlugin as getCustomhrPlugin} from "./plugins-customhr";
import {getPlugin as getImagemanagerPlugin} from "./plugins-imagemanager";
import {getPlugin as getAboutPlugin} from "./plugins-about";
+import {getPlugin as getDetailsPlugin} from "./plugins-details";
const style_formats = [
{title: "Large Header", format: "h2", preview: 'color: blue;'},
];
const formats = {
- codeeditor: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div'},
alignleft: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-left'},
aligncenter: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-center'},
alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-right'},
}
-/**
- * @param {WysiwygConfigOptions} options
- * @return {{toolbar: string, groupButtons: Object<string, Object>}}
- */
-function buildToolbar(options) {
- const textDirPlugins = options.textDirection === 'rtl' ? 'ltr rtl' : '';
-
- const groupButtons = {
- formatoverflow: {
- icon: 'more-drawer',
- tooltip: 'More',
- items: 'strikethrough superscript subscript inlinecode removeformat'
- },
- listoverflow: {
- icon: 'more-drawer',
- tooltip: 'More',
- items: 'outdent indent'
- },
- insertoverflow: {
- icon: 'more-drawer',
- tooltip: 'More',
- items: 'hr codeeditor drawio media'
- }
- };
-
- const toolbar = [
- 'undo redo',
- 'styleselect',
- 'bold italic underline formatoverflow',
- 'forecolor backcolor',
- 'alignleft aligncenter alignright alignjustify',
- 'bullist numlist listoverflow',
- textDirPlugins,
- 'link table imagemanager-insert insertoverflow',
- 'code about fullscreen'
- ];
-
- return {
- toolbar: toolbar.filter(row => Boolean(row)).join(' | '),
- groupButtons,
- };
-}
-
/**
* @param {WysiwygConfigOptions} options
* @return {string}
"media",
"imagemanager",
"about",
+ "details",
options.textDirection === 'rtl' ? 'directionality' : '',
];
window.tinymce.PluginManager.add('customhr', getCustomhrPlugin(options));
window.tinymce.PluginManager.add('imagemanager', getImagemanagerPlugin(options));
window.tinymce.PluginManager.add('about', getAboutPlugin(options));
+ window.tinymce.PluginManager.add('details', getDetailsPlugin(options));
if (options.drawioUrl) {
window.tinymce.PluginManager.add('drawio', getDrawioPlugin(options));
}
/**
- * Load custom HTML head content from the settings into the editor.
- * TODO: We should be able to get this from current parent page?
- * @param {Editor} editor
+ * Fetch custom HTML head content from the parent page head into the editor.
*/
-function loadCustomHeadContent(editor) {
- window.$http.get(window.baseUrl('/custom-head-content')).then(resp => {
- if (!resp.data) return;
- let head = editor.getDoc().querySelector('head');
- head.innerHTML += resp.data;
- });
+function fetchCustomHeadContent() {
+ const headContentLines = document.head.innerHTML.split("\n");
+ const startLineIndex = headContentLines.findIndex(line => line.trim() === '<!-- Start: custom user content -->');
+ const endLineIndex = headContentLines.findIndex(line => line.trim() === '<!-- End: custom user content -->');
+ if (startLineIndex === -1 || endLineIndex === -1) {
+ return ''
+ }
+ return headContentLines.slice(startLineIndex + 1, endLineIndex).join('\n');
}
/**
editor.on('init', () => {
editorChange();
scrollToQueryString(editor);
- fixScrollForMobile(editor);
window.editor = editor;
});
window.$events.emit('editor-html-change', content);
}
- // TODO - Update to standardise across both editors
- // Use events within listenForBookStackEditorEvents instead (Different event signature)
- window.$events.listen('editor-html-update', html => {
- editor.setContent(html);
- editor.selection.select(editor.getBody(), true);
- editor.selection.collapse(false);
- editorChange(html);
- });
-
// Custom handler hook
window.$events.emitPublic(options.containerElement, 'editor-tinymce::setup', {editor});
}
}
+/**
+ * @param {WysiwygConfigOptions} options
+ */
+function getContentStyle(options) {
+ return `
+html, body, html.dark-mode {
+ background: ${options.darkMode ? '#222' : '#fff'};
+}
+body {
+ padding-left: 15px !important;
+ padding-right: 15px !important;
+ height: initial !important;
+ margin:0!important;
+ margin-left: auto! important;
+ margin-right: auto !important;
+ overflow-y: hidden !important;
+}`.trim().replace('\n', '');
+}
+
/**
* @param {WysiwygConfigOptions} options
* @return {Object}
// Set language
window.tinymce.addI18n(options.language, options.translationMap);
- const {toolbar, groupButtons: toolBarGroupButtons} = buildToolbar(options);
-
// Return config object
return {
width: '100%',
statusbar: false,
menubar: false,
paste_data_images: false,
- extended_valid_elements: 'pre[*],svg[*],div[drawio-diagram]',
+ extended_valid_elements: 'pre[*],svg[*],div[drawio-diagram],details[*],summary[*],div[*]',
automatic_uploads: false,
- valid_children: "-div[p|h1|h2|h3|h4|h5|h6|blockquote],+div[pre],+div[img]",
+ custom_elements: 'doc-root,code-block',
+ valid_children: [
+ "-div[p|h1|h2|h3|h4|h5|h6|blockquote|code-block]",
+ "+div[pre|img]",
+ "-doc-root[doc-root|#text]",
+ "-li[details]",
+ "+code-block[pre]",
+ "+doc-root[code-block]"
+ ].join(','),
plugins: gatherPlugins(options),
imagetools_toolbar: 'imageoptions',
contextmenu: false,
- toolbar: toolbar,
- content_style: `html, body, html.dark-mode {background: ${options.darkMode ? '#222' : '#fff'};} body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}`,
+ toolbar: getPrimaryToolbar(options),
+ content_style: getContentStyle(options),
style_formats,
style_formats_merge: false,
media_alt_source: false,
file_picker_types: 'file image',
file_picker_callback,
paste_preprocess(plugin, args) {
- let content = args.content;
+ const content = args.content;
if (content.indexOf('<img src="file://') !== -1) {
args.content = '';
}
},
init_instance_callback(editor) {
- loadCustomHeadContent(editor);
+ const head = editor.getDoc().querySelector('head');
+ head.innerHTML += fetchCustomHeadContent();
},
setup(editor) {
- for (const [key, config] of Object.entries(toolBarGroupButtons)) {
- editor.ui.registry.addGroupToolbarButton(key, config);
- }
+ registerAdditionalToolbars(editor, options);
getSetupCallback(options)(editor);
},
};