[REL] v2.7.0

# v2.7.0

 - [IMP] runtime/utils: export htmlEscape and add tests
 - [FIX] utils: Correct validation of mount target in shadow DOM/iframe
 - [IMP] runtime: add markup tag function
This commit is contained in:
Romeo Fragomeli
2025-03-26 13:58:50 +01:00
parent e788e361c7
commit 56041bc133
4 changed files with 68 additions and 14 deletions
+65 -11
View File
@@ -276,13 +276,39 @@ function inOwnerDocument(el) {
const rootNode = el.getRootNode();
return rootNode instanceof ShadowRoot && el.ownerDocument.contains(rootNode.host);
}
/**
* Determine whether the given element is contained in a specific root documnet:
* either directly or with a shadow root in between or in an iframe.
*/
function isAttachedToDocument(element, documentElement) {
let current = element;
const shadowRoot = documentElement.defaultView.ShadowRoot;
while (current) {
if (current === documentElement) {
return true;
}
if (current.parentNode) {
current = current.parentNode;
}
else if (current instanceof shadowRoot && current.host) {
current = current.host;
}
else {
return false;
}
}
return false;
}
function validateTarget(target) {
// Get the document and HTMLElement corresponding to the target to allow mounting in iframes
const document = target && target.ownerDocument;
if (document) {
if (!document.defaultView) {
throw new OwlError("Cannot mount a component: the target document is not attached to a window (defaultView is missing)");
}
const HTMLElement = document.defaultView.HTMLElement;
if (target instanceof HTMLElement || target instanceof ShadowRoot) {
if (!document.body.contains(target instanceof HTMLElement ? target : target.host)) {
if (!isAttachedToDocument(target, document)) {
throw new OwlError("Cannot mount a component on a detached dom node");
}
return;
@@ -319,12 +345,40 @@ async function loadFile(url) {
*/
class Markup extends String {
}
/*
* Marks a value as safe, that is, a value that can be injected as HTML directly.
* It should be used to wrap the value passed to a t-out directive to allow a raw rendering.
*/
function markup(value) {
return new Markup(value);
function htmlEscape(str) {
if (str instanceof Markup) {
return str;
}
if (str === undefined) {
return markup("");
}
if (typeof str === "number") {
return markup(String(str));
}
[
["&", "&"],
["<", "&lt;"],
[">", "&gt;"],
["'", "&#x27;"],
['"', "&quot;"],
["`", "&#x60;"],
].forEach((pairs) => {
str = String(str).replace(new RegExp(pairs[0], "g"), pairs[1]);
});
return markup(str);
}
function markup(valueOrStrings, ...placeholders) {
if (!Array.isArray(valueOrStrings)) {
return new Markup(valueOrStrings);
}
const strings = valueOrStrings;
let acc = "";
let i = 0;
for (; i < placeholders.length; ++i) {
acc += strings[i] + htmlEscape(placeholders[i]);
}
acc += strings[i];
return new Markup(acc);
}
function createEventHandler(rawEvent) {
@@ -5704,7 +5758,7 @@ function compile(template, options = {
}
// do not modify manually. This file is generated by the release script.
const version = "2.6.1";
const version = "2.7.0";
// -----------------------------------------------------------------------------
// Scheduler
@@ -6172,9 +6226,9 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
});
};
export { App, Component, EventBus, OwlError, __info__, batched, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml };
export { App, Component, EventBus, OwlError, __info__, batched, blockDom, htmlEscape, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml };
__info__.date = '2025-03-05T08:37:58.580Z';
__info__.hash = '2b5cea9';
__info__.date = '2025-03-26T12:58:40.935Z';
__info__.hash = 'e788e36';
__info__.url = 'https://github.com/odoo/owl';