From 5a53c1a7cc0319de50c882e5b37b32c9707bd346 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:08:08 +0200 Subject: [PATCH 01/11] feat: add a `config` object to the tinyMcePlugin model to accomodate configuration upfront --- .../models/tinymce-plugin.model.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/tinymce-plugin.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/tinymce-plugin.model.ts index 61a686ca0c..77c997ae44 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/tinymce-plugin.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/tinymce-plugin.model.ts @@ -1,5 +1,6 @@ import type { UmbTinyMcePluginBase } from '@umbraco-cms/backoffice/tiny-mce'; import type { ManifestApi } from '@umbraco-cms/backoffice/extension-api'; +import type { RawEditorOptions } from '@umbraco-cms/backoffice/external/tinymce'; export interface MetaTinyMcePlugin { /** @@ -26,6 +27,20 @@ export interface MetaTinyMcePlugin { */ icon?: string; }>; + + /** + * Sets the default configuration for the TinyMCE editor. This configuration will be used when the editor is initialized. + * + * @see [TinyMCE Configuration](https://www.tiny.cloud/docs/configure/) for more information. + * @optional + * @examples [ + * { + * "plugins": "wordcount", + * "statusbar": true + * } + * ] + */ + config?: RawEditorOptions; } /** From f4ebd1b87264177fbbe6ea040d59e64da677f172 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:08:14 +0200 Subject: [PATCH 02/11] chore: mock data --- .../src/mocks/handlers/manifests.handlers.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts index b8a500f4bb..1b210c543d 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts @@ -45,6 +45,18 @@ const privateManifests: PackageManifestResponse = [ propertyEditorSchema: 'Umbraco.TextBox', }, }, + { + type: 'tinyMcePlugin', + alias: 'My.TinyMcePlugin.Custom', + name: 'My Custom TinyMce Plugin', + js: '/App_Plugins/tinyMcePlugin.js', + meta: { + config: { + plugins: 'wordcount', + statusbar: true, + }, + }, + }, ], }, { From 82c2a80229b833fd986dcbc1dddef3939c78dd85 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:08:21 +0200 Subject: [PATCH 03/11] chore: mockdata --- .../public-assets/App_Plugins/tinyMcePlugin.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/public-assets/App_Plugins/tinyMcePlugin.js diff --git a/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/tinyMcePlugin.js b/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/tinyMcePlugin.js new file mode 100644 index 0000000000..8f65e6ed23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/tinyMcePlugin.js @@ -0,0 +1,9 @@ +export default class UmbTinyMceMockPlugin { + /** + * @param {TinyMcePluginArguments} args + */ + constructor(host, args) { + // Add your plugin code here + console.log('editor initialized', args) + } +} From 9ae442dccca86e69b16c80149cb8e67b482d40b5 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:10:31 +0200 Subject: [PATCH 04/11] fix: avoid setting the tiny config as a lit state --- .../input-tiny-mce/input-tiny-mce.element.ts | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts index 8e12f17c43..95dc06911f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts @@ -53,10 +53,6 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' @property({ attribute: false }) configuration?: UmbPropertyEditorConfigCollection; - @state() - private _tinyConfig: RawEditorOptions = {}; - - #plugins: Array UmbTinyMcePluginBase> = []; #editorRef?: Editor | null = null; #stylesheetRepository = new UmbStylesheetDetailRepository(this); #umbStylesheetRuleManager = new UmbStylesheetRuleManager(); @@ -230,7 +226,7 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' } // set the default values that will not be modified via configuration - this._tinyConfig = { + const config: RawEditorOptions = { autoresize_bottom_margin: 10, body_class: 'umb-rte', contextMenu: false, @@ -249,13 +245,13 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' ...configurationOptions, }; - this.#setLanguage(); + config.language = this.#getLanguage(); if (this.#editorRef) { this.#editorRef.destroy(); } - const editors = await renderEditor(this._tinyConfig).catch((error) => { + const editors = await renderEditor(config).catch((error) => { console.error('Failed to render TinyMCE', error); return []; }); @@ -263,8 +259,9 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' } /** - * Sets the language to use for TinyMCE */ - #setLanguage() { + * Gets the language to use for TinyMCE + **/ + #getLanguage() { const localeId = this.localize.lang(); //try matching the language using full locale format let languageMatch = availableLanguages.find((x) => localeId?.localeCompare(x) === 0); @@ -277,10 +274,7 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' } } - // only set if language exists, will fall back to tiny default - if (languageMatch) { - this._tinyConfig.language = languageMatch; - } + return languageMatch; } #editorSetup(editor: Editor) { From f0491384b96d3793349add372bc8ad8d4dfe83ed Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:11:23 +0200 Subject: [PATCH 05/11] fix: combine two `onInit` events --- .../components/input-tiny-mce/input-tiny-mce.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts index 95dc06911f..e03120cdcf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts @@ -330,13 +330,14 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' } }); }); - editor.on('init', () => editor.setContent(this.value?.toString() ?? '')); + } #onInit(editor: Editor) { //enable browser based spell checking editor.getBody().setAttribute('spellcheck', 'true'); uriAttributeSanitizer(editor); + editor.setContent(this.value?.toString() ?? ''); } #onChange(value: string) { From 4f9de15fbd8f61c08142f98c29db0b9ba908f14f Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:11:59 +0200 Subject: [PATCH 06/11] fix: find plugins up front and merge their manifest config to initialize tinyMce, then later on initialize the plugin APIs --- .../input-tiny-mce/input-tiny-mce.element.ts | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts index e03120cdcf..0ca4e01800 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts @@ -2,12 +2,11 @@ import { availableLanguages } from './input-tiny-mce.languages.js'; import { defaultFallbackConfig } from './input-tiny-mce.defaults.js'; import { pastePreProcessHandler } from './input-tiny-mce.handlers.js'; import { uriAttributeSanitizer } from './input-tiny-mce.sanitizer.js'; -import type { TinyMcePluginArguments, UmbTinyMcePluginBase } from './tiny-mce-plugin.js'; -import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api'; -import { css, customElement, html, property, query, state } from '@umbraco-cms/backoffice/external/lit'; -import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; +import type { UmbTinyMcePluginBase } from './tiny-mce-plugin.js'; +import { type ClassConstructor, loadManifestApi } from '@umbraco-cms/backoffice/extension-api'; +import { css, customElement, html, property, query } from '@umbraco-cms/backoffice/external/lit'; import { getProcessedImageUrl } from '@umbraco-cms/backoffice/utils'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { type ManifestTinyMcePlugin, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbStylesheetDetailRepository, UmbStylesheetRuleManager } from '@umbraco-cms/backoffice/stylesheet'; @@ -81,15 +80,32 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' return this.#editorRef; } - protected async firstUpdated(): Promise { - await Promise.all([...(await this.#loadPlugins())]); - await this.#setTinyConfig(); + constructor() { + super(); + + this.#loadEditor(); + } + + #plugins: Promise | undefined>[] = []; + async #loadEditor() { + this.observe(umbExtensionsRegistry.byType('tinyMcePlugin'), (manifests) => { + this.#plugins.length = 0; + this.#plugins = this.#loadPlugins(manifests); + + let config: RawEditorOptions = {}; + manifests.forEach((manifest) => { + if (manifest.meta?.config) { + // TODO: Deep merge config + config = { ...config, ...manifest.meta.config }; + } + }); + this.#setTinyConfig(config); + }); } disconnectedCallback() { super.disconnectedCallback(); - // TODO: Test if there is any problems with destroying the RTE here, but not initializing on connectedCallback. (firstUpdated is only called first time the element is rendered, not when it is reconnected) this.#editorRef?.destroy(); } @@ -99,29 +115,14 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' * setup method, the asynchronous nature means the editor is loaded before * the plugins are ready and so are not associated with the editor. */ - async #loadPlugins() { - const observable = umbExtensionsRegistry?.byType('tinyMcePlugin'); - const manifests = await firstValueFrom(observable); - + #loadPlugins(manifests: Array) { const promises = []; for (const manifest of manifests) { if (manifest.js) { - promises.push( - loadManifestApi(manifest.js).then((plugin) => { - if (plugin) { - this.#plugins.push(plugin); - } - }), - ); + promises.push(loadManifestApi(manifest.js)); } if (manifest.api) { - promises.push( - loadManifestApi(manifest.api).then((plugin) => { - if (plugin) { - this.#plugins.push(plugin); - } - }), - ); + promises.push(loadManifestApi(manifest.api)); } } return promises; @@ -177,7 +178,7 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' return formatStyles; } - async #setTinyConfig() { + async #setTinyConfig(additionalConfig?: RawEditorOptions) { const dimensions = this.configuration?.getValueByAlias<{ width?: number; height?: number }>('dimensions'); const stylesheetPaths = this.configuration?.getValueByAlias('stylesheets') ?? []; @@ -243,6 +244,9 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' // Extend with configuration options ...configurationOptions, + + // Extend with additional configuration options + ...additionalConfig, }; config.language = this.#getLanguage(); @@ -277,17 +281,9 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' return languageMatch; } - #editorSetup(editor: Editor) { + async #editorSetup(editor: Editor) { editor.suffix = '.min'; - // instantiate plugins - these are already loaded in this.#loadPlugins - // to ensure they are available before setting up the editor. - // Plugins require a reference to the current editor as a param, so can not - // be instantiated until we have an editor - for (const plugin of this.#plugins) { - new plugin({ host: this, editor }); - } - // define keyboard shortcuts editor.addShortcut('Ctrl+S', '', () => this.dispatchEvent(new CustomEvent('rte.shortcut.save', { composed: true, bubbles: true })), @@ -331,6 +327,18 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' }); }); + // instantiate plugins + // to ensure they are available before setting up the editor. + // Plugins require a reference to the current editor as a param, so can not + // be instantiated until we have an editor + this.#plugins.forEach(async (plugin) => { + const pluginConstructor = await plugin; + if (pluginConstructor) { + // [v15]: This might be improved by changing to `createExtensionApi` and avoiding the `#loadPlugins` method altogether, but that would require a breaking change + // because that function sends the UmbControllerHost as the first argument, which is not the case here. + new pluginConstructor({ host: this, editor }); + } + }); } #onInit(editor: Editor) { From a029f2bd2ea8e3487705b953cc86684918586509 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:13:00 +0200 Subject: [PATCH 07/11] chore: mock data --- .../public-assets/App_Plugins/tinyMcePlugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/tinyMcePlugin.js b/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/tinyMcePlugin.js index 8f65e6ed23..f7a4a549b1 100644 --- a/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/tinyMcePlugin.js +++ b/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/tinyMcePlugin.js @@ -2,7 +2,7 @@ export default class UmbTinyMceMockPlugin { /** * @param {TinyMcePluginArguments} args */ - constructor(host, args) { + constructor(args) { // Add your plugin code here console.log('editor initialized', args) } From eeae753df81afcd583cec5f7b4b235dab7f35b6a Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:31:00 +0200 Subject: [PATCH 08/11] chore: mock --- .../src/mocks/handlers/manifests.handlers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts index 1b210c543d..6233357ed6 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts @@ -52,7 +52,7 @@ const privateManifests: PackageManifestResponse = [ js: '/App_Plugins/tinyMcePlugin.js', meta: { config: { - plugins: 'wordcount', + plugins: ['wordcount'], statusbar: true, }, }, From 410bf45d5d6d9529279ef41ed1e4c494e01e90a8 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:31:15 +0200 Subject: [PATCH 09/11] fix: load plugins up front --- .../input-tiny-mce/input-tiny-mce.element.ts | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts index 0ca4e01800..8c5964662a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts @@ -52,6 +52,7 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' @property({ attribute: false }) configuration?: UmbPropertyEditorConfigCollection; + #plugins: Array | undefined> = []; #editorRef?: Editor | null = null; #stylesheetRepository = new UmbStylesheetDetailRepository(this); #umbStylesheetRuleManager = new UmbStylesheetRuleManager(); @@ -86,11 +87,10 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' this.#loadEditor(); } - #plugins: Promise | undefined>[] = []; async #loadEditor() { - this.observe(umbExtensionsRegistry.byType('tinyMcePlugin'), (manifests) => { + this.observe(umbExtensionsRegistry.byType('tinyMcePlugin'), async (manifests) => { this.#plugins.length = 0; - this.#plugins = this.#loadPlugins(manifests); + this.#plugins = await this.#loadPlugins(manifests); let config: RawEditorOptions = {}; manifests.forEach((manifest) => { @@ -115,14 +115,14 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' * setup method, the asynchronous nature means the editor is loaded before * the plugins are ready and so are not associated with the editor. */ - #loadPlugins(manifests: Array) { + async #loadPlugins(manifests: Array) { const promises = []; for (const manifest of manifests) { if (manifest.js) { - promises.push(loadManifestApi(manifest.js)); + promises.push(await loadManifestApi(manifest.js)); } if (manifest.api) { - promises.push(loadManifestApi(manifest.api)); + promises.push(await loadManifestApi(manifest.api)); } } return promises; @@ -241,19 +241,18 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' setup: (editor) => this.#editorSetup(editor), target: this._editorElement, paste_data_images: false, + language: this.#getLanguage(), // Extend with configuration options ...configurationOptions, // Extend with additional configuration options - ...additionalConfig, + //...additionalConfig, // TODO: Deep merge }; - config.language = this.#getLanguage(); + console.log('tried to set config', additionalConfig); - if (this.#editorRef) { - this.#editorRef.destroy(); - } + this.#editorRef?.destroy(); const editors = await renderEditor(config).catch((error) => { console.error('Failed to render TinyMCE', error); @@ -281,7 +280,7 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' return languageMatch; } - async #editorSetup(editor: Editor) { + #editorSetup(editor: Editor) { editor.suffix = '.min'; // define keyboard shortcuts @@ -327,18 +326,16 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' }); }); - // instantiate plugins - // to ensure they are available before setting up the editor. + // instantiate plugins to ensure they are available before setting up the editor. // Plugins require a reference to the current editor as a param, so can not // be instantiated until we have an editor - this.#plugins.forEach(async (plugin) => { - const pluginConstructor = await plugin; - if (pluginConstructor) { + for (const plugin of this.#plugins) { + if (plugin) { // [v15]: This might be improved by changing to `createExtensionApi` and avoiding the `#loadPlugins` method altogether, but that would require a breaking change // because that function sends the UmbControllerHost as the first argument, which is not the case here. - new pluginConstructor({ host: this, editor }); + new plugin({ host: this, editor }); } - }); + } } #onInit(editor: Editor) { From b03ea6bf2c6a9a3bee903bf2e34a524cd684dcde Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:43:05 +0200 Subject: [PATCH 10/11] fix: use `umbDeepMerge` to merge config coming in twice over in order not to overwrite --- .../input-tiny-mce/input-tiny-mce.element.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts index 8c5964662a..650aacc0f6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts @@ -5,7 +5,7 @@ import { uriAttributeSanitizer } from './input-tiny-mce.sanitizer.js'; import type { UmbTinyMcePluginBase } from './tiny-mce-plugin.js'; import { type ClassConstructor, loadManifestApi } from '@umbraco-cms/backoffice/extension-api'; import { css, customElement, html, property, query } from '@umbraco-cms/backoffice/external/lit'; -import { getProcessedImageUrl } from '@umbraco-cms/backoffice/utils'; +import { getProcessedImageUrl, umbDeepMerge } from '@umbraco-cms/backoffice/utils'; import { type ManifestTinyMcePlugin, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @@ -95,10 +95,10 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' let config: RawEditorOptions = {}; manifests.forEach((manifest) => { if (manifest.meta?.config) { - // TODO: Deep merge config - config = { ...config, ...manifest.meta.config }; + config = umbDeepMerge(manifest.meta.config, config); } }); + this.#setTinyConfig(config); }); } @@ -227,7 +227,7 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' } // set the default values that will not be modified via configuration - const config: RawEditorOptions = { + let config: RawEditorOptions = { autoresize_bottom_margin: 10, body_class: 'umb-rte', contextMenu: false, @@ -245,12 +245,12 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' // Extend with configuration options ...configurationOptions, - - // Extend with additional configuration options - //...additionalConfig, // TODO: Deep merge }; - console.log('tried to set config', additionalConfig); + // Extend with additional configuration options + if (additionalConfig) { + config = umbDeepMerge(additionalConfig, config); + } this.#editorRef?.destroy(); From 59372acc5679c47a4593cbe0962bca0bd3ff4d06 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 4 Jun 2024 09:13:54 +0200 Subject: [PATCH 11/11] chore: turn off tinymce promotions --- .../tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts index 650aacc0f6..c6b4f13c08 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.element.ts @@ -242,6 +242,7 @@ export class UmbInputTinyMceElement extends UUIFormControlMixin(UmbLitElement, ' target: this._editorElement, paste_data_images: false, language: this.#getLanguage(), + promotion: false, // Extend with configuration options ...configurationOptions,