Skip to content
Snippets Groups Projects
Commit be8597c4 authored by Marius Dumitru Florea's avatar Marius Dumitru Florea
Browse files

XWIKI-22317: Macros using HTML5 are sometimes badly rendered when edited in WYSIWYG mode

* Verify also the given element, not just its ancestors.
* Bulletproofing

(cherry picked from commit c8349eb2)
parent f80e2448
No related branches found
No related tags found
No related merge requests found
......@@ -916,37 +916,49 @@
// The passed element is of type CKEDITOR.htmlParser.element
isMacroElement: function(element) {
return (element.name == 'div' || element.name == 'span') &&
element.hasClass('macro') && element.attributes['data-macro'];
// The passed element doesn't always have the CKEDITOR.htmlParser.element API. This happens for instance when
// CKEditor checks which plugins to disable (based on the HTML elements they require). In this case the passed
// element only has the data (attributes, children, etc.).
element.hasClass?.('macro') && element.attributes['data-macro'];
},
// The passed element is of type CKEDITOR.htmlParser.element
isMacroOutput: function(element) {
return element.getAscendant && element.getAscendant(function(ancestor) {
// The macro marker comments might have been already processed (e.g. in the case of nested editables) so we need
// to look for a macro output wrapper also.
if (CKEDITOR.plugins.xwikiMacro.isMacroElement(ancestor)) {
return true;
}
// Look for macro marker comments otherwise, taking into account that macro markers can be "nested".
var nestingLevel = 0;
var previousSibling = ancestor;
while (previousSibling.previous && nestingLevel <= 0) {
previousSibling = previousSibling.previous;
if (previousSibling.type === CKEDITOR.NODE_COMMENT) {
if (previousSibling.value === 'stopmacro') {
// Macro output end.
nestingLevel--;
} else if (previousSibling.value.substr(0, 11) === 'startmacro:') {
// Macro output start.
nestingLevel++;
}
}
}
return nestingLevel > 0;
});
// CKEDITOR.htmlParser.element#getAscendant() doesn't check the element itself, so we have to do it.
return isMacroElementOrBetweenMacroMarkers(element) ||
element.getAscendant?.(isMacroElementOrBetweenMacroMarkers);
}
};
/**
* @param {CKEDITOR.htmlParser.element} element the element to check
* @returns {@code true} if the given element is a macro output wrapper or is between macro marker comments,
* {@code false} otherwise
*/
function isMacroElementOrBetweenMacroMarkers(element) {
// The macro marker comments might have been already processed (e.g. in the case of nested editables) so we need to
// look for a macro output wrapper also.
if (CKEDITOR.plugins.xwikiMacro.isMacroElement(element)) {
return true;
}
// Look for macro marker comments otherwise, taking into account that macro markers can be "nested".
var nestingLevel = 0;
var previousSibling = element;
while (previousSibling.previous && nestingLevel <= 0) {
previousSibling = previousSibling.previous;
if (previousSibling.type === CKEDITOR.NODE_COMMENT) {
if (previousSibling.value === 'stopmacro') {
// Macro output end.
nestingLevel--;
} else if (previousSibling.value.substr(0, 11) === 'startmacro:') {
// Macro output start.
nestingLevel++;
}
}
}
return nestingLevel > 0;
}
// Overwrite CKEditor's HTML parser in order to prevent it from removing empty elements from generated macro output.
// It's important to preserve the generated macro output as is, because these empty elements are often used:
// * to display font icons (even on the default wiki home page)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment