Add dataProcessor to ckeditor yaml configuration in TYPO3 - ckeditor

I'm wondering how to add a rule to the dataProcessor like it was possible in the old htmlarea.
In my case I want to add a fixed class to the "ul"-tag.
I tried something like that (tried to adapt the js configuration from ckeditor)
editor:
config:
format_p:
- { element : 'p', attributes : { 'class' : 'ul' }}
...but it does not work.

I did it now via TypoScript like this:
### Set default class for ul from rte
lib.parseFunc_RTE {
externalBlocks := addToList(ul)
externalBlocks {
ul.stripNL = 1
ul.callRecursive = 1
ul.callRecursive.tagStdWrap.HTMLparser = 1
ul.callRecursive.tagStdWrap.HTMLparser.tags.ul {
fixAttrib.class.default = ul
}
}
}
It does basically what I want, BUT still I think this is not optimal. The class is not stored in the DataBase, so if you need to export the content for some reason you will loose this class. And you can not style it in the BE RTE-field (at least not without providing some extra hack css)
So I'm still interested if there is a proper way of doing it in the ckeditor-config.

Related

Sass, create css class dynamic depending on data

I have this class:
.currency-flag-clp:before {
background-image: url('~currency-flags/dist/square-flags/clp.svg');
}
I want to add that class dynamically to an html element, so I need to add a class like:
.currency-flag-XXXXX:before {
background-image: url('~currency-flags/dist/square-flags/XXXXX.svg');
}
Is there a way with sass to do that? I don't want to define 270 class per value, I just want to create the class depending on my data.
As you want to set an individual class on the element it seems you have access to your currency data when building the page. In that case there may be an alternative more simple approach without SASS.
(1) ALTERNATIVE (NON SASS) SOLUTION - maybe a simpler approach
(a) Write a css variable 'actual-currency-flag-url' for your actual flag-image to a style block in the head of your file based on the actual user setting/currency.
(b) Then use that variable to build the url-path in css.
// add to <head> of page:
// based on your data maybe you can do it by php
// note: don't use slashes when building url(...)
<style>
:root {
--actual-currency-url: url(url-path/flag-[actualCurrency].jpg);
}
</style>
// change class off html element
// from <div class="currency-flag-XXXXX"> to:
<div class="currency-flag">
// now you can do in your separate stylesheet file:
.currency-flag:before {
background-image: var(--actual-currency-url);
}
Writing the style direct to the element is less elegant but works as well of course.
(2) POSSIBLE SASS SOLUTION - building 270 classes in SASS using a mixin
(a) Based on your data: generate a simple suffix-list and use it to build a SASS map with the suffixes of your flags.
(b) Use #each to build all 270 classes at once
// example code in SASS:
$flag-suffixes: (
USD,
AUD,
EUR,
//...
);
#each $suffix in $flag-suffixes {
.currency-flag-#{$suffix}:before {
background-image: url('~currency-flags/dist/square-flags/#{$suffix}.svg');
}
}

Elegant way to change view schema in CKEditor5

