Odoo18-Base/addons/html_editor/static/src/utils/blocks.js
2025-01-06 10:57:38 +07:00

87 lines
2.0 KiB
JavaScript

import { closestPath, findNode } from "./dom_traversal";
const blockTagNames = [
"ADDRESS",
"ARTICLE",
"ASIDE",
"BLOCKQUOTE",
"DETAILS",
"DIALOG",
"DD",
"DIV",
"DL",
"DT",
"FIELDSET",
"FIGCAPTION",
"FIGURE",
"FOOTER",
"FORM",
"H1",
"H2",
"H3",
"H4",
"H5",
"H6",
"HEADER",
"HGROUP",
"HR",
"LI",
"MAIN",
"NAV",
"OL",
"P",
"PRE",
"SECTION",
"TABLE",
"UL",
// The following elements are not in the W3C list, for some reason.
"SELECT",
"OPTION",
"TR",
"TD",
"TBODY",
"THEAD",
"TH",
];
const computedStyles = new WeakMap();
/**
* Return true if the given node is a block-level element, false otherwise.
*
* @param node
*/
export function isBlock(node) {
if (!node || node.nodeType !== Node.ELEMENT_NODE) {
return false;
}
const tagName = node.nodeName.toUpperCase();
if (tagName === "BR") {
// A <br> is always inline but getComputedStyle(br).display mistakenly
// returns 'block' if its parent is display:flex (at least on Chrome and
// Firefox (Linux)). Browsers normally support setting a <br>'s display
// property to 'none' but any other change is not supported. Therefore
// it is safe to simply declare that a <br> is never supposed to be a
// block.
return false;
}
// The node might not be in the DOM, in which case it has no CSS values.
if (!node.isConnected) {
return blockTagNames.includes(tagName);
}
// We won't call `getComputedStyle` more than once per node.
let style = computedStyles.get(node);
if (!style) {
style = node.ownerDocument.defaultView.getComputedStyle(node);
computedStyles.set(node, style);
}
if (style.display) {
return !style.display.includes("inline") && style.display !== "contents";
}
return blockTagNames.includes(tagName);
}
export function closestBlock(node) {
return findNode(closestPath(node), (node) => isBlock(node));
}