@camstack/ui-library 1.2.275 → 1.2.276
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/composites/sanitize-info-html.d.ts +16 -0
- package/dist/index.cjs +62 -51
- package/dist/index.js +62 -51
- package/package.json +1 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitize a small HTML subset for `ConfigInfoField.format='html'`.
|
|
3
|
+
*
|
|
4
|
+
* Only `<a>`, `<ul>`, `<ol>`, `<li>`, `<strong>`, `<em>`, `<code>`,
|
|
5
|
+
* `<br>`, `<p>`, and `<span>` are kept. On anchors, only `href` and a
|
|
6
|
+
* normalised `target`/`rel` are emitted; everything else is dropped
|
|
7
|
+
* (including event handlers and inline styles).
|
|
8
|
+
*
|
|
9
|
+
* Allowed `href` schemes: `http(s):`, `mailto:`, and **root-relative**
|
|
10
|
+
* paths (`/addon/…`). Root-relative links stay same-tab (session cookie);
|
|
11
|
+
* absolute http(s) open in a new tab. Protocol-relative (`//…`) is refused.
|
|
12
|
+
*
|
|
13
|
+
* The input comes from addon-authored copy bundled at build time —
|
|
14
|
+
* sanitisation is defence in depth rather than primary trust boundary.
|
|
15
|
+
*/
|
|
16
|
+
export declare function sanitizeInfoHtml(html: string): string;
|
package/dist/index.cjs
CHANGED
|
@@ -7249,6 +7249,68 @@ function ConfigIconFieldControl({ label, value, defaultKey, disabled, onChange }
|
|
|
7249
7249
|
});
|
|
7250
7250
|
}
|
|
7251
7251
|
//#endregion
|
|
7252
|
+
//#region src/composites/sanitize-info-html.ts
|
|
7253
|
+
/**
|
|
7254
|
+
* Sanitize a small HTML subset for `ConfigInfoField.format='html'`.
|
|
7255
|
+
*
|
|
7256
|
+
* Only `<a>`, `<ul>`, `<ol>`, `<li>`, `<strong>`, `<em>`, `<code>`,
|
|
7257
|
+
* `<br>`, `<p>`, and `<span>` are kept. On anchors, only `href` and a
|
|
7258
|
+
* normalised `target`/`rel` are emitted; everything else is dropped
|
|
7259
|
+
* (including event handlers and inline styles).
|
|
7260
|
+
*
|
|
7261
|
+
* Allowed `href` schemes: `http(s):`, `mailto:`, and **root-relative**
|
|
7262
|
+
* paths (`/addon/…`). Root-relative links stay same-tab (session cookie);
|
|
7263
|
+
* absolute http(s) open in a new tab. Protocol-relative (`//…`) is refused.
|
|
7264
|
+
*
|
|
7265
|
+
* The input comes from addon-authored copy bundled at build time —
|
|
7266
|
+
* sanitisation is defence in depth rather than primary trust boundary.
|
|
7267
|
+
*/
|
|
7268
|
+
function sanitizeInfoHtml(html) {
|
|
7269
|
+
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
7270
|
+
const ALLOWED_TAGS = new Set([
|
|
7271
|
+
"A",
|
|
7272
|
+
"UL",
|
|
7273
|
+
"OL",
|
|
7274
|
+
"LI",
|
|
7275
|
+
"STRONG",
|
|
7276
|
+
"EM",
|
|
7277
|
+
"CODE",
|
|
7278
|
+
"BR",
|
|
7279
|
+
"P",
|
|
7280
|
+
"SPAN",
|
|
7281
|
+
"B"
|
|
7282
|
+
]);
|
|
7283
|
+
const doc = new DOMParser().parseFromString(`<div>${html}</div>`, "text/html");
|
|
7284
|
+
const root = doc.body.firstElementChild;
|
|
7285
|
+
if (!root) return "";
|
|
7286
|
+
const walk = (node) => {
|
|
7287
|
+
const children = Array.from(node.children);
|
|
7288
|
+
for (const child of children) {
|
|
7289
|
+
if (!ALLOWED_TAGS.has(child.tagName)) {
|
|
7290
|
+
const text = doc.createTextNode(child.textContent ?? "");
|
|
7291
|
+
child.replaceWith(text);
|
|
7292
|
+
continue;
|
|
7293
|
+
}
|
|
7294
|
+
const allowed = child.tagName === "A" ? new Set(["href"]) : /* @__PURE__ */ new Set();
|
|
7295
|
+
for (const attr of Array.from(child.attributes)) if (!allowed.has(attr.name)) child.removeAttribute(attr.name);
|
|
7296
|
+
if (child.tagName === "A") {
|
|
7297
|
+
const href = child.getAttribute("href") ?? "";
|
|
7298
|
+
const isHttp = /^https?:\/\//i.test(href);
|
|
7299
|
+
const isMailto = href.startsWith("mailto:");
|
|
7300
|
+
const isRootRelative = href.startsWith("/") && !href.startsWith("//");
|
|
7301
|
+
if (!isHttp && !isMailto && !isRootRelative) child.removeAttribute("href");
|
|
7302
|
+
else if (isHttp) {
|
|
7303
|
+
child.setAttribute("target", "_blank");
|
|
7304
|
+
child.setAttribute("rel", "noopener noreferrer");
|
|
7305
|
+
}
|
|
7306
|
+
}
|
|
7307
|
+
walk(child);
|
|
7308
|
+
}
|
|
7309
|
+
};
|
|
7310
|
+
walk(root);
|
|
7311
|
+
return root.innerHTML;
|
|
7312
|
+
}
|
|
7313
|
+
//#endregion
|
|
7252
7314
|
//#region ../../node_modules/clsx/dist/clsx.mjs
|
|
7253
7315
|
function r(e) {
|
|
7254
7316
|
var t, f, n = "";
|
|
@@ -29020,57 +29082,6 @@ var INFO_VARIANT_STYLES = {
|
|
|
29020
29082
|
text: "text-danger"
|
|
29021
29083
|
}
|
|
29022
29084
|
};
|
|
29023
|
-
/**
|
|
29024
|
-
* Sanitize a small HTML subset for `ConfigInfoField.format='html'`.
|
|
29025
|
-
*
|
|
29026
|
-
* Only `<a>`, `<ul>`, `<ol>`, `<li>`, `<strong>`, `<em>`, `<code>`,
|
|
29027
|
-
* `<br>`, and `<p>` are kept. On anchors, only `href` (http/https only)
|
|
29028
|
-
* and a normalised `target/rel` are emitted; everything else is dropped
|
|
29029
|
-
* (including event handlers and inline styles). The input comes from
|
|
29030
|
-
* addon-authored copy bundled at build time — sanitisation is defence
|
|
29031
|
-
* in depth rather than primary trust boundary.
|
|
29032
|
-
*/
|
|
29033
|
-
function sanitizeInfoHtml(html) {
|
|
29034
|
-
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
29035
|
-
const ALLOWED_TAGS = new Set([
|
|
29036
|
-
"A",
|
|
29037
|
-
"UL",
|
|
29038
|
-
"OL",
|
|
29039
|
-
"LI",
|
|
29040
|
-
"STRONG",
|
|
29041
|
-
"EM",
|
|
29042
|
-
"CODE",
|
|
29043
|
-
"BR",
|
|
29044
|
-
"P",
|
|
29045
|
-
"SPAN"
|
|
29046
|
-
]);
|
|
29047
|
-
const doc = new DOMParser().parseFromString(`<div>${html}</div>`, "text/html");
|
|
29048
|
-
const root = doc.body.firstElementChild;
|
|
29049
|
-
if (!root) return "";
|
|
29050
|
-
const walk = (node) => {
|
|
29051
|
-
const children = Array.from(node.children);
|
|
29052
|
-
for (const child of children) {
|
|
29053
|
-
if (!ALLOWED_TAGS.has(child.tagName)) {
|
|
29054
|
-
const text = doc.createTextNode(child.textContent ?? "");
|
|
29055
|
-
child.replaceWith(text);
|
|
29056
|
-
continue;
|
|
29057
|
-
}
|
|
29058
|
-
const allowed = child.tagName === "A" ? new Set(["href"]) : /* @__PURE__ */ new Set();
|
|
29059
|
-
for (const attr of Array.from(child.attributes)) if (!allowed.has(attr.name)) child.removeAttribute(attr.name);
|
|
29060
|
-
if (child.tagName === "A") {
|
|
29061
|
-
const href = child.getAttribute("href") ?? "";
|
|
29062
|
-
if (!/^https?:\/\//i.test(href) && !href.startsWith("mailto:")) child.removeAttribute("href");
|
|
29063
|
-
else {
|
|
29064
|
-
child.setAttribute("target", "_blank");
|
|
29065
|
-
child.setAttribute("rel", "noopener noreferrer");
|
|
29066
|
-
}
|
|
29067
|
-
}
|
|
29068
|
-
walk(child);
|
|
29069
|
-
}
|
|
29070
|
-
};
|
|
29071
|
-
walk(root);
|
|
29072
|
-
return root.innerHTML;
|
|
29073
|
-
}
|
|
29074
29085
|
function InfoBox({ field }) {
|
|
29075
29086
|
const styles = INFO_VARIANT_STYLES[field.variant ?? "info"] ?? INFO_VARIANT_STYLES["info"];
|
|
29076
29087
|
const isHtml = field.format === "html";
|
package/dist/index.js
CHANGED
|
@@ -7225,6 +7225,68 @@ function ConfigIconFieldControl({ label, value, defaultKey, disabled, onChange }
|
|
|
7225
7225
|
});
|
|
7226
7226
|
}
|
|
7227
7227
|
//#endregion
|
|
7228
|
+
//#region src/composites/sanitize-info-html.ts
|
|
7229
|
+
/**
|
|
7230
|
+
* Sanitize a small HTML subset for `ConfigInfoField.format='html'`.
|
|
7231
|
+
*
|
|
7232
|
+
* Only `<a>`, `<ul>`, `<ol>`, `<li>`, `<strong>`, `<em>`, `<code>`,
|
|
7233
|
+
* `<br>`, `<p>`, and `<span>` are kept. On anchors, only `href` and a
|
|
7234
|
+
* normalised `target`/`rel` are emitted; everything else is dropped
|
|
7235
|
+
* (including event handlers and inline styles).
|
|
7236
|
+
*
|
|
7237
|
+
* Allowed `href` schemes: `http(s):`, `mailto:`, and **root-relative**
|
|
7238
|
+
* paths (`/addon/…`). Root-relative links stay same-tab (session cookie);
|
|
7239
|
+
* absolute http(s) open in a new tab. Protocol-relative (`//…`) is refused.
|
|
7240
|
+
*
|
|
7241
|
+
* The input comes from addon-authored copy bundled at build time —
|
|
7242
|
+
* sanitisation is defence in depth rather than primary trust boundary.
|
|
7243
|
+
*/
|
|
7244
|
+
function sanitizeInfoHtml(html) {
|
|
7245
|
+
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
7246
|
+
const ALLOWED_TAGS = new Set([
|
|
7247
|
+
"A",
|
|
7248
|
+
"UL",
|
|
7249
|
+
"OL",
|
|
7250
|
+
"LI",
|
|
7251
|
+
"STRONG",
|
|
7252
|
+
"EM",
|
|
7253
|
+
"CODE",
|
|
7254
|
+
"BR",
|
|
7255
|
+
"P",
|
|
7256
|
+
"SPAN",
|
|
7257
|
+
"B"
|
|
7258
|
+
]);
|
|
7259
|
+
const doc = new DOMParser().parseFromString(`<div>${html}</div>`, "text/html");
|
|
7260
|
+
const root = doc.body.firstElementChild;
|
|
7261
|
+
if (!root) return "";
|
|
7262
|
+
const walk = (node) => {
|
|
7263
|
+
const children = Array.from(node.children);
|
|
7264
|
+
for (const child of children) {
|
|
7265
|
+
if (!ALLOWED_TAGS.has(child.tagName)) {
|
|
7266
|
+
const text = doc.createTextNode(child.textContent ?? "");
|
|
7267
|
+
child.replaceWith(text);
|
|
7268
|
+
continue;
|
|
7269
|
+
}
|
|
7270
|
+
const allowed = child.tagName === "A" ? new Set(["href"]) : /* @__PURE__ */ new Set();
|
|
7271
|
+
for (const attr of Array.from(child.attributes)) if (!allowed.has(attr.name)) child.removeAttribute(attr.name);
|
|
7272
|
+
if (child.tagName === "A") {
|
|
7273
|
+
const href = child.getAttribute("href") ?? "";
|
|
7274
|
+
const isHttp = /^https?:\/\//i.test(href);
|
|
7275
|
+
const isMailto = href.startsWith("mailto:");
|
|
7276
|
+
const isRootRelative = href.startsWith("/") && !href.startsWith("//");
|
|
7277
|
+
if (!isHttp && !isMailto && !isRootRelative) child.removeAttribute("href");
|
|
7278
|
+
else if (isHttp) {
|
|
7279
|
+
child.setAttribute("target", "_blank");
|
|
7280
|
+
child.setAttribute("rel", "noopener noreferrer");
|
|
7281
|
+
}
|
|
7282
|
+
}
|
|
7283
|
+
walk(child);
|
|
7284
|
+
}
|
|
7285
|
+
};
|
|
7286
|
+
walk(root);
|
|
7287
|
+
return root.innerHTML;
|
|
7288
|
+
}
|
|
7289
|
+
//#endregion
|
|
7228
7290
|
//#region ../../node_modules/clsx/dist/clsx.mjs
|
|
7229
7291
|
function r(e) {
|
|
7230
7292
|
var t, f, n = "";
|
|
@@ -28996,57 +29058,6 @@ var INFO_VARIANT_STYLES = {
|
|
|
28996
29058
|
text: "text-danger"
|
|
28997
29059
|
}
|
|
28998
29060
|
};
|
|
28999
|
-
/**
|
|
29000
|
-
* Sanitize a small HTML subset for `ConfigInfoField.format='html'`.
|
|
29001
|
-
*
|
|
29002
|
-
* Only `<a>`, `<ul>`, `<ol>`, `<li>`, `<strong>`, `<em>`, `<code>`,
|
|
29003
|
-
* `<br>`, and `<p>` are kept. On anchors, only `href` (http/https only)
|
|
29004
|
-
* and a normalised `target/rel` are emitted; everything else is dropped
|
|
29005
|
-
* (including event handlers and inline styles). The input comes from
|
|
29006
|
-
* addon-authored copy bundled at build time — sanitisation is defence
|
|
29007
|
-
* in depth rather than primary trust boundary.
|
|
29008
|
-
*/
|
|
29009
|
-
function sanitizeInfoHtml(html) {
|
|
29010
|
-
if (typeof window === "undefined" || typeof DOMParser === "undefined") return "";
|
|
29011
|
-
const ALLOWED_TAGS = new Set([
|
|
29012
|
-
"A",
|
|
29013
|
-
"UL",
|
|
29014
|
-
"OL",
|
|
29015
|
-
"LI",
|
|
29016
|
-
"STRONG",
|
|
29017
|
-
"EM",
|
|
29018
|
-
"CODE",
|
|
29019
|
-
"BR",
|
|
29020
|
-
"P",
|
|
29021
|
-
"SPAN"
|
|
29022
|
-
]);
|
|
29023
|
-
const doc = new DOMParser().parseFromString(`<div>${html}</div>`, "text/html");
|
|
29024
|
-
const root = doc.body.firstElementChild;
|
|
29025
|
-
if (!root) return "";
|
|
29026
|
-
const walk = (node) => {
|
|
29027
|
-
const children = Array.from(node.children);
|
|
29028
|
-
for (const child of children) {
|
|
29029
|
-
if (!ALLOWED_TAGS.has(child.tagName)) {
|
|
29030
|
-
const text = doc.createTextNode(child.textContent ?? "");
|
|
29031
|
-
child.replaceWith(text);
|
|
29032
|
-
continue;
|
|
29033
|
-
}
|
|
29034
|
-
const allowed = child.tagName === "A" ? new Set(["href"]) : /* @__PURE__ */ new Set();
|
|
29035
|
-
for (const attr of Array.from(child.attributes)) if (!allowed.has(attr.name)) child.removeAttribute(attr.name);
|
|
29036
|
-
if (child.tagName === "A") {
|
|
29037
|
-
const href = child.getAttribute("href") ?? "";
|
|
29038
|
-
if (!/^https?:\/\//i.test(href) && !href.startsWith("mailto:")) child.removeAttribute("href");
|
|
29039
|
-
else {
|
|
29040
|
-
child.setAttribute("target", "_blank");
|
|
29041
|
-
child.setAttribute("rel", "noopener noreferrer");
|
|
29042
|
-
}
|
|
29043
|
-
}
|
|
29044
|
-
walk(child);
|
|
29045
|
-
}
|
|
29046
|
-
};
|
|
29047
|
-
walk(root);
|
|
29048
|
-
return root.innerHTML;
|
|
29049
|
-
}
|
|
29050
29061
|
function InfoBox({ field }) {
|
|
29051
29062
|
const styles = INFO_VARIANT_STYLES[field.variant ?? "info"] ?? INFO_VARIANT_STYLES["info"];
|
|
29052
29063
|
const isHtml = field.format === "html";
|