Customization
- Configuration Levels
- Configure the Editor
- Configuration Parameters
- Put Dedicated Insert Macro Buttons on the Tool Bar
- Customize the well-known macro list
- Use additional CKEditor plugins
- Extend the default style set
- Execute JavaScript code inside the editing area (XWiki 10.10+)
- Replace the Default Editor (before XWiki 8.2)
- Add parameters to the CKEditor html conversion request
- Add a new Link Type
Configuration Levels
The CKEditor integration in XWiki is configured at multiple leves:
- app config.js (from application-ckeditor-webjar): default global (static) configuration, no Velocity evaluation
- app CKEditor.ConfigSheet (from application-ckeditor-ui): default global (dynamic) configuration, with Velocity evaluation
- admin CKEditor.Config: global (static) configuration, no Velocity evaluation <- this page is created when administrators use the dedicated CKEditor administration section
- app CKEditor.EditSheet (from application-ckeditor-ui): default instance (dynamic) configuration
- dev instance configuration passed when creating the editor <- provided by developers that use the CKEditor API
- dev custom instance configuration done by listening to editor events (from code that doesn't control the editor instance creation) <- provided by developers that use the CKEditor API; see below for examples
Each level in this list can overwrite the configuration from previous levels (it's actually a merge). The levels marked with app provide default configuration that shouldn't be modified directly by users. The users can and should configure the editor:
- either through the dedicated CKEditor administration section (that generates the CKEditor.Config page)
- or using the CKEditor API (when creating the editor or by listening to editor events)
Configure the Editor
XWiki integrates CKEditor. However XWiki doesn't offer by default all the options you'll find in CKEditor by default. The reason is that we want to offer a simple editor suited for a wiki and there are some features that are less useful in a wiki. In addition we'd like users to be able to focus on writing content and less about style. However you can tune the configuration if you wish to enable those options.
Starting with version 1.9 the recommended way to configure the CKEditor is through the dedicated "WYSIWYG Editor" section in the Wiki Administration.
If you want to configure the CKEditor globally for all the wikis in your farm then you have to copy the file META-INF/resources/webjars/application-ckeditor-webjar/<version>/config.js from WEB-INF/lib/application-ckeditor-webjar-<version>.jar to WEB-INF/classes, preserving its path, and modify it. Don't forget that the configuration properties set at wiki level overwrite the global settings.
If you have an older version of the CKEditor Integration extension installed (<1.9) and you cannot upgrade, you can still configure the editor. You have the following options:
- You can edit the CKEditor.EditSheet page using the Object editor, expand the first JavaScriptExtension object ("CKEditor Loader") and look for the ckeditor.replace line. You'll notice there the configuration options.
- On XWiki 8.1M1+ you can create a JavaScript extension with the following code:require(['deferred!ckeditor'], function(ckeditorPromise) {
ckeditorPromise.done(function(ckeditor) {
ckeditor.on('instanceCreated', function(event) {
// The editor instance was created but it not yet initialized. Unfortunately the configuration object passed when
// the instance was created has not been merged with the global configuration yet.
event.editor.once('configLoaded', function(event) {
// The editor configuration has been loaded (the instance configuration has been merged with the global
// configuration) but the editor has not been fully initialized yet so we can modify the configuration.
ckeditor.tools.extend(event.editor.config, {
height: 200,
...
}, true);
});
});
});
});Don't forget to set "Use this extension" to "On this wiki".
Configuration Parameters
Check out the CKEditor documentation for the full list of generic configuration parameters. Besides these, there are also some configuration parameters that are specific to XWiki. You can set any configuration parameter (either generic or XWiki-specific) using the Advanced configuration text area from the CKEditor administration section. The XWiki-specific parameters are set like this:
config['xwiki-link'] = config['xwiki-link'] || {};
// 'autoGenerateLabels' is the configuration parameter for that plugin.
config['xwiki-link'].autoGenerateLabels = true;
Plugin | Parameter | Description | Since |
---|---|---|---|
applyPasteFilterAfterPasteFromWord | Whether to apply the paste filter after the Word filter. Default value is true | 1.19 | |
xwiki-image | resourceTypes | The resource types you can select from on the Image dialog. See ResourceType.java for the list of supported resource types. The default value is: ['attach', 'icon', 'url'] | |
xwiki-link | resourceTypes | The resource types you can select from on the Link dialog. See ResourceType.java for the list of supported resource types. The default value is: ['doc', 'attach', 'url', 'mailto'] | |
autoGenerateLabels | Whether to create links with auto-generated labels or links with explicit labels. Auto-generated labels are updated automatically when the target page is moved or renamed but they increase a bit the rendering time and the output may be technical, depending on how you configure the link label generation. The default value is false | 1.14 | |
labelGenerator | The service used to obtain the generated link labels, in case autoGenerateLabels is true. | 1.14 | |
xwiki-macro | insertButtons | Used to put dedicated insert macro buttons on the tool bar. See the following sections for more information. The default value is [] | 1.13 |
xwiki-resource | dispatcher | The service used to obtain resource URLs. | |
xwiki-save | saveAndContinueButton | The CSS selector for the Save & Continue button. The default value is: 'input[name=action_saveandcontinue]' | |
leaveConfirmation | Whether to ask for confirmation when leaving the editor with unsaved changes. The default value is true | ||
xwiki-source | htmlConverter | The service used to convert between HTML and wiki syntax. This is used when switching between WYSIWYG and Source modes. | |
xwiki-slash | extraQuickActionGroups | Define additional quick action groups; the value is an array of {id, name, order} objects; a lower order number will show the group higher in the quick actions drop down; note that groups are shown only when they contain at least one action; default value is [] (empty array); here's an example: config.extraQuickActionGroups = [{ id: 'diagrams', name: 'Diagrams', order: 300 }]; | 15.5RC1 |
extraQuickActions | Define additional quick actions; the value is an array of {group, id, name, description, iconClass, iconURL, shortcut, command, outputHTML} objects; the quick action icon is specified either using a CSS class (e.g. when a font icon is used) or an URL; the actual action performed is defined either by the HTML that is inserted in the edited content or by the editor command that is executed; default value is [] (empty array); here's an example: config.extraQuickActions = [{ group: 'content', id: 'a', name: 'Link', iconClass: 'fa fa-link', shortcut: '[', description: 'Insert a link to a wiki page or attachment.', outputHTML: '[' }, { group: 'formatting', id: 'macro-code-js', name: 'JavaScript Snippet', iconClass: 'fa fa-code', description: 'Insert a snippet of JavaScript code', command: { name: 'xwiki-macro', data: { name: 'code', parameters: { language: 'js' }, } } }]; | 15.5RC1 | |
removeQuickActions | Specifies which quick actions to remove; the value is an array of quick action identifiers (strings); default value is [] (empty array); here's an example: config.removeQuickActions = ['blockquote', 'macro-toc']; Note: if you want to remove a macro use the prefix "macro-" and add the id of the macro. | 15.5RC1 | |
xwiki-focusedplaceholder | placeholder | Associates a placeholder text to an HTML tag name; here's an example: config["xwiki-focusedplaceholder"].placeholder.h1 = "Your Heading 1 placeholder"; | 15.5RC1 |
ignoreIfEmpty | The list of HTML tag names that should be ignored if empty, i.e. the list of DOM elements that won't get a placeholder text even if they are empty; default value is ["#text", "a", "abbr", "b", "bdi", "bdo", "br", "cite", "data", "dfn", "em", "i", "mark", "s", "small", "span", "strong", "time", "u", "var", "wbr", "del", "ins"] | 15.5RC1 |
Put Dedicated Insert Macro Buttons on the Tool Bar
XWiki 1.13+ You can speed up macro insertion by placing dedicated insert buttons on the tool bar. The following configuration adds two more buttons to the tool bar: the first inserts a Page Tree and the second inserts an HTML snippet. Both buttons will open the Edit Macro dialog to allow the user to fill the macro parameter values (some values will be pre-filled based on the macro call configuration).
XWiki 1.57+ If you want to insert the macro directly, without going through the Edit Macro dialog, you can do so, by setting insertDirectly: true. Check the third button we insert on the toolbar in the example below.
config['xwiki-macro'].insertButtons = [
// First button, specifies only the macro name.
'documentTree',
// Second button, specifies also macro parameter values.
{
commandId: 'xwiki-macro-html-dirty',
macroCall: {
name: 'html',
parameters: {
clean: false,
wiki: true
}
}
},
// Third button, specifies also the macro content, and the macro is inserted directly.
{
insertDirectly: true,
macroCall: {
name: 'info',
content: 'type message here'
}
}
];
As you can see, there are two ways in which you can specify the buttons:
- a simple way: you just specify the macro name
- an advanced way: you can specify also the macro parameter values and the command name (which is needed if you add more buttons for the same macro)
- you can control whether the macro is inserted inline or as a block element from the macro call configuration:macroCall: {
name: 'mention',
inline: false|true|'enforce',
...
}Note that due to the way the XWiki rendering works, passing inline:true doesn't lead to an inline macro if the macro is alone in a paragrah. XWiki 1.58+ If you want the macro to be inserted inline even in this case then you need to pass inline:'enforce'. This will also place the caret after the macro so that the user can continue editing.
- you can control whether the macro is inserted inline or as a block element from the macro call configuration:
Then, you can control the button icon by using some CSS in a custom skin or by using a SSX Skin Extension. Here's an example:
font-family: 'Glyphicons Halflings';
position: relative;
top: 1px;
}
.cke_button_icon.cke_button__xwiki-macro-documenttree_icon::before {
content: "\e199";
display: inline-block;
text-align: center;
width: 16px;
}
In this example we've used a font icon, but you can use whatever icon you want through CSS.
Customize the well-known macro list
It's possible to customize the content of the macro list from:
The insert button drop-down is controlled by two configuration properties:
- toolbarMenuItems: you first need to define a "toolbar menu item" for the macros you want to expose. Check the examples:infoBox: {
command: 'xwiki-macro-insert',
data: {
name: 'info',
content: 'Type your information message here.',
parameters: {...}
}
},As you can see you can specify both the macro content and parameters (preset the values). For the command you have two options:
- xwiki-macro-insert: insert the macro directly
- xwiki-macro: open the macro wizard
- toolbarMenus: you need to modify the "insert" menu.
Both of these can be modified from the CKEditor administration section, but you need to set the entire value, i.e. you need to copy the current value and modify it (you can't just add a new menu item).
Use additional CKEditor plugins
For the CKEditor integration with XWiki we have selected a list of CKEditor plugins that we bundle by default. They provide the basic WYSIWYG editing features like text formatting, inserting links, images, tables, etc. The integration with these default plugins is supported by the XWiki Development Team, which means you can report issues and we'll look into them. There are many more CKEditor plugins available that you can integrate separately in XWiki, but you should be aware that they are not supported by the XWiki Development Team. The most common issue you can have with these plugins is that they may generate HTML that cannot be converted to the XWiki syntax.
You need to do two things if you want to integrate additional CKEditor plugins:
- Let CKEditor know where the plugin is located:CKEDITOR.plugins.addExternal('plugin name', 'plugin URL or path');
You can put this:
- in the "Advanced Configuration" text area from the CKEditor administration section, if you can hard-code the plugin URL/path or compute it on the client-side using only JavaScript. E.g.: assuming the CKEditor plugin is defined in the Sandbox.Foo JavaScript skin extension like thisCKEDITOR.plugins.add('foo', {
init: function(editor) {
...
}
});then you can specify its location with this:
CKEDITOR.plugins.addExternal('foo', new XWiki.Document('Foo', 'Sandbox').getURL('jsx')); - or in a JavaScript skin extension. E.g.: assuming the CKEditor plugin is defined by resources/ckeditorPlugins/foo.js within the XWiki WAR then you can specify its location withrequire(['deferred!ckeditor'], function(ckeditorPromise) {
ckeditorPromise.done(function(ckeditor) {
ckeditor.plugins.addExternal('foo', "$xwiki.getSkinFile('ckeditorPlugins/foo.js')");
});
});Make sure the JSX is configured to be loaded automatically on the entire wiki.
- in the "Advanced Configuration" text area from the CKEditor administration section, if you can hard-code the plugin URL/path or compute it on the client-side using only JavaScript. E.g.: assuming the CKEditor plugin is defined in the Sandbox.Foo JavaScript skin extension like this
- Enable the plugin in the CKEditor configuration:config.extraPlugins = 'foo,bar';
Extend the default style set
The CKEditor provides a Styles drop down on the tool bar that you can use to apply various styles to the selected content. If you want to add custom styles then you have two options:
- Use the dedicated administration section to overwrite completely the style set. Checkout the styleSet configuration option. You'll probably want to copy some of the default styles.
- Use a JavaScript extension (e.g. a JSX object loaded on the wiki) to extend the default style set:// The following code is executed only when CKEditor is loaded on the current page.
require(['deferred!ckeditor'], function(ckeditorPromise) {
ckeditorPromise.done(function(ckeditor) {
// Wait for an editor instance to be created.
ckeditor.once('instanceCreated', function(event) {
// Wait for the default style set to be loaded.
event.editor.once('stylesSet', function(event) {
// Modify the default style set.
ckeditor.stylesSet.get('html5').push({name: 'Custom', element: 'p', attributes: {'class': 'custom'}})
});
});
});
});
Execute JavaScript code inside the editing area (XWiki 10.10+)
The sheet (CKEditor.ContentSheet) used to render the content of the edited page inside the editing area doesn't load, by default, the JavaScript code required by the edited content. This means, for instance, that if the edited content is using a macro that requires some JavaScript code in order to be displayed properly then that JavaScript code is not executed and thus the macro output doesn't look good inside the editing area. There are multiple reasons for this behavior:
- loading and executing the JavaScript code slows down the editor
- the JavaScript code could modify the edited content (outside of the protected macro output) and these changes would be saved
- the JavaScript code could throw exceptions or interfere with the CKEditor code thus breaking the editor which may lead to content loss
- executing the JavaScript code opens the door to XSS attacks
One way to fix the macro output, while still being safe with respect to JavaScript, is to modify the macro code so that it behaves differently when executed in WYSIWYG edit mode. The macro could for instance generate a placeholder (e.g. an image) in WYSIWYG edit mode, that doesn't need JavaScript.
If this is not enough and you really want to execute the JavaScript code inside the editing area then you need to do this:
- Enable the loading of the JavaScript Skin Extensions from the CKEditor administration section
- Modify the macro code to mark the scripts that are safe to be loaded inside the editing area:#set ($discard = $xwiki.jsx.use('Path.To.MyMacro', {'wysiwyg': true}))
- Use the macro from the CKEditor and look for:
- JavaScript exceptions in the JavaScript console
- Content that should not be saved
If you get this then you need to fix the JavaScript code.
Replace the Default Editor (before XWiki 8.2)
When Editing a Page
By default this extension adds a new "CKEditor" entry to the Edit menu. This means that the CKEditor won't be available for your simple users because only the advanced users have the Edit menu. The simple users have only the Edit button/link/icon. In order to open the CKEditor by default (i.e. replace the default editor) you can navigate to the CKEditor.EditMenuEntry page and from the Objects editing mode replace the Code property of the existing JavaScriptExtension object with:
$('#tmEdit > a, a#tmEditDefault').attr('href', function(index, url) {
return url + (url.indexOf('?') < 0 ? '?' : '&') + 'editor=inline&sheet=CKEditor.EditSheet';
});
$('a#tmEditWysiwyg').attr('href', function(index, url) {
return url.replace('editor=wysiwyg', 'editor=inline&sheet=CKEditor.EditSheet');
});
});
As a result the URL of the default edit link will point to the CKEditor. This has no effect though if you open the edit page directly using the URL (browser address bar). If you want the default edit URL (e.g. /xwiki/bin/edit/A/B/C) to open the CKEditor then you'll have to modify the edit.vm Velocity template (e.g. in a custom skin).
When Editing a Section of a Page
In order to be able to edit page sections using the CKEditor you need to edit the CKEditor.EditMenuEntry page as indicated in the previous section and append the following JavaScript code to the end of the Code property:
var modifySectionEditLinks = function() {
// Use the CKEditor for editing page sections.
$('.edit_section > a').attr('href', function(index, oldHref) {
return oldHref + '&editor=inline&sheet=CKEditor.EditSheet';
});
};
if (window.XWiki && XWiki.domIsLoaded) {
modifySectionEditLinks();
} else {
// XWiki 6.4+
require(['xwiki-events-bridge'], function() {
$(document).on('xwiki:dom:loaded', modifySectionEditLinks);
});
}
});
If you're using the CKEditor Integration version 1.2 or older you also need to modify the CKEditor.EditSheet page as indicated in this commit.
When Creating a Blank Page
When you create a page using the "Blank page" (or "Empty wiki page") type (template) you are redirected to the edit mode for that page. In order to use the CKEditor in this case, instead of the default WYSIWYG editor, you need to import the file.
XWiki 15.2+, 14.10.7+
Add parameters to the CKEditor html conversion request
A xwiki:wysiwyg:convertHTML event is send before a request to convert some content to HTML is sent by CKEditor. Listeners can add new request parameters by add properties on the data object send with the event. The example below show how to add an example parameter with value 1.
data.example = 1;
});
Add a new Link Type
If you want to add a new link type in the Link dialog, follow these steps:
- Configure the list of resource types to appear in the link modal dropdown:config['xwiki-link'] = config['xwiki-link'] || {};
config['xwiki-link'].resourceTypes = ['doc', 'attach', 'url', 'mailto', 'sip']; - Specify the resource type metadata, which you can do from a JSX:require(['deferred!resource'], resourcePromise => {
resourcePromise.then(resource => {
resource.types.sip = {
label: 'SIP Phone Number',
icon: 'glyphicon glyphicon-phone',
placeholder: '+49XXXXXXXX'
};
return resource;
});
}); - Add the new link type on the XWiki Rendering side.