inital commit

This commit is contained in:
2026-01-01 15:25:19 +05:30
commit f0ae49465a
36361 changed files with 4894111 additions and 0 deletions

260
node_modules/jodit/esm/core/dom/dom.d.ts generated vendored Normal file
View File

@@ -0,0 +1,260 @@
/*!
* 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
*/
/**
* [[include:core/dom/README.md]]
* @packageDocumentation
* @module dom
*/
import type { HTMLTagNames, ICreate, IDictionary, IJodit, NodeCondition, Nullable } from "../../types/index";
/**
* Module for working with DOM
*/
export declare class Dom {
private constructor();
/**
* Remove all content from element
*/
static detach(node: Nullable<Node>): void;
/**
* Wrap all inline next siblings
*/
static wrapNextInline(current: Node, tag: Node | HTMLTagNames, editor: IJodit): HTMLElement;
private static __wrapElements;
/**
* Wrap all inline siblings
*/
static wrapInline(current: Node, tag: Node | HTMLTagNames, editor: IJodit): HTMLElement;
static wrap<K extends HTMLTagNames>(current: Node | Range, tag: HTMLElement, create: ICreate): HTMLElementTagNameMap[K];
static wrap<K extends HTMLTagNames>(current: Node | Range, tag: K, create: ICreate): HTMLElementTagNameMap[K];
/**
* Remove parent of node and insert this node instead that parent
*/
static unwrap(node: Node): void;
/**
* Call functions for all nodes between `start` and `end`
*/
static between(start: Node, end: Node, callback: (node: Node) => void | boolean): void;
/**
* Replace one tag to another transfer content
*
* @param elm - The element that needs to be replaced by new
* @param newTagName - tag name for which will change `elm`
* @param withAttributes - If true move tag's attributes
* @param notMoveContent - false - Move content from elm to newTagName
* @example
* ```javascript
* Jodit.modules.Dom.replace(parent.editor.getElementsByTagName('span')[0], 'p');
* // Replace the first <span> element to the < p >
* ```
*/
static replace<T extends HTMLElement>(elm: Node, newTagName: HTMLTagNames): T;
static replace<T extends HTMLElement>(elm: Node, newTagName: HTMLTagNames, create: ICreate, withAttributes?: boolean, notMoveContent?: boolean): T;
static replace<T extends Node>(elm: Node, newTagName: T | string, create?: ICreate, withAttributes?: boolean, notMoveContent?: boolean): T;
/**
* Checks whether the Node text and blank (in this case it may contain invisible auxiliary characters ,
* it is also empty )
*
* @param node - The element of wood to be checked
*/
static isEmptyTextNode(node: Nullable<Node>): boolean;
static isEmptyContent(node: Node): boolean;
/**
* The node is editable
*/
static isContentEditable(node: Nullable<Node>, root: HTMLElement): boolean;
/**
* Check if element is empty
*/
static isEmpty(node: Node, condNoEmptyElement: (node: Element) => boolean): boolean;
static isEmpty(node: Node, noEmptyTags?: Set<string>): boolean;
/**
* Returns true if it is a DOM node
*/
static isNode(object: unknown): object is Node;
/**
* Check if element is table cell
*/
static isCell(elm: unknown): elm is HTMLTableCellElement;
/**
* Check if element is a list element UL or OL
*/
static isList(elm: Nullable<Node>): elm is HTMLOListElement;
/**
* Check if element is a part of list element LI
*/
static isLeaf(elm: Nullable<Node>): elm is HTMLLIElement;
/**
* Check is element is Image element
*/
static isImage(elm: unknown): elm is HTMLImageElement;
/**
* Check the `node` is a block element
* @param node - Object to check
*/
static isBlock(node: unknown): node is HTMLDivElement;
/**
* Check if element is text node
*/
static isText(node: Node | null | false): node is Text;
/**
* Check if element is comment node
*/
static isComment(node: Node): node is Comment;
/**
* Check if element is element node
*/
static isElement(node: unknown): node is Element;
/**
* Check if element is document fragment
*/
static isFragment(node: unknown): node is DocumentFragment;
/**
* Check if element is HTMLElement node
*/
static isHTMLElement(node: unknown): node is HTMLElement;
/**
* Check element is inline block
*/
static isInlineBlock(node: Node | null | false): node is HTMLElement;
/**
* It's block and it can be split
*/
static canSplitBlock(node: unknown): boolean;
/**
* Get last matched node inside root
*/
static last(root: Nullable<Node>, condition: NodeCondition): Nullable<Node>;
/**
* Find previous node
*/
static prev<T extends Node = Node>(node: Node, condition: NodeCondition, root: HTMLElement, withChild?: boolean): Nullable<T>;
/**
* Find next node what `condition(next) === true`
*/
static next<T extends Node = Node>(node: Node, condition: NodeCondition, root: HTMLElement, withChild?: boolean): Nullable<T>;
static prevWithClass(node: HTMLElement, className: string): Nullable<HTMLElement>;
static nextWithClass(node: HTMLElement, className: string): Nullable<HTMLElement>;
/**
* Find next/prev node what `condition(next) === true`
*/
static find<T extends Node = Node>(node: Node, condition: NodeCondition, root: HTMLElement, leftToRight?: boolean, withChild?: boolean): Nullable<T>;
/**
* Find next/prev node what `condition(next) === true`
*/
static nextGen(start: Node, root: HTMLElement, leftToRight?: boolean, withChild?: boolean): Generator<Node>;
/**
* It goes through all the internal elements of the node, causing a callback function
*
* @param elm - the element whose children and descendants you want to iterate over
* @param callback - It called for each item found
* @example
* ```javascript
* Jodit.modules.Dom.each(editor.s.current(), function (node) {
* if (node.nodeType === Node.TEXT_NODE) {
* node.nodeValue = node.nodeValue.replace(Jodit.INVISIBLE_SPACE_REG_EX, '') // remove all of the text element codes invisible character
* }
* });
* ```
*/
static each(elm: Node, callback: (node: Node) => void | boolean, leftToRight?: boolean): boolean;
static eachGen(root: Node, leftToRight?: boolean): Generator<Node>;
private static runInStack;
/**
* Find next/prev node what `condition(next) === true`
*/
static findWithCurrent(node: Node, condition: NodeCondition, root: HTMLElement | Node, sibling?: 'nextSibling' | 'previousSibling', child?: 'firstChild' | 'lastChild'): Nullable<Node>;
/**
* Get not empty sibling
*/
static findSibling(node: Node, left?: boolean, cond?: (n: Node) => boolean): Nullable<Node>;
/**
* Returns the nearest non-empty sibling
*/
static findNotEmptySibling(node: Node, left: boolean): Nullable<Node>;
/**
* Returns the nearest non-empty neighbor
*/
static findNotEmptyNeighbor(node: Node, left: boolean, root: HTMLElement): Nullable<Node>;
static sibling(node: Node, left?: boolean): Nullable<Node>;
/**
* It goes through all the elements in ascending order, and checks to see if they meet the predetermined condition
*/
static up<T extends HTMLElement>(node: Nullable<Node>, condition: NodeCondition, root?: Node, checkRoot?: boolean): Nullable<T>;
/**
* Find parent by tag name
*/
static closest<T extends HTMLElement, K extends HTMLTagNames>(node: Nullable<Node>, tags: K, root: HTMLElement): Nullable<HTMLElementTagNameMap[K]>;
static closest<T extends HTMLElement, K extends keyof HTMLElementTagNameMap>(node: Nullable<Node>, tags: Set<K>, root: HTMLElement): Nullable<HTMLElementTagNameMap[K]>;
static closest<T extends HTMLElement, K extends keyof HTMLElementTagNameMap>(node: Nullable<Node>, tags: K[], root: HTMLElement): Nullable<HTMLElementTagNameMap[K]>;
static closest<T extends HTMLElement>(node: Nullable<Node>, condition: NodeCondition, root: HTMLElement): Nullable<T>;
/**
* Furthest parent node matching condition
*/
static furthest<T extends HTMLElement>(node: Nullable<Node>, condition: NodeCondition, root: HTMLElement): Nullable<T>;
/**
* Append new element in the start of root
*/
static appendChildFirst(root: HTMLElement, newElement: HTMLElement | DocumentFragment): void;
/**
* Insert newElement after element
*/
static after(elm: Node, newElement: Node | DocumentFragment): void;
/**
* Insert newElement before element
*/
static before(elm: Node, newElement: Node | DocumentFragment): void;
/**
* Insert newElement as first child inside element
*/
static prepend(root: Node, newElement: Node | DocumentFragment): void;
/**
* Insert newElement as last child inside element
*/
static append(root: Node, newElements: Array<Node | DocumentFragment>): void;
static append(root: Node, newElement: Node | DocumentFragment): void;
/**
* Move all content to another element
*/
static moveContent(from: Node, to: Node, inStart?: boolean, filter?: (node: Node) => boolean): void;
/**
* Check root contains child or equal child
*/
static isOrContains(root: Node, child: Node, onlyContains?: boolean): boolean;
/**
* Safe remove element from DOM
*/
static safeRemove(...nodes: unknown[]): void;
static safeInsertNode(range: Range, node: Node): void;
/**
* Hide element
*/
static hide(node: Nullable<HTMLElement>): void;
/**
* Show element
*/
static show(node: Nullable<HTMLElement>): void;
/**
* Check if element is some tag
*/
static isTag<K extends HTMLTagNames>(node: Node | null | undefined | false | EventTarget, tagName: K): node is HTMLElementTagNameMap[K];
static isTag<K extends HTMLTagNames>(node: Node | null | undefined | false | EventTarget, tagNames: Set<K>): node is HTMLElementTagNameMap[K];
/**
* Marks an item as temporary
*/
static markTemporary<K extends HTMLElement>(element: K, attributes?: IDictionary): K;
/**
* Check if element is temporary
*/
static isTemporary(element: unknown): boolean;
/**
* Replace temporary elements from string
*/
static replaceTemporaryFromString(value: string): string;
/**
* Get temporary list
*/
static temporaryList(root: HTMLElement): HTMLElement[];
}

