Skip to content

Commit

Permalink
[TASK] Re-add autolinking RTE feature in CKeditor
Browse files Browse the repository at this point in the history
A missing functionality is added, which happened when introducing CKeditor.

Automatically linking a URL when typing www.typo3.org should happen directly.

A specific plugin is used for that. Base concept was taken from
https://github.com/Gnodiah/ckeditor-autolink

Resolves: #80977
Releases: master, 8.7
Change-Id: I575b63eeb696166b5e3b06047106e26cb68eb7b4
Reviewed-on: https://review.typo3.org/54611
Tested-by: TYPO3com <[email protected]>
Reviewed-by: Sebastian Hofer <[email protected]>
Tested-by: Sebastian Hofer <[email protected]>
Tested-by: Riccardo De Contardi <[email protected]>
Reviewed-by: Susanne Moog <[email protected]>
Tested-by: Susanne Moog <[email protected]>
  • Loading branch information
bmack authored and susannemoog committed Nov 29, 2017
1 parent b61e711 commit e096754
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ editor:
typo3link: { resource: "EXT:rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js", route: "rteckeditor_wizard_browse_links" }
# This is a plugin, found here: https://github.com/ufdada/quicktable
quicktable: { resource: "EXT:rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js" }
autolinking: { resource: "EXT:rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/**
* AutoLinking plugin for CKEditor 4.7
*
* Automatically creates an anchor tag when typing an URL or email.

This comment has been minimized.

Copy link
@kitzberger

kitzberger Feb 21, 2019

@bmack you're sure this is working for emails as well? In TYPO3 8.7 only URLs seem to work for me, but not mail addresses ;-/

This comment has been minimized.

Copy link
@bmack

bmack Feb 21, 2019

Author Member

good point. can you open up a ticket for this?

* Inspired by https://github.com/Gnodiah/ckeditor-autolink
*/
CKEDITOR.plugins.add('autolinking', {
init: function(editor) {
var spaceChar = 32, enterChar = 13, tabChar = 9, fillChar = ' ';
var isFillChar = function (node, isInStart) {
return node.nodeType == 3 && !node.nodeValue.replace(new RegExp((isInStart ? '^' : '' ) + ' '), '').length;
};
var isBodyTag = function (node) {
return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body';
};
var isAnchorTag = function (node) {
return node && node.nodeType == 1 && node.tagName.toLowerCase() === 'a';
};
var html = function (str) {
return str ? str.replace(/&((g|l|quo)t|amp|#39);/g, function (m) {
return {
'&lt;':'<',
'&amp;':'&',
'&quot;':'"',
'&gt;':'>',
'&#39;':"'"
}[m]
}) : '';
};

var hasParentAnchorTag = function (node) {
if (node && !isBodyTag(node)) {
while (node) {
if (isBodyTag(node)) {
return false;
} else if (isAnchorTag(node)) {
return true;
}
node = node.parentNode;
}
}
return false;
};

editor.on('instanceReady', function() {
editor.autolinking = function(evt) {
var sel = editor.getSelection().getNative(),
range = sel.getRangeAt(0).cloneRange(),
offset,
charCode;

var start = range.startContainer;
while (start.nodeType == 1 && range.startOffset > 0) {
start = range.startContainer.childNodes[range.startOffset - 1];
if (!start) break;

range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length);
range.collapse(true);
start = range.startContainer;
}

do {
if (range.startOffset == 0) {
start = range.startContainer.previousSibling;

while (start && start.nodeType == 1) {
if (CKEDITOR.env.gecko && start.firstChild)
start = start.firstChild;
else
start = start.lastChild;
}
if (!start || isFillChar(start)) break;
offset = start.nodeValue.length;
} else {
start = range.startContainer;
offset = range.startOffset;
}
range.setStart(start, offset - 1);
charCode = range.toString().charCodeAt(0);
} while (charCode != 160 && charCode != spaceChar);

if (range.toString().replace(new RegExp(fillChar, 'g'), '').match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) {
while (range.toString().length) {
if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) break;

try {
range.setStart(range.startContainer, range.startOffset+1);
} catch (e) {
var startChar = range.startContainer;
while (!(next = startChar.nextSibling)) {
if (isBodyTag(startChar)) {
return;
}
startChar = startChar.parentNode;
}
range.setStart(next, 0);
}
}

if (hasParentAnchorTag(range.startContainer)) {
return;
}

var a = document.createElement('a'),
href;

editor.undoManger && editor.undoManger.save();
a.appendChild(range.extractContents());
a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, '');
href = a.getAttribute('href').replace(new RegExp(fillChar,'g'), '');
href = /^(?:https?:\/\/)/ig.test(href) ? href : 'http://' + href;
a.href = html(href);

range.insertNode(a);
range.setStart(a.nextSibling, 0);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
editor.undoManger && editor.undoManger.save();
}
};

editor.on('key', function(evt) {
if (evt.data.keyCode === spaceChar || evt.data.keyCode === tabChar || evt.data.keyCode === enterChar) {
editor.autolinking(evt);
}
});
});
}
});

0 comments on commit e096754

Please sign in to comment.