AEM 6.5 RTE appends .html to links



In AEM 6.5 I am having an issue with the link feature of RTE. It appends .html by default to any link starting with a "/". My application is Single Page so I want only the route. How can I override this default behavior? does not have any insights.

Accepted Solutions (1)

Accepted Solutions (1)





First of all, those are good instincts! 😉

However the solution is the following:

  1. Under the RTE node, create a child called htmlRules
  2. Under htmlRules create a child called links
  3. Add the following property to links:



ensureInternalLinkExt  --  Boolean  --  false​




Here is the resulting node structure:


PS: don't forget to add the htmlRules and links nodes to each RTE (the one in the cq:dialog and the in cq:editConfig for example).

This fixes the issue as you can see from this GIF:

Peek 2020-04-11 15-20.gif


Thanks a lot. That worked. However, I wanted to know what would be the correct approach to this problem resolution. I mean how could I have come to know myself about adding these nodes and properties would resolve the issue. The documentation at does not have this information.

I agree, the documentation on this point is pretty terrible. I'd actually done this before but I had to remind myself 😅

So if you look at the code that you commented, you see that it is inside some if-blocks (here is a snippet of richtext.js😞

// add extension to internal links if necessary (relative links are considered
// internal links as well)
if (this.ensureInternalLinkExt && this.isPage(href)) {
    var anchor = '';
    if (anchorPos > 0) {
        anchor = href.substring(anchorPos, href.length);
        href = href.substring(0, anchorPos);
    var query = '';
    var queryPos = href.indexOf('?');
    if (queryPos > 0) {
        query = href.substring(queryPos, href.length);
        href = href.substring(0, queryPos);
    // add extension to href if necessary
    var extSepPos = href.lastIndexOf('.');
    var slashPos = href.lastIndexOf('/');
    var hasClosingSlash = (slashPos === (href.length - 1));
    if (((extSepPos <= 0) || (extSepPos < slashPos)) && !hasClosingSlash) {
        obj.href = href + CUI.rte.Constants.EXTENSION_HTML + query + anchor;

The top-most condition checks a boolean variable called ensureInternalLinkExt. If we keep searching, we find that ensureInternalLinkExt comes from config, which is the same object that gives us the protocols:

config = config || {};
var defaults = {
'cssMode': 'auto',
'protocols': [
'targetConfig': {
    'mode': 'blank'
'ensureInternalLinkExt': true

 The documentation you linked to, if you read through it, does in fact explain how to set the protocols configuration (link to the relevant section here). So by logical deduction, we can assume that the same technique will work for ensureInternalLinkExt 😂
So yeah, if you are not familiar with the documentation or if you don't know much about RTE and editor plugins it's pretty hard to find (I remember when I first did this it probably took me over 2 hours to figure out, even though it seems kinda obvious now). It really should be documented better, but that's true of a LOT of things in AEM. On the plus side, that's why we get paid more than Java Spring developers or something XD If it was too easy, anybody could do it haha 👍


Answers (0)