redactor
redactor copied to clipboard
Redactor randomly deletes all links in a block, or in the rest of the field
Description
In Firefox and Chrome, inserting a link will randomly delete all surrounding links. Once in a while, I don't notice it happening, and I have to manually reinsert dozens of references and external links on the page. It's infuriating, since it can erase hours of work.
This issue is very common (~60% of the time), and it has been there since I started using Craft. I wanted to report it to Redactor, but they have no sort of community forum.
Steps to reproduce
- In a long article, double-click a word to select it
- Insert a link (Cmd + K). It happens more often with text
- When you save the link, watch for surrounding links being removed, and appearing as normal text.
https://user-images.githubusercontent.com/88917/122943603-73111380-d377-11eb-9a54-835f8aaf3d3e.mov
Additional info
- Craft version: all versions from the last 4 years, including a fully updated Craft setup.
- Browser: all Chrome and Firefox versions from the last 4 years
First mentioned here 4 years ago: https://github.com/craftcms/cms/issues/2158
Long shot, but does this bug happen after using Live Preview? I'm wondering if this pr for a long standing JS error would fix other odd issues like this too: https://github.com/craftcms/redactor/pull/329
I never use live preview, so that is very unlikely. The example above happened on a freshly loaded page.
I've had editors report this bug but I've never been able to reproduce it. My editors say it happens randomly but there must be a cause. Would you mind pasting the exact html you are editing above and the Redactor config?
It happens very frequently. The problem is completely random, but the easiest way to reproduce it is to select a word, italicise it (Cmd + I), and link to it (Cmd + K). Redactor seems to hate this.
https://user-images.githubusercontent.com/88917/123619890-eb5d5600-d809-11eb-872d-2d1f282ef003.mov
For example, select the word "their" in the HTML below, then Cmd + I, then Cmd + K. When you save the link, all links before that word get deleted.
<h2>Tipping at the restaurant</h2>
<p>Germans usually tip their waiters<sup><a href="https://en.wikipedia.org/wiki/Gratuity#Germany">1</a></sup>. Tipping is not mandatory, but it's common<sup><a href="https://en.wikipedia.org/wiki/Gratuity#Germany">1</a></sup>. German waiters do not depend on tips to survive, but it's a big part of their income<sup><a href="https://www.reddit.com/r/germany/comments/b48xti/how_does_one_tip_in_berlin/ej56dbp/">1</a>, <a href="https://www.reddit.com/r/germany/comments/2wptvp/do_you_guys_give_tips/cotaw6a/">2</a></sup>.</p>
Redactor and field configs:
{
"buttons": ["html","format","bold","italic","lists","link","file","image","video","horizontalrule"],
"plugins": ["inlinestyle", "fullscreen", "table", "video", "pagebreak", "widget"],
"imageResizable": true,
"imagePosition": true
}
contentColumnType: mediumtext
fieldGroup: 24164084-1fbe-4cb3-8263-5c3215381e7d
handle: body
instructions: ''
name: Body
searchable: true
settings:
availableTransforms: '*'
availableVolumes: '*'
cleanupHtml: true
columnType: mediumtext
purifierConfig: ''
purifyHtml: '1'
redactorConfig: Advanced.json
removeEmptyTags: '1'
removeInlineStyles: '1'
removeNbsp: '1'
showUnpermittedFiles: false
showUnpermittedVolumes: false
translationKeyFormat: null
translationMethod: none
type: craft\redactor\Field
This is a huge problem for me, especially with auto-saving drafts. It can undo large swathes of my work, and if I don't immediately notice, I have to manually fix everything. I have wasted hours on this bug this years.
Thank you! I can reproduce the problem exactly as per your video.
Some initial observations:
- It occurs when you attempt to link italicized text.
- Any existing links preceding the text you are trying to link, within the same block-level element (e.g.
<p>
)- are removed.
This strongly suggests the regular expression used when inserting a new link is too greedy. Clearly a bug in Redactor that can also be easily reproduced on their own editor demos: https://imperavi.com/redactor/examples/initialization/base-example/
It sometimes spreads across multiple blocks. I spend a whole hour repairing links after Redactor erased them across a five page article. I have written to Imperavi and linked to this ticket. I hope they'll join the conversation.
In one instance, it replaced every link on the first half of the page to use the same URL. Again, another hour hunting through my search history for citations. It's incredibly frustrating.
I've sort of figured out roughly why this happens. After selecting some text and wrapping with a tag - for example, <em>
or <strong>
, the selection start point remains the same position as before the text was wrapped. It doesn't move inside the newly inserted tag. When you subsequently try to make the selection a link, Redactor uses a start position for the selected text outside the <em>
but an end position inside the <em>
. Redactor inserts some <spans>
to mark those positions so you can see where it's going wrong.
This shows what I mean:
![Screenshot 2021-06-28 at 16 10 39](https://user-images.githubusercontent.com/279127/123662303-3c327600-d82d-11eb-9186-c71fb1f66e96.png)
As a work around editors could click anywhere else in the editor window and then re-select the text, before adding the link.
Obviously that's not ideal but I wonder if there is a way to automate that, say by unselecting text after any new insert?
Ok, here's a crude workaround. It will unselect a text selection after you apply an inline style in Redactor, thus forcing the editor to reselect the text they wish to link. Create a plugin config/redactor/plugins/fixlinks.js
with this script:
(function($R)
{
$R.add('plugin', 'fixlinks', {
onformat: function(type, nodes)
{
if (type == 'inline') {
// clear selection
if (window.getSelection) {
window.getSelection().removeAllRanges();
} else if (document.selection) {
document.selection.empty();
}
}
}
});
})(Redactor);
And add to the plugins array in your Redactor config, e.g.:
{
"plugins": ["fixlinks"]
}
Let me know if that helps.
Here's another stab at that which (as far as I can tell) solves the issue, by forcing Redactor to select the contents of the newly inserted wrapping element. The editor can do multiple operations to the same text selection without triggering the error.
Create a plugin config/redactor/plugins/fixlinks.js
with this script:
(function($R)
{
$R.add('plugin', 'fixlinks', {
onformat: function(type, nodes)
{
var sel = window.getSelection(),
nextSibling = sel.anchorNode.nextSibling;
if (nextSibling) {
sel.removeAllRanges();
var newRange = document.createRange();
newRange.selectNodeContents(nextSibling);
sel.addRange(newRange);
}
}
});
})(Redactor);
And add to the plugins array in your Redactor config, e.g.:
{
"plugins": ["fixlinks"]
}
Thanks for the suggested fix! I'll implement it as soon as I can and report back.
@croxton, I just deployed your recommended fix. I'll give it a go over the next few weeks. Thank you for suggesting it in the first place.