<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <title>Liferay 7: Adding external plugins to CKEditor</title>
  <link rel="self" href="https://liferay.dev/c/message_boards/find_thread?p_l_id=119785294&amp;threadId=104295451" />
  <subtitle>Liferay 7: Adding external plugins to CKEditor</subtitle>
  <id>https://liferay.dev/c/message_boards/find_thread?p_l_id=119785294&amp;threadId=104295451</id>
  <updated>2026-04-04T20:17:47Z</updated>
  <dc:date>2026-04-04T20:17:47Z</dc:date>
  <entry>
    <title>RE: Liferay 7: Adding external plugins to CKEditor</title>
    <link rel="alternate" href="https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=112353233" />
    <author>
      <name>Sébastien Nadeau</name>
    </author>
    <id>https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=112353233</id>
    <updated>2019-02-14T17:38:53Z</updated>
    <published>2019-02-14T17:38:53Z</published>
    <summary type="html">&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;Hi,&lt;br&gt;&lt;br&gt;I'm trying to add the htmlbuttons plugin (&lt;a href="https://ckeditor.com/cke4/addon/htmlbuttons"&gt;https://ckeditor.com/cke4/addon/htmlbuttons&lt;/a&gt;) to ckeditor in my Liferay 7.1.2 GA3 instance, like this:&lt;br&gt;&lt;br&gt;&lt;pre&gt;&lt;code&gt;@Component(immediate = true, service = DynamicInclude.class)
public class RvmCKEditorDynamicInclude implements DynamicInclude {

&amp;amp;nbsp; @Override
&amp;amp;nbsp; public void include(HttpServletRequest request, HttpServletResponse response, String pKey) throws IOException {
&amp;amp;nbsp; &amp;amp;nbsp; Bundle bundle = _bundleContext.getBundle();
&amp;amp;nbsp; &amp;amp;nbsp; URL entryURL = bundle.getEntry("/META-INF/resources/ckeditor/plugins/htmlbuttons/plugin.js");
&amp;amp;nbsp; &amp;amp;nbsp; StreamUtil.transfer(entryURL.openStream(), response.getOutputStream(), false);
&amp;amp;nbsp; }

&amp;amp;nbsp; @Override
&amp;amp;nbsp; public void register(DynamicIncludeRegistry dynamicIncludeRegistry) {
&amp;amp;nbsp; &amp;amp;nbsp; dynamicIncludeRegistry.register("com.liferay.frontend.editor.ckeditor.web#ckeditor#additionalResources");
&amp;amp;nbsp; }

&amp;amp;nbsp; @Activate
&amp;amp;nbsp; protected void activate(BundleContext bundleContext) {
&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;_bundleContext = bundleContext;
&amp;amp;nbsp; }

&amp;amp;nbsp; private BundleContext _bundleContext;
}

&lt;/code&gt;&lt;/pre&gt;​​​​​​​However, I get this bizarre behavior when I try to edit a web content:&lt;br&gt;&lt;br&gt;&lt;img src="/documents/14/110203813/ckeditor_htmlbuttons_plugin.png/8b8a2a71-ff2e-037f-1a18-183b5af24d2c?t=1550165671781"&gt;&lt;br&gt;&lt;br&gt;As you can see, the plugin is not added correctly to Liferay's ckeditor, it is loaded along with the content of the Web Content Editor portlet. Anyone knows what I am missing?&lt;br&gt;&lt;br&gt;Thank you!&lt;br&gt;​​​​​​​&lt;/body&gt;&lt;/html&gt;</summary>
    <dc:creator>Sébastien Nadeau</dc:creator>
    <dc:date>2019-02-14T17:38:53Z</dc:date>
  </entry>
  <entry>
    <title>RE: Liferay 7: Adding external plugins to CKEditor</title>
    <link rel="alternate" href="https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=112014880" />
    <author>
      <name>Tim Telcik</name>
    </author>
    <id>https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=112014880</id>
    <updated>2019-01-15T10:55:34Z</updated>
    <published>2019-01-15T10:55:34Z</published>
    <summary type="html">&lt;p&gt;Hello Zsombor,&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;maybe I can help umbump the static image loading issue you reported.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Discussions and sample solutions for using static images in OSGi
  modules are available at:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;a
      href="https://itsliferay.blogspot.com/2017/03/include-static-resources-liferaydxp.html"&gt;How
      to include static resources (CSS/JS/Images) in Liferay OSGI module&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;a
      href="https://community.liferay.com/fr/forums/-/message_boards/message/103213792"&gt;liferay
      7 module add static image&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;However, you still need to patch the ckeditor youtube plugin config
  to work around a limitation in Liferay OSGi static image servlet proxy.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The default image resource path is relative to the Liferay Portal 7.x
  &amp;quot;frontend-editor-ckeditor-web&amp;quot; module, which is incorrect.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Hence, update the youtube plugin script (plugin.js) with this snippet
  (or equivalent) :&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;
            editor.ui.addButton('Youtube', {
                label : editor.lang.youtube.button,
                toolbar : 'insert',
                command : 'youtube',
                //icon : this.path + 'images/icon.png'
                icon : '/o/YOUR-LIFERAY-PORTAL-OSGI-MODULE-NAME/ckeditor/plugins/youtube/' + 'images/icon.png'
            });&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;This approach is working for me.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;I would prefer the Liferay Portal 7.x
  &amp;quot;frontend-editor-ckeditor-web&amp;quot; module to behave in a more
  consistent manner which honours the static image path of the ckeditor
  extension module.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Let me know if this helps.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Regards,&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Tim&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</summary>
    <dc:creator>Tim Telcik</dc:creator>
    <dc:date>2019-01-15T10:55:34Z</dc:date>
  </entry>
  <entry>
    <title>RE: Liferay 7: Adding external plugins to CKEditor</title>
    <link rel="alternate" href="https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=110668237" />
    <author>
      <name>Antonio Musarra</name>
    </author>
    <id>https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=110668237</id>
    <updated>2018-08-03T22:35:21Z</updated>
    <published>2018-08-03T22:35:21Z</published>
    <summary type="html">&lt;p&gt;Hi.&lt;/p&gt;
