discourse/plugins/checklist/assets/javascripts/lib/rich-editor-extension.js
Renato Atilio 49f6f5d083
UX: rich editor checklist undoable input rule (#32877)
Removes the rich editor checklist input rule `undoable: false`, which is
not needed.

Making it undoable allows a backspace to undo the input rule conversion,
so we can go from a check to a `[]` again
2025-05-23 14:20:27 +10:00

69 lines
1.6 KiB
JavaScript

/** @type {RichEditorExtension} */
const extension = {
// TODO(renato): make the checkbox clickable
// TODO(renato): auto-continue checkbox list on ENTER
// TODO(renato): apply .has-checkbox style to the <li> to avoid :has
nodeSpec: {
check: {
attrs: { checked: { default: false } },
inline: true,
group: "inline",
draggable: true,
selectable: false,
toDOM(node) {
return [
"span",
{
class: node.attrs.checked
? "chcklst-box checked fa fa-square-check-o fa-fw"
: "chcklst-box fa fa-square-o fa-fw",
},
];
},
parseDOM: [
{
tag: "span.chcklst-box",
getAttrs: (dom) => {
return { checked: hasCheckedClass(dom.className) };
},
},
],
},
},
inputRules: [
{
match: /(^|\s)\[(x? ?)]$/,
handler: (state, match, start, end) =>
state.tr.replaceWith(
start + match[1].length,
end,
state.schema.nodes.check.create({ checked: match[2] === "x" })
),
},
],
parse: {
check_open: {
node: "check",
getAttrs: (token) => ({
checked: hasCheckedClass(token.attrGet("class")),
}),
},
check_close: { noCloseToken: true, ignore: true },
},
serializeNode: {
check: (state, node) => {
state.write(node.attrs.checked ? "[x]" : "[ ]");
},
},
};
const CHECKED_REGEX = /\bchecked\b/;
function hasCheckedClass(className) {
return CHECKED_REGEX.test(className);
}
export default extension;