/* * Load the site's JavaScript into a jsdom window. jsdom has no editing * commands, so document.execCommand records its calls in window.commands * (and does nothing else), and queryCommandState throws, as it does in * some browsers. */ "use strict"; const fs = require("node:fs"); const path = require("node:path"); const { JSDOM } = require("jsdom"); const ROOT = path.resolve(__dirname, "..", ".."); // The story field of publish/write.inc.php, in a form const STORY_FORM = `
`; function load(scripts, body, story) { const dom = new JSDOM(`${body}`, { runScripts: "outside-only", url: "https://xxx.org.za/publish/", pretendToBeVisual: true, }); const window = dom.window; window.commands = []; window.document.execCommand = function (command, ui, value) { window.commands.push([command, value]); return true; }; window.document.queryCommandState = function () { throw new Error("not supported"); }; if (story !== undefined) window.document.getElementById("story").value = story; for (const script of scripts) window.eval(fs.readFileSync(path.join(ROOT, script), "utf8")); return window; } // A window with the story form and publish/editor.js, and the editor attached function editorWindow(story = "") { const window = load(["publish/editor.js"], STORY_FORM, story); const textarea = window.document.getElementById("story"); const editor = window.XxxEditor.attach(textarea); const box = window.document.querySelector(".xed-area"); return { window, document: window.document, textarea, editor, box }; } // Select from (node, offset) to (endNode, endOffset), or put the caret there function select(window, node, offset, endNode = node, endOffset = offset) { const range = window.document.createRange(); range.setStart(node, offset); range.setEnd(endNode, endOffset); const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); return range; } // Select all the text of an element function selectText(window, element) { const range = window.document.createRange(); range.selectNodeContents(element); const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); return range; } function button(document, label) { const found = document.querySelector(`.xed-btn[aria-label="${label}"]`); if (!found) throw new Error(`No button "${label}"`); return found; } function key(window, target, key, options = {}) { const event = new window.KeyboardEvent("keydown", Object.assign({ key, bubbles: true, cancelable: true }, options)); target.dispatchEvent(event); return event; } module.exports = { ROOT, STORY_FORM, load, editorWindow, select, selectText, button, key };