739
node_modules/jodit/esm/core/dom/dom.js generated vendored Normal file
View File

@@ -0,0 +1,739 @@
/*!
* 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 * as consts from "../constants.js";
import { globalDocument, INSEPARABLE_TAGS, LIST_TAGS, NO_EMPTY_TAGS, TEMP_ATTR } from "../constants.js";
import { toArray } from "../helpers/array/to-array.js";
import { isArray, isFunction, isHTML, isMarker, isSet, isString, isVoid } from "../helpers/checker/index.js";
import { trim } from "../helpers/string/trim.js";
import { $$, assert, attr, call, css, dataBind, error } from "../helpers/utils/index.js";
/**
* Module for working with DOM
*/
export class Dom {
constructor() {
throw new Error('Dom is static module');
}
/**
* Remove all content from element
*/
static detach(node) {
while (node && node.firstChild) {
node.removeChild(node.firstChild);
}
}
/**
* Wrap all inline next siblings
*/
static wrapNextInline(current, tag, editor) {
let tmp;
const first = current;
let last = current;
editor.s.save();
let needFindNext = false;
do {
needFindNext = false;
tmp = last.nextSibling;
if (tmp && !Dom.isBlock(tmp) && !Dom.isTag(tmp, 'br')) {
needFindNext = true;
last = tmp;
}
} while (needFindNext);
return Dom.__wrapElements(tag, editor, first, last);
}
static __wrapElements(tag, editor, first, last) {
const wrapper = isString(tag) ? editor.createInside.element(tag) : tag;
if (first.parentNode) {
first.parentNode.insertBefore(wrapper, first);
}
let next = first;
while (next) {
next = first.nextSibling;
wrapper.appendChild(first);
if (first === last || !next) {
break;
}
first = next;
}
editor.s.restore();
return wrapper;
}
/**
* Wrap all inline siblings
*/
static wrapInline(current, tag, editor) {
let tmp;
let first = current;
let last = current;
editor.s.save();
let needFindNext = false;
do {
needFindNext = false;
tmp = first.previousSibling;
if (tmp && !Dom.isBlock(tmp)) {
needFindNext = true;
first = tmp;
}
} while (needFindNext);
do {
needFindNext = false;
tmp = last.nextSibling;
if (tmp && !Dom.isBlock(tmp)) {
needFindNext = true;
last = tmp;
}
} while (needFindNext);
return Dom.__wrapElements(tag, editor, first, last);
}
/**
* Wrap node inside another node
*/
static wrap(current, tag, create) {
const wrapper = isString(tag) ? create.element(tag) : tag;
if (Dom.isNode(current)) {
if (!current.parentNode) {
throw error('Element should be in DOM');
}
current.parentNode.insertBefore(wrapper, current);
wrapper.appendChild(current);
}
else {
const fragment = current.extractContents();
current.insertNode(wrapper);
wrapper.appendChild(fragment);
}
return wrapper;
}
/**
* Remove parent of node and insert this node instead that parent
*/
static unwrap(node) {
const parent = node.parentNode;
if (parent) {
while (node.firstChild) {
parent.insertBefore(node.firstChild, node);
}
Dom.safeRemove(node);
}
}
/**
* Call functions for all nodes between `start` and `end`
*/
static between(start, end, callback) {
let next = start;
while (next && next !== end) {
if (start !== next && callback(next)) {
break;
}
let step = next.firstChild || next.nextSibling;
if (!step) {
while (next && !next.nextSibling) {
next = next.parentNode;
}
step = next === null || next === void 0 ? void 0 : next.nextSibling;
}
next = step;
}
}
static replace(elm, newTagName, create, withAttributes = false, notMoveContent = false) {
if (isHTML(newTagName)) {
assert(create, 'Need create instance for new tag');
newTagName = create.fromHTML(newTagName);
}
let tag;
if (isString(newTagName)) {
assert(create, 'Need create instance for new tag');
tag = create.element(newTagName);
}
else {
tag = newTagName;
}
if (!notMoveContent) {
while (elm.firstChild) {
tag.appendChild(elm.firstChild);
}
}
if (withAttributes && Dom.isElement(elm) && Dom.isElement(tag)) {
toArray(elm.attributes).forEach(attr => {
tag.setAttribute(attr.name, attr.value);
});
}
if (elm.parentNode) {
elm.parentNode.replaceChild(tag, elm);
}
return tag;
}
/**
* Checks whether the Node text and blank (in this case it may contain invisible auxiliary characters ,
* it is also empty )
*
* @param node - The element of wood to be checked
*/
static isEmptyTextNode(node) {
return (Dom.isText(node) &&
(!node.nodeValue ||
node.nodeValue
.replace(consts.INVISIBLE_SPACE_REG_EXP(), '')
.trim().length === 0));
}
static isEmptyContent(node) {
return Dom.each(node, (elm) => Dom.isEmptyTextNode(elm));
}
/**
* The node is editable
*/
static isContentEditable(node, root) {
return (Dom.isNode(node) &&
!Dom.closest(node, elm => Dom.isElement(elm) &&
elm.getAttribute('contenteditable') === 'false', root));
}
static isEmpty(node, condNoEmptyElement = NO_EMPTY_TAGS) {
if (!node) {
return true;
}
let cond;
if (!isFunction(condNoEmptyElement)) {
cond = (elm) => condNoEmptyElement.has(elm.nodeName.toLowerCase());
}
else {
cond = condNoEmptyElement;
}
const emptyText = (node) => node.nodeValue == null || trim(node.nodeValue).length === 0;
if (Dom.isText(node)) {
return emptyText(node);
}
return (!(Dom.isElement(node) && cond(node)) &&
Dom.each(node, (elm) => {
if ((Dom.isText(elm) && !emptyText(elm)) ||
(Dom.isElement(elm) && cond(elm))) {
return false;
}
}));
}
/**
* Returns true if it is a DOM node
*/
static isNode(object) {
// Duck-typing
return Boolean(object &&
isString(object.nodeName) &&
typeof object.nodeType === 'number' &&
object.childNodes &&
isFunction(object.appendChild));
}
/**
* Check if element is table cell
*/
static isCell(elm) {
return (Dom.isNode(elm) && (elm.nodeName === 'TD' || elm.nodeName === 'TH'));
}
/**
* Check if element is a list element UL or OL
*/
static isList(elm) {
return Dom.isTag(elm, LIST_TAGS);
}
/**
* Check if element is a part of list element LI
*/
static isLeaf(elm) {
return Dom.isTag(elm, 'li');
}
/**
* Check is element is Image element
*/
static isImage(elm) {
return (Dom.isNode(elm) && /^(img|svg|picture|canvas)$/i.test(elm.nodeName));
}
/**
* Check the `node` is a block element
* @param node - Object to check
*/
static isBlock(node) {
return (!isVoid(node) &&
typeof node === 'object' &&
Dom.isNode(node) &&
consts.IS_BLOCK.test(node.nodeName));
}
/**
* Check if element is text node
*/
static isText(node) {
return Boolean(node && node.nodeType === Node.TEXT_NODE);
}
/**
* Check if element is comment node
*/
static isComment(node) {
return Boolean(node && node.nodeType === Node.COMMENT_NODE);
}
/**
* Check if element is element node
*/
static isElement(node) {
var _a;
if (!Dom.isNode(node)) {
return false;
}
const win = (_a = node.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView;
return Boolean(win && node.nodeType === Node.ELEMENT_NODE);
}
/**
* Check if element is document fragment
*/
static isFragment(node) {
var _a;
if (!Dom.isNode(node)) {
return false;
}
const win = (_a = node.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView;
return Boolean(win && node.nodeType === Node.DOCUMENT_FRAGMENT_NODE);
}
/**
* Check if element is HTMLElement node
*/
static isHTMLElement(node) {
var _a;
if (!Dom.isNode(node)) {
return false;
}
const win = (_a = node.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView;
return Boolean(win && node instanceof win.HTMLElement);
}
/**
* Check element is inline block
*/
static isInlineBlock(node) {
return (Dom.isElement(node) &&
!/^(BR|HR)$/i.test(node.tagName) &&
['inline', 'inline-block'].indexOf(css(node, 'display').toString()) !== -1);
}
/**
* It's block and it can be split
*/
static canSplitBlock(node) {
return (!isVoid(node) &&
Dom.isHTMLElement(node) &&
Dom.isBlock(node) &&
!/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) &&
node.style !== undefined &&
!/^(fixed|absolute)/i.test(node.style.position));
}
/**
* Get last matched node inside root
*/
static last(root, condition) {
let last = root === null || root === void 0 ? void 0 : root.lastChild;
if (!last) {
return null;
}
do {
if (condition(last)) {
return last;
}
let next = last.lastChild;
if (!next) {
next = last.previousSibling;
}
if (!next && last.parentNode !== root) {
do {
last = last.parentNode;
} while (last &&
!(last === null || last === void 0 ? void 0 : last.previousSibling) &&
last.parentNode !== root);
next = last === null || last === void 0 ? void 0 : last.previousSibling;
}
last = next;
} while (last);
return null;
}
/**
* Find previous node
*/
static prev(node, condition, root, withChild = true) {
return Dom.find(node, condition, root, false, withChild);
}
/**
* Find next node what `condition(next) === true`
*/
static next(node, condition, root, withChild = true) {
return Dom.find(node, condition, root, true, withChild);
}
static prevWithClass(node, className) {
return Dom.prev(node, node => {
return (Dom.isElement(node) && node.classList.contains(className));
}, node.parentNode);
}
static nextWithClass(node, className) {
return Dom.next(node, elm => Dom.isElement(elm) && elm.classList.contains(className), node.parentNode);
}
/**
* Find next/prev node what `condition(next) === true`
*/
static find(node, condition, root, leftToRight = true, withChild = true) {
const gen = this.nextGen(node, root, leftToRight, withChild);
let item = gen.next();
while (!item.done) {
if (condition(item.value)) {
return item.value;
}
item = gen.next();
}
return null;
}
/**
* Find next/prev node what `condition(next) === true`
*/
static *nextGen(start, root, leftToRight = true, withChild = true) {
const stack = [];
let currentNode = start;
do {
let next = leftToRight
? currentNode.nextSibling
: currentNode.previousSibling;
while (next) {
stack.unshift(next);
next = leftToRight ? next.nextSibling : next.previousSibling;
}
yield* this.runInStack(start, stack, leftToRight, withChild);
currentNode = currentNode.parentNode;
} while (currentNode && currentNode !== root);
return null;
}
/**
* It goes through all the internal elements of the node, causing a callback function
*
* @param elm - the element whose children and descendants you want to iterate over
* @param callback - It called for each item found
* @example
* ```javascript
* Jodit.modules.Dom.each(editor.s.current(), function (node) {
* if (node.nodeType === Node.TEXT_NODE) {
* node.nodeValue = node.nodeValue.replace(Jodit.INVISIBLE_SPACE_REG_EX, '') // remove all of the text element codes invisible character
* }
* });
* ```
*/
static each(elm, callback, leftToRight = true) {
const gen = this.eachGen(elm, leftToRight);
let item = gen.next();
while (!item.done) {
if (callback(item.value) === false) {
return false;
}
item = gen.next();
}
return true;
}
static eachGen(root, leftToRight = true) {
return this.runInStack(root, [root], leftToRight);
}
static *runInStack(start, stack, leftToRight, withChild = true) {
while (stack.length) {
const item = stack.pop();
if (withChild) {
let child = leftToRight ? item.lastChild : item.firstChild;
while (child) {
stack.push(child);
child = leftToRight
? child.previousSibling
: child.nextSibling;
}
}
if (start !== item) {
yield item;
}
}
}
/**
* Find next/prev node what `condition(next) === true`
*/
static findWithCurrent(node, condition, root, sibling = 'nextSibling', child = 'firstChild') {
let next = node;
do {
if (condition(next)) {
return next || null;
}
if (child && next && next[child]) {
const nextOne = Dom.findWithCurrent(next[child], condition, next, sibling, child);
if (nextOne) {
return nextOne;
}
}
while (next && !next[sibling] && next !== root) {
next = next.parentNode;
}
if (next && next[sibling] && next !== root) {
next = next[sibling];
}
} while (next && next !== root);
return null;
}
/**
* Get not empty sibling
*/
static findSibling(node, left = true, cond = (n) => !Dom.isEmptyTextNode(n)) {
let sibling = Dom.sibling(node, left);
while (sibling && !cond(sibling)) {
sibling = Dom.sibling(sibling, left);
}
return sibling && cond(sibling) ? sibling : null;
}
/**
* Returns the nearest non-empty sibling
*/
static findNotEmptySibling(node, left) {
return Dom.findSibling(node, left, n => {
var _a;
return (!Dom.isEmptyTextNode(n) &&
Boolean(!Dom.isText(n) || (((_a = n.nodeValue) === null || _a === void 0 ? void 0 : _a.length) && trim(n.nodeValue))));
});
}
/**
* Returns the nearest non-empty neighbor
*/
static findNotEmptyNeighbor(node, left, root) {
return call(left ? Dom.prev : Dom.next, node, n => Boolean(n &&
(!(Dom.isText(n) || Dom.isComment(n)) ||
trim((n === null || n === void 0 ? void 0 : n.nodeValue) || '').length)), root);
}
static sibling(node, left) {
return left ? node.previousSibling : node.nextSibling;
}
/**
* It goes through all the elements in ascending order, and checks to see if they meet the predetermined condition
*/
static up(node, condition, root, checkRoot = false) {
let start = node;
if (!start) {
return null;
}
do {
if (condition(start)) {
return start;
}
if (start === root || !start.parentNode) {
break;
}
start = start.parentNode;
} while (start && start !== root);
if (start === root && checkRoot && condition(start)) {
return start;
}
return null;
}
static closest(node, tagsOrCondition, root) {
let condition;
const lc = (s) => s.toLowerCase();
if (isFunction(tagsOrCondition)) {
condition = tagsOrCondition;
}
else if (isArray(tagsOrCondition) || isSet(tagsOrCondition)) {
const set = isSet(tagsOrCondition)
? tagsOrCondition
: new Set(tagsOrCondition.map(lc));
condition = (tag) => Boolean(tag && set.has(lc(tag.nodeName)));
}
else {
condition = (tag) => Boolean(tag && lc(tagsOrCondition) === lc(tag.nodeName));
}
return Dom.up(node, condition, root);
}
/**
* Furthest parent node matching condition
*/
static furthest(node, condition, root) {
let matchedParent = null, current = node === null || node === void 0 ? void 0 : node.parentElement;
while (current && current !== root) {
if (condition(current)) {
matchedParent = current;
}
current = current === null || current === void 0 ? void 0 : current.parentElement;
}
return matchedParent;
}
/**
* Append new element in the start of root
*/
static appendChildFirst(root, newElement) {
const child = root.firstChild;
if (child) {
if (child !== newElement) {
root.insertBefore(newElement, child);
}
}
else {
root.appendChild(newElement);
}
}
/**
* Insert newElement after element
*/
static after(elm, newElement) {
const { parentNode } = elm;
if (!parentNode) {
return;
}
if (parentNode.lastChild === elm) {
parentNode.appendChild(newElement);
}
else {
parentNode.insertBefore(newElement, elm.nextSibling);
}
}
/**
* Insert newElement before element
*/
static before(elm, newElement) {
const { parentNode } = elm;
if (!parentNode) {
return;
}
parentNode.insertBefore(newElement, elm);
}
/**
* Insert newElement as first child inside element
*/
static prepend(root, newElement) {
root.insertBefore(newElement, root.firstChild);
}
static append(root, newElement) {
if (isArray(newElement)) {
newElement.forEach(node => {
this.append(root, node);
});
}
else {
root.appendChild(newElement);
}
}
/**
* Move all content to another element
*/
static moveContent(from, to, inStart = false, filter = () => true) {
const fragment = (from.ownerDocument || globalDocument).createDocumentFragment();
toArray(from.childNodes)
.filter(elm => {
if (filter(elm)) {
return true;
}
Dom.safeRemove(elm);
return false;
})
.forEach((node) => {
fragment.appendChild(node);
});
if (!inStart || !to.firstChild) {
to.appendChild(fragment);
}
else {
to.insertBefore(fragment, to.firstChild);
}
}
/**
* Check root contains child or equal child
*/
static isOrContains(root, child, onlyContains = false) {
if (root === child) {
return !onlyContains;
}
return Boolean(child && root && this.up(child, nd => nd === root, root, true));
}
/**
* Safe remove element from DOM
*/
static safeRemove(...nodes) {
nodes.forEach(node => Dom.isNode(node) &&
node.parentNode &&
node.parentNode.removeChild(node));
}
static safeInsertNode(range, node) {
range.collapsed || range.deleteContents();
const child = Dom.isFragment(node) ? node.lastChild : node;
if (range.startContainer === range.endContainer &&
range.collapsed &&
Dom.isTag(range.startContainer, INSEPARABLE_TAGS)) {
Dom.after(range.startContainer, node);
}
else {
range.insertNode(node);
child && range.setStartBefore(child);
}
range.collapse(true);
// https://developer.mozilla.org/en-US/docs/Web/API/Range/insertNode
// if the new node is to be added to a text Node, that Node is split at the
// insertion point, and the insertion occurs between the two text nodes.
[node.nextSibling, node.previousSibling].forEach(n => Dom.isText(n) && !n.nodeValue && Dom.safeRemove(n));
}
/**
* Hide element
*/
static hide(node) {
if (!node) {
return;
}
dataBind(node, '__old_display', node.style.display);
node.style.display = 'none';
}
/**
* Show element
*/
static show(node) {
if (!node) {
return;
}
const display = dataBind(node, '__old_display');
if (node.style.display === 'none') {
node.style.display = display || '';
}
}
static isTag(node, tagNames) {
if (!this.isElement(node)) {
return false;
}
const nameL = node.tagName.toLowerCase();
const nameU = node.tagName.toUpperCase();
if (tagNames instanceof Set) {
return tagNames.has(nameL) || tagNames.has(nameU);
}
if (Array.isArray(tagNames)) {
throw new TypeError('Dom.isTag does not support array');
}
const tags = tagNames;
if (nameL === tags || nameU === tags) {
return true;
}
return false;
}
/**
* Marks an item as temporary
*/
static markTemporary(element, attributes) {
attributes && attr(element, attributes);
attr(element, TEMP_ATTR, true);
return element;
}
/**
* Check if element is temporary
*/
static isTemporary(element) {
if (!Dom.isElement(element)) {
return false;
}
return isMarker(element) || attr(element, TEMP_ATTR) === 'true';
}
/**
* Replace temporary elements from string
*/
static replaceTemporaryFromString(value) {
return value.replace(/<([a-z]+)[^>]+data-jodit-temp[^>]+>(.+?)<\/\1>/gi, '$2');
}
/**
* Get temporary list
*/
static temporaryList(root) {
return $$(`[${TEMP_ATTR}]`, root);
}
}

10
node_modules/jodit/esm/core/dom/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
/*!
* 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
*/
/**
* @module dom
*/
export * from "./dom";
export * from "./lazy-walker";

10
node_modules/jodit/esm/core/dom/index.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
/*!
* 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
*/
/**
* @module dom
*/
export * from "./dom.js";
export * from "./lazy-walker.js";

38
node_modules/jodit/esm/core/dom/lazy-walker.d.ts generated vendored Normal file
View File

@@ -0,0 +1,38 @@
/*!
* 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
*/
/**
* @module dom
*/
import type { IAsync, IDestructible } from "../../types/index";
import { Eventify } from "../event-emitter/eventify";
export declare class LazyWalker extends Eventify<{
visit: (node: Node) => boolean;
break: (reason?: string) => void;
end: (affect: boolean) => void;
}> implements IDestructible {
private readonly async;
private readonly options;
private workNodes;
setWork(root: Node): this;
private hadAffect;
private isWorked;
private isFinished;
constructor(async: IAsync, options?: {
readonly whatToShow?: number;
readonly reverse?: boolean;
readonly timeoutChunkSize?: number;
readonly timeout?: number;
});
private idleId;
private __schedulerController;
private _requestStarting;
break(reason?: string): void;
end(): void;
private stop;
destruct(): void;
private __workPerform;
private visitNode;
}

109
node_modules/jodit/esm/core/dom/lazy-walker.js generated vendored Normal file
View File

@@ -0,0 +1,109 @@
/*!
* 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
*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if (d = decorators[i])
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { autobind } from "../decorators/index.js";
import { Dom } from "./dom.js";
import { Eventify } from "../event-emitter/eventify.js";
export class LazyWalker extends Eventify {
setWork(root) {
if (this.isWorked) {
this.break();
}
this.workNodes = Dom.eachGen(root, !this.options.reverse);
this.isFinished = false;
this._requestStarting();
return this;
}
constructor(async, options = {}) {
super();
this.async = async;
this.options = options;
this.workNodes = null;
this.hadAffect = false;
this.isWorked = false;
this.isFinished = false;
this.idleId = 0;
this.__schedulerController = null;
}
_requestStarting() {
this.__schedulerController = new AbortController();
this.async
.schedulerPostTask(this.__workPerform, {
delay: this.options.timeout,
signal: this.__schedulerController.signal
})
.catch(() => null);
}
break(reason) {
if (this.isWorked) {
this.stop();
this.emit('break', reason);
}
}
end() {
if (this.isWorked) {
this.stop();
this.emit('end', this.hadAffect);
this.hadAffect = false;
}
}
stop() {
this.isWorked = false;
this.isFinished = true;
this.workNodes = null;
this.async.cancelIdleCallback(this.idleId);
}
destruct() {
super.destruct();
this.stop();
}
__workPerform() {
var _a;
if (this.workNodes) {
this.isWorked = true;
let count = 0;
const chunkSize = (_a = this.options.timeoutChunkSize) !== null && _a !== void 0 ? _a : 50;
while (!this.isFinished && count <= chunkSize) {
const item = this.workNodes.next();
count += 1;
if (this.visitNode(item.value)) {
this.hadAffect = true;
}
if (item.done) {
this.end();
return;
}
}
}
else {
this.end();
}
if (!this.isFinished) {
this._requestStarting();
}
}
visitNode(nodeElm) {
var _a;
if (!nodeElm ||
(this.options.whatToShow !== undefined &&
nodeElm.nodeType !== this.options.whatToShow)) {
return false;
}
return (_a = this.emit('visit', nodeElm)) !== null && _a !== void 0 ? _a : false;
}
}
__decorate([
autobind
], LazyWalker.prototype, "__workPerform", null);