Hello
This post is about my experience with these two add-ons:
1 remove linebreaks / do word wrap
2 Edit Field During Review (Cloze)
I needed an easy, simple way to remove linebreaks while reviewing, and I almost always edit using (Edit Field During Review (Cloze) ), but the problem was that "(remove linebreaks / do word wrap) didn’t work in the reviewer window.
I didn’t find anything online that could help me, so I used ChatGPT to help me create a custom shortcut according to this ( Edit-Field-During-Review-Cloze/FAQ.md at master · BlueGreenMagick/Edit-Field-During-Review-Cloze · GitHub )
This was the final product:
”Paste this at the bottom of both Front & Back templates:
<script>
(function () {
if (!window.EFDRC || !EFDRC.registerShortcut) return;
// Turn HTML (with <br>, <p>, etc.) into single-line text
function flattenHTML(html) {
const tmp = document.createElement('div');
tmp.innerHTML = html
.replace(/<br\s*\/?>/gi, ' ')
.replace(/<\/(div|p|li|tr|h[1-6])>/gi, ' ')
.replace(/<li[^>]*>/gi, '')
.replace(/ /gi, ' ');
let text = (tmp.textContent || '').replace(/\s+/g, ' ');
return text.replace(/\s+([,.;:!?])/g, '$1').trim();
}
function getSelectionRangeIn(root) {
const sel = document.getSelection();
if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return null;
const a = sel.anchorNode, f = sel.focusNode;
return (root.contains(a) && root.contains(f)) ? sel.getRangeAt(0) : null;
}
function replaceSelectionText(range, text) {
const sel = document.getSelection();
sel.removeAllRanges();
sel.addRange(range);
// Prefer execCommand for better undo integration
try {
if (document.queryCommandSupported && document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, text);
return;
}
} catch (e) {}
// Fallback DOM replacement
range.deleteContents();
const node = document.createTextNode(text);
range.insertNode(node);
const r2 = document.createRange();
r2.setStartAfter(node); r2.setEndAfter(node);
sel.removeAllRanges(); sel.addRange(r2);
}
// Ctrl+Alt+L — SELECTION-ONLY (does nothing if no selection)
EFDRC.registerShortcut('Ctrl+Alt+L', (ev, elem) => {
ev.preventDefault(); ev.stopPropagation();
const range = getSelectionRangeIn(elem);
if (!range) {
// tiny visual cue that you need a selection
try { elem.animate([{outline:'2px solid transparent'},{outline:'2px solid currentColor'}], {duration:120}); } catch(e){}
return;
}
const wrap = document.createElement('div');
wrap.appendChild(range.cloneContents());
const flattened = flattenHTML(wrap.innerHTML);
replaceSelectionText(range, flattened);
});
// Ctrl+Alt+Shift+L — WHOLE FIELD (explicit)
EFDRC.registerShortcut('Ctrl+Alt+Shift+L', (ev, elem) => {
ev.preventDefault(); ev.stopPropagation();
const flattenedAll = flattenHTML(elem.innerHTML);
const sel = document.getSelection();
const r = document.createRange();
r.selectNodeContents(elem);
sel.removeAllRanges(); sel.addRange(r);
try {
if (document.queryCommandSupported && document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, flattenedAll);
} else {
elem.textContent = flattenedAll; // last-resort fallback
}
} catch(e) { elem.textContent = flattenedAll; }
});
})();
</script>
Now:
-
Ctrl+Alt+L only affects the selected text. If nothing is selected, it does nothing.
-
Ctrl+Alt+Shift+L cleans the entire field when you want that explicitly.”
And it worked!
But then I wanted to use this ( Edit-Field-During-Review-Cloze/FAQ.md at master · BlueGreenMagick/Edit-Field-During-Review-Cloze · GitHub ) to make it more built-in and not edit note type.
And this is the final product:
”
-
In Anki, go to
Tools → Add-ons → select “Edit Field During Review (Cloze)” → View Files. -
This opens the folder where the add-on’s code lives.
-
Go into the
webfolder
That’s where the add-on loads custom JS/CSS. -
Inside
web, create a new file named:
removeLineBreaks.js -
Paste your script into it. (the above script-you just need to remove the “ “ from the start and finish )
-
Now, to make the add-on read the file (script),
Inreviewer.py, find this block (around line ~230):js_contents = ["global_card.js", "resize.js"] for file_name in js_contents: web_content.js.append(url_from_fname(file_name))Change it to:
js_contents = ["global_card.js", "resize.js", "removeLineBreaks.js"] for file_name in js_contents: web_content.js.append(url_from_fname(file_name))Save → restart Anki.
Option 2: More Flexible (Auto-load any JS inweb/)Replace that block with:
import os for file_name in os.listdir(os.path.join(os.path.dirname(__file__), "web")): if file_name.endswith(".js"): web_content.js.append(url_from_fname(file_name))That way, any
.jsYou drop into theweb/folder will load automatically — no need to editreviewer.pyagain.(I used option one)
-
If you want it to show up in your add-on’s config panel, you can add this to the Advanced Config editor →
special_formatting:"removeLineBreaks": { "command": "removeLineBreaks", "enabled": true, "shortcut": "Ctrl+Alt+L" }, "removeLineBreaksAll": { "command": "removeLineBreaksAll", "enabled": true, "shortcut": "Ctrl+Alt+Shift+L" }These names (
removeLineBreaks,removeLineBreaksAll) don’t exist by default, but by keeping them consistent you’ll see them listed and can change the hotkeys later.
And that’s it, it worked for me (I just did it, so I’m not sure if I’m gonna run into any problem with it in the future)
I wanted to share this here to help the community and anyone who may need it.
Disclaimer:
1- I don’t know coding AT ALL, so proceed at your own risk
2- I respect the community and the developers for their efforts. If altering the add-on is wrong in any way, please point that out (I don’t know, but I assumed it’s ok)