&lt;p&gt;You have resolved?&lt;/p&gt;
&lt;p&gt;You can share your project?&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Thanks&lt;/p&gt;</summary>
    <dc:creator>Antonio Musarra</dc:creator>
    <dc:date>2018-08-03T22:35:21Z</dc:date>
  </entry>
  <entry>
    <title>RE: Liferay 7: Adding external plugins to CKEditor</title>
    <link rel="alternate" href="https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=105639860" />
    <author>
      <name>Zsombor Nagy</name>
    </author>
    <id>https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=105639860</id>
    <updated>2018-03-21T13:58:10Z</updated>
    <published>2018-03-21T13:58:10Z</published>
    <summary type="html">Bump!&lt;br /&gt;No response for a month &lt;img alt="emoticon" src="@theme_images_path@/emoticons/sad.gif" &gt;&lt;br /&gt;Anyone, any help?</summary>
    <dc:creator>Zsombor Nagy</dc:creator>
    <dc:date>2018-03-21T13:58:10Z</dc:date>
  </entry>
  <entry>
    <title>Liferay 7: Adding external plugins to CKEditor</title>
    <link rel="alternate" href="https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=104295450" />
    <author>
      <name>Zsombor Nagy</name>
    </author>
    <id>https://liferay.dev/c/message_boards/find_message?p_l_id=119785294&amp;messageId=104295450</id>
    <updated>2018-02-21T06:44:26Z</updated>
    <published>2018-02-21T06:44:26Z</published>
    <summary type="html">&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;strong&gt;&lt;br&gt;&lt;span style="font-size: 18px;"&gt;EXAMPLE: adding YouTube plugin to CKEditor in Liferay 7&lt;/span&gt;&lt;br&gt;&lt;/strong&gt;&lt;br&gt;I created a &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;DynamicInclude&lt;/span&gt;&lt;/strong&gt; based module and an &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;EditorConfigContributorbased&lt;/span&gt;&lt;/strong&gt; based one according to the official tutorials: &lt;a href="https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/modifying-an-editors-configuration"&gt;Modifying an Editor’s Configuration&lt;/a&gt; and &lt;a href="https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/adding-new-behavior-to-an-editor"&gt;Adding New Behavior to an Editor&lt;/a&gt;&lt;br&gt;&lt;br&gt;In the &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;DynamicInclude&lt;/span&gt;&lt;/strong&gt; based module:&lt;br&gt;&lt;ul&gt;&lt;li&gt;I pasted the plugin files to src/main/resources/ckeditor/plugins/youtube/&lt;/li&gt;&lt;li&gt;In the component's &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;include&lt;/span&gt;&lt;/strong&gt; method I transferred each file to the &lt;span style="font-family: Courier New"&gt;&lt;strong&gt;respose &lt;/strong&gt;&lt;/span&gt;object the following way:&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code&gt;// CKEDIROT_PLUGINS_PATH = "/META-INF/resources/ckeditor/plugins/";

ClassLoader classLoader = DynamicIncludeTest.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(CKEDIROT_PLUGINS_PATH+"youtube/plugin.js");
StreamUtil.transfer(inputStream, response.getOutputStream(), false);

