craftercms / craftercms

Parent project for Crafter CMS. Issue tracking across all repositories and global builds.
GNU General Public License v3.0
287 stars 98 forks source link

[studio-ui] Add ability to include TinyMCE plugins #4618

Closed rart closed 3 years ago

rart commented 3 years ago

Is your feature request related to a problem? Please describe. To add tinymce plugins, one needs to either add the plugin js to TinyMCE's plugin directory (i.e. edit studio source) or use tinymce's external_plugins option. This option is not published on Studio's TinyMCE config file, making it impossible to add plugins to tinymce without an overlay.

Describe the solution you'd like Publish the external_plugins config option so developers can create tinymce plugins or load external plugins.

<config>
    <setup>
        ...
        <toolbarItems2>my_button</toolbarItems2>
    <external_plugins>
        <my_button><![CDATA[/studio/1/plugin/file?siteId=mysite&type=tinymce&name=my_button&filename=plugin.min.js]]></my_button>
    </external_plugins>

ToDo

Describe alternatives you've considered Overlay, devs to create a custom form control to have full control of tinymce.

Additional context

rart commented 3 years ago

@jvega190 please add new config to blueprint samples. Please tick the box above and assign to vita when done.

rart commented 3 years ago

@jvega190 please this one for all of our in-house blueprints

<!--
You may create a TinyMCE plugins and serve them from your site via site plugins. For example, to add
a button to one of the toolbars:
1. Add your plugin to a toolbarItemsN (see above). 
  <toolbarItems2>my_button</toolbarItems2>
2. Tell TinyMCE where to load the plugin from via "external plugins" option
  <external_plugins>
    <my_button><![CDATA[/studio/1/plugin/file?siteId=mysite&type=tinymce&name=my_button&filename=plugin.min.js]]></my_button>
  </external_plugins>
-->

Remove the <toolbarItems2><!-- my_button --></toolbarItems2> comment, leaving that bit as it was.

jvega190 commented 3 years ago

@alhambrav note that the url is different for 3.1.x and 4.0.x, so in 3.1.x config would go like <my_button><![CDATA[/studio/api/2/plugin/file?siteId=hello&type=tinymce&name=example&filename=plugin.min.js]]></my_button> and in 4.0.x like: <my_button><![CDATA[/studio/1/plugin/file?siteId=mysite&type=tinymce&name=my_button&filename=plugin.min.js]]></my_button>

jvega190 commented 3 years ago

@rart configurations updated ^

alhambrav commented 3 years ago

PR https://github.com/craftercms/docs/pull/1204 and https://github.com/craftercms/docs/pull/1205

russdanner commented 3 years ago

Can we have a macro for SITEID that just uses the current Site ID?

rart commented 3 years ago

Ideally, the backend would be the one to process that macro as that's where it's centralised. There are quite a few places in the UI where the API is used in different ways plus third parties may also use it on their plugins too.

(The backend could do this via the crafter site cookie either when site arg is not sent and/or when site arg matches a special value we define such as {site})

sumerjabri commented 3 years ago

Can we have a macro for SITEID that just uses the current Site ID?

@russdanner Is this related to this ticket (TinyMCE) or the macro ticket?

@rart The backend doesn't carry state. That's the job of the API caller. We can discuss more on Slack.

russdanner commented 3 years ago

@sumerjabri The request is related to this ticket. The solution here hardcodes the Site ID in the URL to the external plugin.

russdanner commented 3 years ago

CONFIRMED in 3.1

Testing: Place the following file (add and commit it) in: /config/studio/plugins/tinymce/example/plugin.min.js


/*
  Note: We have included the plugin in the same JavaScript file as the TinyMCE
  instance for display purposes only. Tiny recommends not maintaining the plugin
  with the TinyMCE instance and using the `external_plugins` option.
*/
tinymce.PluginManager.add('example', function(editor, url) {
    var openDialog = function () {
        return editor.windowManager.open({
            title: 'Example plugin',
            body: {
                type: 'panel',
                items: [
                    {
                        type: 'input',
                        name: 'title',
                        label: 'Title'
                    }
                ]
            },
            buttons: [
                {
                    type: 'cancel',
                    text: 'Close'
                },
                {
                    type: 'submit',
                    text: 'Save',
                    primary: true
                }
            ],
            onSubmit: function (api) {
                var data = api.getData();
                /* Insert content when the window form is submitted */
                editor.insertContent('Title: ' + data.title);
                api.close();
            }
        });
    };
    /* Add a button that opens a window */
    editor.ui.registry.addButton('example', {
        text: 'My button',
        onAction: function () {
            /* Open window */
            openDialog();
        }
    });
    /* Adds a menu item, which can then be included in any menu via the menu/menubar configuration */
    editor.ui.registry.addMenuItem('example', {
        text: 'Example plugin',
        onAction: function() {
            /* Open window */
            openDialog();
        }
    });
    /* Return the metadata for the help plugin */
    return {
        getMetadata: function () {
            return  {
                name: 'Example plugin',
                url: 'http://exampleplugindocsurl.com'
            };
        }
    };
});

With the following tinymce5 config in 3.1.x The plugin url is different in 4.x

<config>
    <setup>
        <id>generic</id> <!-- This starts a profile configuration -->

        <rteStylesheets> <!-- This informs the RTE to use the CSS files -->
            <!-- <link>/static-assets/css/rte/rte.css</link> -->
        </rteStylesheets>

        <rteStyleOverride>
            body {
                <!-- styles -->
            }
        </rteStyleOverride>

        <plugins>
            print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template 
            codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists wordcount 
            textpattern help acecode
        </plugins>

 <external_plugins>
        <example><![CDATA[http://localhost:8080/studio/api/2/plugin/file?siteId=editorial&type=tinymce&name=example&filename=plugin.min.js]]></example>
    </external_plugins>

        <extendedElements></extendedElements>   <!-- elements whitelist (won't be stripped out) -->

        <toolbarItems1>
            example | formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat
        </toolbarItems1>
        <toolbarItems2> example</toolbarItems2>
        <toolbarItems3></toolbarItems3>
        <toolbarItems4></toolbarItems4>

        <codeEditorWrap>false</codeEditorWrap>
    </setup>
</config>

Open the a form that uses tinymce5 with this config and test that the button is in both places on the toolbar

sumerjabri commented 3 years ago

@rart to add the macro expansion to 3.1 and 4

rart commented 3 years ago

@russdanner macro done. Use {site} on URL for site id interpolation at runtime.

@jvega190 please update blueprints

@alhambrav please update docs

sumerjabri commented 3 years ago

@russdanner please validate and mark it but don't close it until we're done with BP and doc updates.

jvega190 commented 3 years ago

@sumerjabri @rart blueprints udpated

alhambrav commented 3 years ago

Update getPluginFile call to use {site} macro - PR https://github.com/craftercms/docs/pull/1220 and https://github.com/craftercms/docs/pull/1221

russdanner commented 3 years ago

Will retest

russdanner commented 3 years ago

Confirmed

russdanner commented 2 years ago

Moved this to 4.0.1 just to confirm. It's been merged for more than a year.