I'm looking for a way to change the view schema/tags used by CKE5 while trying not to reimplement everything. So basically the question is what is the best way to change for example the <strong> element to <b> in the editor.
My current solution is to change the *editing.js file, and the base plugin file to include the modified Editing plugin instead of the original. This works nicely, however, I'm wondering if there is a way to reduce the number of lines of code needed to accomplish this task.
So my solution currently looks like this:
newbold.js:
static get requires() {
return [ NewBoldEditing, BoldUI ];
}
and newboldediting.js:
editor.conversion.attributeToElement({
model: 'bold',
view: 'b'
});
Is there a better way of doing this (that preferably wouldn't involve reimplementing this many classes)?
You could provide only a very simple plugin that overwrites the default bold attribute conversion.
class BoldToB extends Plugin {
init() {
this.editor.conversion.attributeToElement( {
model: 'bold',
view: 'b',
converterPriority: 'high'
} );
}
}
Here's a fiddle for you to test: https://jsfiddle.net/u3zyw67v/
Note that in the fiddle I don't have access to Plugin class so I had to add constructor(). You don't need to do that if you extend Plugin class.

How to change group of CSS items in jqGrid

I want to change group of CSS items in jqGrid. Documentation is saying
Of course if we want to change not only one CSS item from a group, but two or more we can use jQuery extend to do this:
var my_col_definition = {
icon_move : 'ui-icon-arrow-1',
icon_menu : "ui-icon-pencil"
}
$.extend( $.jgrid.styleUI.jQueryUI.colmenu , my_col_definition );
And this is working partially. But I want to override all icons in my Bootstrap with next code:
$.extend($.jgrid.styleUI.Bootstrap, {
common: {
icon_base: "fa"
},
inlinedit: {
icon_edit_nav: "fa-edit"
},
navigator: {
icon_edit_nav: "fa-edit"
},
// ...
});
and my grid stops working and does not respond to any commands. There are no errors in console.
Do anybody know how to fix the problem in an elegant way and do not override every group separately?
It is unknown which versions of Guriddo jqGrid and Bootstrap are used.
I see you try to use the fontAwesome.
With the last release you can use fontAwesome with ths following settings:
<script>
$.jgrid.defaults.styleUI = 'Bootstrap4';
$.jgrid.defaults.iconSet = "fontAwesome";
</script>
And point to the needed css files as described in this documentation
You can change the icons the way you do in your code without problems - I have tested this and it works.
In any case, please prepare a simple demo which reproduces the problem, so that we can look into it.

Ckeditor plugin configuration not working

I have tried to add justify plugin to be able to align text right, left or centre. But after following the instructions in the documentation (http://apostrophecms.org/docs/tutorials/howtos/ckeditor.html), I wonder if the plugin should be located in a specific folder (mine is at public/modules/apostrophe-areas/js/ckeditorPlugins/justify/), as it disappears when the site is loaded, but if I include it in some other folder such as public/plugins/justify still doesn't work.
This is my code just in case: (located at lib/modules/apostrophe-areas/public/js/user.js)
apos.define('apostrophe-areas', {
construct: function(self, options) {
// Use the super pattern - don't forget to call the original method
var superEnableCkeditor = self.enableCkeditor;
self.enableCkeditor = function() {
superEnableCkeditor();
// Now do as we please
CKEDITOR.plugins.addExternal('justify', '/modules/apostrophe-areas/js/ckeditorPlugins/justify/', 'plugin.js');
};
}
});
Also, it would be nice to know how the plugin should be called at the Toolbar settings for editable widgets.
Thanks!
The URL you need is:
/modules/my-apostrophe-areas/js/ckeditorPlugins/justify/
The my- prefix is automatically prepended so that the public folders of both the original apostrophe-areas module and your project-level extension of it can have a distinct URL. Otherwise there would be no way for both to access their user.js, for instance.
I'll add this note to the HOWTO in question, which currently handwaves the issue by stubbing in a made-up URL.
As for how the plugin should be called, use the toolbar control name exported by that plugin — that part is a ckeditor question, not really an Apostrophe one. But looking at the source code of that plugin they are probably JustifyLeft, JustifyCenter, JustifyRight and JustifyBlock.
It turns out that it's not enough to simply call CKEDITOR.plugins.addExternal inside apostophe-areas. You also need to override self.beforeCkeditorInline of the apostrophe-rich-text-widgets-editor module and explicitly call self.config.extraPlugins = 'your_plugin_name';.
Here's what I ended up with:
In lib/modules/apostrophe-areas/public/js/user.js:
apos.define('apostrophe-areas', {
construct: function(self, options) {
// Use the super pattern - don't forget to call the original method
var superEnableCkeditor = self.enableCkeditor;
self.enableCkeditor = function() {
superEnableCkeditor();
// Now do as we please
CKEDITOR.plugins.addExternal('justify', '/modules/my-apostrophe-areas/js/ckeditorPlugins/justify/', 'plugin.js');
};
}
});
then in in lib/modules/apostrophe-rich-text-widgets/public/js/editor.js:
apos.define('apostrophe-rich-text-widgets-editor', {
construct: function(self, options) {
self.beforeCkeditorInline = function() {
self.config.extraPlugins = 'justify';
};
}
});
For some reason doing CKEDITOR.config.extraPlugins = 'justify' inside apostrophe-areas does not work, probably due to the way how CKEDITOR is initialized;
One more thing: this particular plug-in (justify, that is) does not seem to follow the button definition logic. It has button icons defined as images, whereas CKEditor 4.6 used in Apostrophe CMS 2.3 uses font-awesome to display icons. It means that the icons that ship with the justify module won't be displayed and you'll have to write your own css for each button individually.
There is another issue which you'll probably face when you finally enable the justify buttons. The built-in html sanitizer will be strip off the styles justify adds to align the content.
Apostrophe CMS seems to be using sanitize-html to sanitize the input, so changing CKEditor settings won't have any effect. To solve the issue, add the following to your app.js:
'apostrophe-rich-text-widgets': {
// The standard list copied from the module, plus sup and sub
sanitizeHtml: {
allowedAttributes: {
a: ['href', 'name', 'target'],
img: ['src'],
'*': ['style'] //this will make sure the style attribute is not stripped off
}
}
}
Thank you both for your help. After following both approaches of: locating the plugin at my-apostrophe-areas folder as well as editing editor.js on the apostrophe-rich-text widget (the sanitize.html file was already using that configuration), I got the plugin working. However, I was still having the issue with the icons.
I fixed that adding the Font Awesome icons that correspond to align-justify, align-right, align-left and align-center at the end of public/modules/apostrophe-areas/js/vendor/ckeditor/skins/apostrophe/editor.less

ckeditor how to allow for .insertHtml("<customTag myAttr='value'"></customTag>")

var currentDialog = CKEDITOR.dialog.getCurrent();
currentDialog._.editor.insertHtml("<customTag myAttr='var'></customTag>");
Throws an error, TypeError: Cannot read property 'isBlock' of undefined
If I try .insertHtml("<span>hello</span>") it works just fine.
How can I change ckeditor to allow me to specify my own custom html tags via .insertHtml()? I'd love to just change it to be something like <span class='custom'... or something like that, but I'm having to deal with legacy CMS articles. Using latest ckeditor. Thanks.
You need to modify CKEDITOR.dtd object so editor will know this tag and correctly parse HTML and process DOM:
CKEDITOR.dtd.customtag = { em:1 }; // List of tag names it can contain.
CKEDITOR.dtd.$block.customtag = 1; // Choose $block or $inline.
CKEDITOR.dtd.body.customtag = 1; // Body may contain customtag.
You need to allow for this tag and its styles/attrs/classes in Advanced Content Filter:
editor.filter.allow( 'customtag[myattr]', 'myfeature' );
Unfortunately, due to some caching, in certain situations you cannot modify DTD object after CKEditor is loaded - you need to modify it when it is created. So to do that:
Clone the CKEditor repository or CKEditor presets repository.
Modify core/dtd.js code.
And build your minified package following instructions in README.md - the only requirements are Java (sorry - Google Closure Compiler :P) and Bash.
PS. That error should not be thrown when unknown element is inserted, so I reported http://dev.ckeditor.com/ticket/10339 and to solve this inconvenience http://dev.ckeditor.com/ticket/10340.
I worked around this issue with a combination of createFromHtml() and insertElement()
CKEDITOR.replace('summary', { ... });
var editor = CKEDITOR.instances.summary;
editor.on('key', function(ev) {
if (ev.data.keyCode == 9) { // TAB
var tabHtml = '<span style="white-space:pre"> </span>';
var tabElement = CKEDITOR.dom.element.createFromHtml(tabHtml, editor.document);
editor.insertElement(tabElement);
}
}

Resources