inputStream = classLoader.getResourceAsStream(CKEDIROT_PLUGINS_PATH+"youtube/lang/ar.js");
StreamUtil.transfer(inputStream, response.getOutputStream(), false);

inputStream = classLoader.getResourceAsStream(CKEDIROT_PLUGINS_PATH+"youtube/lang/cs.js");
StreamUtil.transfer(inputStream, response.getOutputStream(), false);
// ... the other language js files...&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;In the &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;EditorConfigContributor &lt;/span&gt;&lt;/strong&gt;based module's &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;populateConfigJSONObject&lt;/span&gt; &lt;/strong&gt;method:&lt;br&gt;&lt;ul&gt;&lt;li&gt;I appended &lt;strong&gt;&lt;em&gt;"youtube"&lt;/em&gt;&lt;/strong&gt; to the external plugins:&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code&gt;String extraPlugins = jsonObject.getString("extraPlugins");
extraPlugins = extraPlugins + ",youtube,";
jsonObject.put("extraPlugins", extraPlugins);&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;I inserted the button into toolbar:&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code&gt;JSONArray toolbarLiferay = jsonObject.getJSONArray("toolbar_liferay");
JSONArray newTools = JSONFactoryUtil.createJSONArray();
newTools.put("Youtube");
toolbarLiferay.put(newTools);&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;I deployed the two modules and have a fully functional Youtube plugin, with a small problem.&lt;br&gt;&lt;br&gt;&lt;strong&gt;&lt;span style="font-size: 18px;"&gt;PROBLEM: - The button won't have an icon&lt;/span&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;I cannot transfer the plugin's png icon in the &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;DynamicInclude&lt;/span&gt;&lt;/strong&gt; based module's &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;include &lt;/span&gt;&lt;/strong&gt;method, since a &lt;strong&gt;&lt;span style="font-family: Courier New"&gt;DynamicInclude &lt;/span&gt;&lt;/strong&gt;module...&lt;br&gt;&lt;blockquote&gt;...allows anyone to inject JavaScript code right after the editor instantiation to configure/change the editor.&lt;/blockquote&gt;&lt;br&gt;In my example if I try to pass the YouTube plugin's png icons, like...&lt;pre&gt;&lt;code&gt;inputStream = classLoader.getResourceAsStream(CKEDIROT_PLUGINS_PATH+"youtube/images/icon.png");
StreamUtil.transfer(inputStream, response.getOutputStream(), false);&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;... I'll just get parse errors:&lt;pre&gt;&lt;code&gt;ERROR [http-nio-8080-exec-1][GoogleJavaScriptMinifier:116] (http://localhost:8080/group/guest/~/control_panel/manage:1922): Parse error. illegal character
ERROR [http-nio-8080-exec-1][GoogleJavaScriptMinifier:116] (http://localhost:8080/group/guest/~/control_panel/manage:1922): Parse error. missing } after function body
ERROR [http-nio-8080-exec-1][GoogleJavaScriptMinifier:116] (http://localhost:8080/group/guest/~/control_panel/manage:1923): Parse error. illegal character
ERROR [http-nio-8080-exec-1][GoogleJavaScriptMinifier:116] (http://localhost:8080/group/guest/~/control_panel/manage:1923): Parse error. missing } after function body
ERROR [http-nio-8080-exec-1][GoogleJavaScriptMinifier:116] (http://localhost:8080/group/guest/~/control_panel/manage:1924): Parse error. illegal character
ERROR [http-nio-8080-exec-1][GoogleJavaScriptMinifier:116] (http://localhost:8080/group/guest/~/control_panel/manage:1924): Parse error. missing } after function body
ERROR [http-nio-8080-exec-1][GoogleJavaScriptMinifier:116] (http://localhost:8080/group/guest/~/control_panel/manage:1924): Parse error. illegal character
ERROR [http-nio-8080-exec-1][GoogleJavaScriptMinifier:129] {0} error(s), {1} warning(s)&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-size: 18px;"&gt;&lt;strong&gt;QUESTION&lt;/strong&gt;&lt;/span&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;How can I  pass a plugin's icons to be able to see it on it's respective button in CKEditor?&lt;/li&gt;&lt;li&gt;Is there a simpler approach to resolving this problem scenario?&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;strong&gt;&lt;span style="font-size: 24px;"&gt;Thank you for reading and assisting!&lt;/span&gt;&lt;/strong&gt;&lt;/body&gt;&lt;/html&gt;</summary>
    <dc:creator>Zsombor Nagy</dc:creator>
    <dc:date>2018-02-21T06:44:26Z</dc:date>
  </entry>
</feed>
