UNPKG

jodit

Version:

Jodit is an awesome and useful wysiwyg editor with filebrowser

139 lines (138 loc) 4.6 kB
/*! * Jodit Editor (https://xdsoft.net/jodit/) * Released under MIT see LICENSE.txt in the project root for license information. * Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net */ import { globalWindow } from "../../../core/constants.js"; import { Dom } from "../../../core/dom/dom.js"; import { $$ } from "../../../core/helpers/utils/selector.js"; /** * @private */ const TMP_ATTR = 'jd-tmp-selection'; /** * @private */ export function highlightTextRanges(jodit, rng, restRanges, ci, root) { if (rng.startContainer.nodeValue == null || rng.endContainer.nodeValue == null) { return; } if (checkNativeSelectionMethod(jodit, rng, restRanges)) { return; } const span = ci.element('span', { [TMP_ATTR]: true }); Dom.markTemporary(span); normalizeRanges(rng, restRanges, ci); let next = rng.startContainer; do { if (!next) { break; } if (Dom.isText(next) && !isSelectionWrapper(next.parentNode)) { Dom.wrap(next, span.cloneNode(), ci); } if (next === rng.endContainer) { break; } let step = next.firstChild || next.nextSibling; if (!step) { while (next && !next.nextSibling && next !== root) { next = next.parentNode; } step = next === null || next === void 0 ? void 0 : next.nextSibling; } next = step; } while (next && next !== root); } /** * @private */ export function getSelectionWrappers(root) { return $$(`[${TMP_ATTR}]`, root); } /** * @private */ export function clearSelectionWrappers(jodit) { getSelectionWrappers(jodit.editor).forEach(span => Dom.unwrap(span)); clearNativeSelection(jodit); } /** * @private */ export function clearSelectionWrappersFromHTML(root) { return root.replace(RegExp(`<span[^>]+${TMP_ATTR}[^>]+>(.*?)</span>`, 'g'), '$1'); } /** * @private */ function isSelectionWrapper(node) { return Dom.isElement(node) && node.hasAttribute(TMP_ATTR); } function checkNativeSelectionMethod(jodit, rng, restRanges) { if (jodit.o.search.useCustomHighlightAPI && // @ts-ignore Because Highlight is not defined in the types TS 5.3.3 globalWindow && typeof globalWindow.Highlight !== 'undefined') { const ranges = [rng, ...restRanges].map(rng => { const range = jodit.selection.createRange(); range.setStart(rng.startContainer, rng.startOffset); range.setEnd(rng.endContainer, rng.endOffset); return range; }); const searchHighlight = new Highlight(...ranges); // @ts-ignore CSS.highlights.clear(); // @ts-ignore CSS.highlights.set('jodit-search-result', searchHighlight); restRanges.length = 0; return true; } return false; } export function clearNativeSelection(jodit) { if (jodit.o.search.useCustomHighlightAPI && // @ts-ignore Because Highlight is not defined in the types TS 5.3.3 globalWindow && typeof globalWindow.Highlight !== 'undefined') { // @ts-ignore CSS.highlights.clear(); } } function normalizeRanges(rng, restRanges, ci) { const startText = rng.startContainer.nodeValue; let diff = 0; if (rng.startOffset !== 0) { const text = ci.text(startText.substring(0, rng.startOffset)); rng.startContainer.nodeValue = startText.substring(rng.startOffset); Dom.before(rng.startContainer, text); if (rng.startContainer === rng.endContainer) { diff = rng.startOffset; rng.endOffset -= diff; } rng.startOffset = 0; } const endText = rng.endContainer.nodeValue; if (rng.endOffset !== endText.length) { const text = ci.text(endText.substring(rng.endOffset)); rng.endContainer.nodeValue = endText.substring(0, rng.endOffset); Dom.after(rng.endContainer, text); for (const range of restRanges) { if (range.startContainer === rng.endContainer) { range.startContainer = text; range.startOffset = range.startOffset - rng.endOffset - diff; if (range.endContainer === rng.endContainer) { range.endContainer = text; range.endOffset = range.endOffset - rng.endOffset - diff; } } else { break; } } rng.endOffset = rng.endContainer.nodeValue.length; } }