Jakub Bryniarski
Jakub Bryniarski

Reputation: 1

How to correctly override CKEditor config in Liferay 7.4.3.102 CE GA102

I am new to liferay and currently trying to override config for CKEditor in JournalArticle to add buttons and then plugins.

I have created ConfigContributor and ConfigServletFilter to try override default configuration. Unfortunately both of them keep being overriden by something.

Contributor:

> import java.util.Locale;
> import java.util.Map;
> 
> import com.liferay.item.selector.ItemSelector;
> import com.liferay.item.selector.criteria.image.criterion.ImageItemSelectorCriterion;
> import com.liferay.item.selector.criteria.url.criterion.URLItemSelectorCriterion;
> 
> import com.liferay.portal.kernel.json.JSONArray;
> import com.liferay.portal.kernel.json.JSONFactoryUtil;
> import com.liferay.portal.kernel.json.JSONObject;
> import com.liferay.portal.kernel.json.JSONUtil;
> import com.liferay.portal.kernel.json.JSONFactory;
> import com.liferay.portal.kernel.util.GetterUtil;
> import org.osgi.service.component.annotations.Component;
> import com.liferay.portal.kernel.editor.configuration.BaseEditorConfigContributor;
> import com.liferay.portal.kernel.editor.configuration.EditorConfigContributor;
> import com.liferay.portal.kernel.portlet.RequestBackedPortletURLFactory;
> import com.liferay.portal.kernel.theme.ThemeDisplay;
> import com.liferay.portal.kernel.util.Validator;
> import org.osgi.service.component.annotations.Reference;
> 
> import javax.portlet.PortletURL;
> 
> @Component(
> property = {
>         "editor.name=ckeditor",
>         "javax.portlet.name=com_liferay_journal_web_portlet_JournalPortlet",
>         "service.ranking:Integer=" + Integer.MAX_VALUE
>     },
> service = EditorConfigContributor.class
> )
> public class CKEditorConfigContributor implements EditorConfigContributor {
> 
>   @Override
> public void populateConfigJSONObject(
> JSONObject jsonObject, Map<String, Object> inputEditorTaglibAttributes,
> ThemeDisplay themeDisplay, RequestBackedPortletURLFactory requestBackedPortletURLFactory) {
> 
> jsonObject.put(
>             "allowedContent",
>             "a[*](*); div[*](*); figcaption; figure; iframe[*](*); img[*](*){*}; li ol ul; " +
>                     "p[*](*){text-align}; col[span]; colgroup[span]; table[border, cellpadding, " +
>                     "cellspacing]{width}; tbody td[colspan, headers, rowspan]{*}; th[abbr, colspan, " +
>                     "headers, rowspan, scope, sorted]{*}; thead tr; source[*](*); video[*](*);"
>     ).put(
>             "stylesSet", getStyleFormatsJsonArray(themeDisplay.getLocale())
>     );
> 
> String namespace = GetterUtil.getString(
> inputEditorTaglibAttributes.get("liferay-ui:input-editor:namespace"));
> String name = GetterUtil.getString(
> inputEditorTaglibAttributes.get("liferay-ui:input-editor:name"));
> 
> populateFileBrowserURL(
> jsonObject, requestBackedPortletURLFactory, namespace + name + "selectItem");
> 
> Custom configuration
> jsonObject.put("customConfig", "/o/frontend-editor-ckeditor-web/ckeditor/config.js");
> 
> Additional toolbar and extraPlugins configuration
> String extraPlugins = jsonObject.getString("extraPlugins");
> 
> if (Validator.isNotNull(extraPlugins)) {
> extraPlugins = extraPlugins + ",clipboard";
> else {
> extraPlugins = "clipboard";
>     }
> 
> jsonObject.put("extraPlugins", extraPlugins);
> 
>     /*JSONArray toolbar = JSONFactoryUtil.createJSONArray();
> toolbar.put(JSONFactoryUtil.createJSONArray().put("Undo").put("Redo"));
> toolbar.put(JSONFactoryUtil.createJSONArray().put("Styles").put("Bold").put("Italic").put("Underline"));
> toolbar.put(JSONFactoryUtil.createJSONArray().put("NumberedList").put("BulletedList"));
> toolbar.put(JSONFactoryUtil.createJSONArray().put("Link").put("Unlink"));
> toolbar.put(JSONFactoryUtil.createJSONArray().put("Source").put("Expand"));
> 
> jsonObject.put("toolbar_simple", toolbar);*/
> 
> Log the configuration for debugging purposes
> jsonObject.put("toolbar", "custom");
> System.out.println("CKEditorConfigContributor: " + jsonObject.toString());
>   }
> 
> private JSONArray getStyleFormatsJsonArray(Locale locale) {
> return JSONUtil.putAll(
> getStyleFormatJsonObject("Normal", "p", null),
> getStyleFormatJsonObject("Heading 1", "h1", null),
> getStyleFormatJsonObject("Heading 2", "h2", null),
> getStyleFormatJsonObject("Heading 3", "h3", null),
> getStyleFormatJsonObject("Heading 4", "h4", null),
> getStyleFormatJsonObject("Preformatted Text", "pre", null),
> getStyleFormatJsonObject("Cited Work", "cite", null),
> getStyleFormatJsonObject("Computer Code", "code", null),
> getStyleFormatJsonObject("Info Message", "div",
>                     "overflow-auto portlet-msg-info"),
> getStyleFormatJsonObject("Alert Message", "div",
>                     "overflow-auto portlet-msg-alert"),
> getStyleFormatJsonObject("Error Message", "div",
>                     "overflow-auto portlet-msg-error")
>     );
>   }
> 
> private JSONObject getStyleFormatJsonObject(String styleFormatName, String element, String cssClass) {
> JSONObject styleJsonObject = jsonFactory.createJSONObject();
> 
> if (Validator.isNotNull(cssClass)) {
> JSONObject attributesJsonObject = JSONUtil.put("class", cssClass);
> styleJsonObject.put("attributes", attributesJsonObject);
>     }
> 
> styleJsonObject.put("element", element).put("name", styleFormatName);
> 
> return styleJsonObject;
>   }
> 
> private void populateFileBrowserURL(
> JSONObject jsonObject, RequestBackedPortletURLFactory requestBackedPortletURLFactory, String eventName) {
> 
> PortletURL itemSelectorURL = itemSelector.getItemSelectorURL(
> requestBackedPortletURLFactory, eventName,
> new ImageItemSelectorCriterion(), new URLItemSelectorCriterion());
> 
> jsonObject.put(
>             "filebrowserImageBrowseLinkUrl", itemSelectorURL.toString()
>     ).put(
>             "filebrowserImageBrowseUrl", itemSelectorURL.toString()
>     );
>   }
> 
>   @Reference
> private ItemSelector itemSelector;
> 
>   @Reference
> private JSONFactory jsonFactory;
> }

ServletFilter:

import com.liferay.portal.kernel.util.StreamUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.service.component.annotations.Component;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.net.URL;

@Component(
    immediate = true,
    property = {
        "servlet-context-name=",
        "servlet-filter-name=CKEditorConfigServletFilter",
        "url-pattern=/o/frontend-editor-ckeditor-web/ckeditor/config.js"
    },
    service = Filter.class
)
public class CKEditorConfigServletFilter implements Filter {

  private Bundle bundle;

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    System.out.println("servlet filter zainicjalizowany");
    bundle = FrameworkUtil.getBundle(this.getClass());
    System.out.println("bundle: " + bundle);
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
          throws IOException, ServletException {
    URL entryURL = bundle.getEntry("/META-INF/resources/js/ckeditor5/config.js");
    System.out.println("do filter wystartowal: " + entryURL);
    if (entryURL != null) {
      response.setContentType("application/javascript");
      StreamUtil.transfer(entryURL.openStream(), response.getOutputStream(), false);
    } else {
      chain.doFilter(request, response);
    }
  }

  @Override
    public void destroy() {
  }
}

config.js: one of my tries of config.js:

CKEDITOR.editorConfig = function(config) {
    // Define changes to default configuration here. For example:
    // config.language = 'fr';
    // config.uiColor = '#AADC6E';

    // Define the toolbar groups as it is a more accessible solution.
    console.log(config)
    config.toolbarGroups = [
        { name: 'clipboard', groups: ['clipboard', 'undo'] },
        { name: 'editing', groups: ['find', 'selection', 'spellchecker'] },
        { name: 'links' },
        { name: 'insert' },
        { name: 'forms' },
        { name: 'tools' },
        { name: 'document', groups: ['mode', 'document', 'doctools'] },
        { name: 'others' },
        '/',
        { name: 'basicstyles', groups: ['basicstyles', 'cleanup'] },
        { name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align', 'bidi'] },
        { name: 'styles' },
        { name: 'colors' },
        { name: 'about' }
    ];

    // Remove some buttons provided by the standard plugins, which we don't need to have.
    config.removeButtons = 'Underline,Subscript,Superscript';

    // Set the most common block elements.
    config.format_tags = 'p;h1;h2;h3;pre';

    // Simplify the dialog windows.
    config.removeDialogTabs = 'image:advanced;link:advanced';

    // Additional configuration options
    config.extraPlugins = 'divarea,clipboard';
    config.removePlugins = 'elementspath';

    // Custom toolbar definition
    config.toolbar_custom = [
        ['Undo', 'Redo', '-', 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'SelectAll', 'RemoveFormat'],
        ['Link', 'Unlink', 'Anchor'],
        ['Image', 'Flash', 'Table', '-', 'Smiley', 'SpecialChar']
    ];

    config.toolbar = "custom";
    console.log('end')
};

portal-ext.properties:

editor.wysiwyg.default=ckeditor
editor.wysiwyg.portal-impl.portlet.ddm.text_html.ftl=ckeditor
editor.wysiwyg.portal-web.docroot.html.portlet.announcements.edit_entry.jsp=ckeditor
editor.wysiwyg.portal-web.docroot.html.portlet.blogs.edit_entry.jsp=ckeditor
editor.wysiwyg.portal-web.docroot.html.portlet.mail.edit.jsp=ckeditor
editor.wysiwyg.portal-web.docroot.html.portlet.mail.edit_message.jsp=ckeditor
editor.wysiwyg.portal-web.docroot.html.portlet.message_boards.edit_message.html.jsp=ckeditor
editor.wysiwyg.portal-web.docroot.html.taglib.ui.discussion.jsp=ckeditor
editor.wysiwyg.portal-web.docroot.html.taglib.ui.email_notification_settings.jsp=ckeditor

editor.wysiwyg.portal-web.docroot.html.jsp=ckeditor

So my config is overrided correctly in /o/frontend-editor-ckeditor-web/ckeditor/config.js. It seems like liferay reads it, but then something else is overriding it. I don't have any other Contributors or implementations that could interfere with CKEditor. I have also tried adding another config like toolbar_custom and setting config.toolbar to custom, override default config of config.toolbar_simple but all the time config.toolbar keeps being overrided to "simple" and my config.toolbar_simple is being overrided as well. Do you guys have any idea how to solve it? I will be very thankful for any help.

Upvotes: 0

Views: 338

Answers (0)

Related Questions