Adding 'codesample' to TinyMCE

Hi peeps, I want to include the codesample plugin for TinyMCE but I'm not sure where to start with the configuration. I had a look at the Plone control panel under the TinyMCE section and I see there's an option for including custom plugins with the plugin_name|location syntax, and a few different JSON configuration fields, but I'm a little confused.

The 'location' in the custom plugin field is supposed to be what..? The JavaScript dependency, some of TinyMCE resource?

Any help would be appreciated!

in previous version of Plone (up to 5.1.0), the syntax was something like

autolink|++plone++static/components/tinymce-builded/js/tinymce/plugins/autolink/plugin.js

this is working with Plone 5.1.2 btw, but that's an accident. It will not work with codesample.

I have looked at what is happening. I have managed to get codesample to work with Plone 5.1.2 that's proof that there is no inherent bug in codesample that is preventing it to work. FTR I looked at how working plugins where working (such as autolink): these plugins are included in the big javascript soup known as logged-in.js. So I included codesample (and also a little sample code I did) by:

  • creating resources with the Plone resource manager
  • patching the mockup pattern.js (could not find a way around patching)
  • regenerating the logged-in file with plone-compile-resources
    Then codesample worked - in this case the path does not matter in fact: it works fine with

codesample|blabla

that's only logical since the plugin is found by standard requirejs mechanism, not loaded explicitely. Autolink plugin works because it's loaded in mocked while codesample is not.

Now what has changed after 5.1.0 to block explicit loading of Tinymce plugins ? IMO not much has changed in Plone. The big change is in Tinymce itself, that was upgraded from 4.5.6 (Plone 5.1.0) to 4.7.6. This does not look like a big change, however it should be considered that Tinymce has undergone a total rewrite around the 4.7.3 (?) version to switch from plain old Js to Typescript (mostly: there are also 2 other langages used but Typescript is the most used) My guess is something has changed in Tinymce and Plone should change in some way to be able to load plugins directly. I will search in this direction at least now that I have ruled out codesample plugin itself.

2 Likes

Additional info on this.
The tinymce initialization has indeed quite changed from 4.5.6 to 4.7.6. Change from Javascript to Typescript may not has been a big issue (Typescript is widely compatible), but initialization has changed.
In fact I got an idea while reading 4.5.6 code; the init function was commented with the indication that it was supposed to be called automatically by Tinymce upon a call to 'rendered'. Searching on the net, all sample I have found initialize Tinymce the way Plone (mockup in fact) is doing it. However, all sample code I have found is old. The most recent one date from 2015 and is a Django code; AFAIK Django is still using Tinymce 3 to this day (from the Github project for integration of Tinymce in Django).
OTOH the sample code for Tinymce 4.7.6 is as follow (in /src/core/main/ts/api/Editor.ts):

 * // Creates a new editor instance
 * var ed = new tinymce.Editor('textareaid', {
 *     some_setting: 1
 * }, tinymce.EditorManager);

So, I tried to copy this code into Plone. More correctly, I hacked savagely plone-logged-in-compiled.js (that I had first regenerated in a un-uglified version by hacking Gruntfile.js and restarting plone-compile-resources)

--- plone-logged-in-compiled.js.ori	2018-06-03 19:46:28.456905685 +0000
+++ plone-logged-in-compiled.js	2018-06-07 23:21:54.768893388 +0000
@@ -67336,25 +67336,10 @@
           }
         }
 
-        tinymce.init(tinyOptions);
-        self.tiny = tinymce.get(self.tinyId);
 
-        if (self.tiny !== null){
-          self.tiny.initialized = true;
-        }
+        self.tiny = new tinymce.Editor(self.tinyId, tinyOptions, tinymce.EditorManager);
+        self.tiny.render();
 
-        /* tiny really should be doing this by default
-         * but this fixes overlays not saving data */
-        var $form = self.$el.parents('form');
-        $form.on('submit', function() {
-          if (self.options.inline === true) {
-            // save back from contenteditable to textarea
-            self.$el.val(self.tiny.getContent());
-          } else {
-            // normal case
-            self.tiny.save();
-          }
-        });
       });
     },
     destroy: function() {

this code is coming from mockup, of course. And it's necessary to regenerate logged-in.js (I guess that it could be possible to test this in Plone dev mode and avoid regenerate logged-in.js but when debugging Plone everything is so slow that I prefer to do all testing in Plone prod mode)

Result is mode interesting that my first try.
Codesample seem to work.
I guess that it could allow to use homegrown plugins in Plone 5.1.2+ too.

Now it needs more testing obviously.
But if other people are interested to test this change in other setups it could be interesting because while this is a small change it could have serious side effects.

1 Like

What I don't understand is why we have such a comprehensive TinyMCE configuration area in Plone but if we want to include a plugin we have to start regenerating compiled files..? This seems incredibly unintuitive for all intents and purposes that the settings try to make things easier. Is there not an easier way of handling this purely in the resource registry somehow..?

Maybe I was not clear enough, but for me having to jump through all these hoops is a bug, not a feature. Tinymce 4.7.6 was added to Plone without taking in account all the differences from previous versions. I was just suggesting a way that could lead to a possible fix. It did not raise any interest, Tinymce is not so important these days it seems.

I'm having this problem trying to port a plugin from Plone 5.0 to 5.1.2. I don't think it's even getting to my plugin.js; the problem seems to be with the mechanism for registering custom plugins in Plone's machinery.

What I tried:
I have a skins folder such that ${portal_url}/tinymce_latext/plugin.js is accessible. I know some of the API has changed in this version of TinyMCE so I am trying to just include a basically empty file as a starting point:

(function () {
    alert('hi');
})();

In TinyMCE Settings -> Plugins and Toolbars -> Custom Plugins I have: latex|tinymce_latex/plugin.js

I get the alert but the iframe fails to load with error "TypeError: e.getDoc(...) is undefined" Has anyone gotten this custom plugin section to work? I'd love to see a code example. This is currently a blocker on a couple of our sites moving to 5.1.

If you use this string:

latex|tinymce_latex/plugin.js

then the script should be placed in a path similar to this:

./eggs/Products.CMFPlone-5.x.x-py2.7.egg/Products/CMFPlone/static/components/tinymce-builded/js/tinymce/plugins/latex/plugin.js

However personally I do require keeping within a theme, so I use the following string:

latex|++theme++default/tinymce/plugins/latex/plugin.js

It works for me correctly in Plone version 5.1.6