@reblu/site-blocks 0.4.0 → 0.4.2
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/README.md +65 -0
- package/dist/index.cjs +68 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +68 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -51,9 +51,13 @@ declare function buildShareUrls(url: string, title: string): ShareUrls;
|
|
|
51
51
|
* `dangerouslySetInnerHTML` consumers listed above. `MarkdownRenderer` re-parses that
|
|
52
52
|
* string through `html-react-parser` into a token-styled component map
|
|
53
53
|
* (`markdown-renderer.tsx` `buildOptions`), and that map rebuilds most elements from
|
|
54
|
-
* scratch
|
|
55
|
-
*
|
|
56
|
-
*
|
|
54
|
+
* scratch. It forwards only the subset of author attributes that carries MEANING
|
|
55
|
+
* (`id`, `lang`, `dir`, `title`, `hidden`, `role`, `aria-*`, `data-*`, and the list
|
|
56
|
+
* numbering attributes) — see `PRESERVED_GLOBAL_ATTRIBUTES` there for the line and
|
|
57
|
+
* why it sits where it does. `class` and `style` in particular are guaranteed by THIS
|
|
58
|
+
* module and still dropped by that one, because the map owns presentation (REB-666).
|
|
59
|
+
* Nothing the renderer forwards widens this schema: it can only pass through what
|
|
60
|
+
* `sanitizeHtml` already allowed.
|
|
57
61
|
*
|
|
58
62
|
* REB-606: this used to run on `isomorphic-dompurify`, which pulls `jsdom` into the
|
|
59
63
|
* import graph. `jsdom`'s transitive `html-encoding-sniffer` → `@exodus/bytes` chain
|
package/dist/index.d.ts
CHANGED
|
@@ -51,9 +51,13 @@ declare function buildShareUrls(url: string, title: string): ShareUrls;
|
|
|
51
51
|
* `dangerouslySetInnerHTML` consumers listed above. `MarkdownRenderer` re-parses that
|
|
52
52
|
* string through `html-react-parser` into a token-styled component map
|
|
53
53
|
* (`markdown-renderer.tsx` `buildOptions`), and that map rebuilds most elements from
|
|
54
|
-
* scratch
|
|
55
|
-
*
|
|
56
|
-
*
|
|
54
|
+
* scratch. It forwards only the subset of author attributes that carries MEANING
|
|
55
|
+
* (`id`, `lang`, `dir`, `title`, `hidden`, `role`, `aria-*`, `data-*`, and the list
|
|
56
|
+
* numbering attributes) — see `PRESERVED_GLOBAL_ATTRIBUTES` there for the line and
|
|
57
|
+
* why it sits where it does. `class` and `style` in particular are guaranteed by THIS
|
|
58
|
+
* module and still dropped by that one, because the map owns presentation (REB-666).
|
|
59
|
+
* Nothing the renderer forwards widens this schema: it can only pass through what
|
|
60
|
+
* `sanitizeHtml` already allowed.
|
|
57
61
|
*
|
|
58
62
|
* REB-606: this used to run on `isomorphic-dompurify`, which pulls `jsdom` into the
|
|
59
63
|
* import graph. `jsdom`'s transitive `html-encoding-sniffer` → `@exodus/bytes` chain
|
package/dist/index.js
CHANGED
|
@@ -13033,6 +13033,41 @@ var HEADING_CLASSES = {
|
|
|
13033
13033
|
function hasClass(el, name) {
|
|
13034
13034
|
return typeof el.attribs.class === "string" && el.attribs.class.split(/\s+/).includes(name);
|
|
13035
13035
|
}
|
|
13036
|
+
var PRESERVED_GLOBAL_ATTRIBUTES = [
|
|
13037
|
+
// Anchor targets. In-document links ("see clause 4" → `#clause-4`) resolve to
|
|
13038
|
+
// nothing without them.
|
|
13039
|
+
"id",
|
|
13040
|
+
// Language and direction of a passage — a bilingual legal page is the normal case
|
|
13041
|
+
// here, and screen readers switch voice on it.
|
|
13042
|
+
"lang",
|
|
13043
|
+
"dir",
|
|
13044
|
+
// Advisory text the author wrote; it is content, not styling.
|
|
13045
|
+
"title",
|
|
13046
|
+
// Explicit "do not publish this". Without it a block authored as `<p hidden>`
|
|
13047
|
+
// becomes VISIBLE — publishing what the author marked as not-for-publication.
|
|
13048
|
+
"hidden",
|
|
13049
|
+
// Accessible semantics. `../lib/markdown` restores these through the sanitiser
|
|
13050
|
+
// precisely so they are not lost (REB-286's axe gate); dropping them one layer
|
|
13051
|
+
// later would undo that.
|
|
13052
|
+
"role"
|
|
13053
|
+
];
|
|
13054
|
+
var PRESERVED_ATTRIBUTE_PREFIXES = ["aria-", "data-"];
|
|
13055
|
+
var PRESERVED_TAG_ATTRIBUTES = {
|
|
13056
|
+
ol: ["start", "type"],
|
|
13057
|
+
li: ["value", "type"]
|
|
13058
|
+
};
|
|
13059
|
+
var BOOLEAN_ATTRIBUTES = /* @__PURE__ */ new Set(["hidden"]);
|
|
13060
|
+
function authorAttributes(el) {
|
|
13061
|
+
const tagSpecific = PRESERVED_TAG_ATTRIBUTES[el.name] ?? [];
|
|
13062
|
+
const preserved = {};
|
|
13063
|
+
for (const [rawName, value] of Object.entries(el.attribs)) {
|
|
13064
|
+
const name = rawName.toLowerCase();
|
|
13065
|
+
const keep = PRESERVED_GLOBAL_ATTRIBUTES.includes(name) || tagSpecific.includes(name) || PRESERVED_ATTRIBUTE_PREFIXES.some((prefix) => name.startsWith(prefix));
|
|
13066
|
+
if (!keep) continue;
|
|
13067
|
+
preserved[name] = BOOLEAN_ATTRIBUTES.has(name) ? true : value;
|
|
13068
|
+
}
|
|
13069
|
+
return preserved;
|
|
13070
|
+
}
|
|
13036
13071
|
function isExternalHref(href) {
|
|
13037
13072
|
return !!href && /^(https?:)?\/\//.test(href);
|
|
13038
13073
|
}
|
|
@@ -13042,29 +13077,46 @@ function buildOptions(headingOffset) {
|
|
|
13042
13077
|
if (!(node instanceof Element)) return void 0;
|
|
13043
13078
|
const children2 = () => domToReact(node.children, options);
|
|
13044
13079
|
const { name, attribs } = node;
|
|
13080
|
+
const author = authorAttributes(node);
|
|
13045
13081
|
const headingMatch = /^h([1-6])$/.exec(name);
|
|
13046
13082
|
if (headingMatch) {
|
|
13047
13083
|
const rendered = Math.min(6, Number(headingMatch[1]) + headingOffset);
|
|
13048
13084
|
const Tag = `h${rendered}`;
|
|
13049
|
-
return /* @__PURE__ */ jsx(Tag, { className: HEADING_CLASSES[rendered], children: children2() });
|
|
13085
|
+
return /* @__PURE__ */ jsx(Tag, { ...author, className: HEADING_CLASSES[rendered], children: children2() });
|
|
13050
13086
|
}
|
|
13051
13087
|
switch (name) {
|
|
13052
13088
|
case "p":
|
|
13053
|
-
return /* @__PURE__ */ jsx("p", { className: "my-4 leading-relaxed text-foreground/90", children: children2() });
|
|
13089
|
+
return /* @__PURE__ */ jsx("p", { ...author, className: "my-4 leading-relaxed text-foreground/90", children: children2() });
|
|
13054
13090
|
case "ul":
|
|
13055
|
-
return /* @__PURE__ */ jsx("ul", { className: hasClass(node, "contains-task-list") ? "list-none pl-0 my-4 space-y-1" : "list-disc ml-6 my-4", children: children2() });
|
|
13091
|
+
return /* @__PURE__ */ jsx("ul", { ...author, className: hasClass(node, "contains-task-list") ? "list-none pl-0 my-4 space-y-1" : "list-disc ml-6 my-4", children: children2() });
|
|
13056
13092
|
case "ol":
|
|
13057
|
-
return /* @__PURE__ */ jsx("ol", { className: "list-decimal ml-6 my-4", children: children2() });
|
|
13093
|
+
return /* @__PURE__ */ jsx("ol", { ...author, className: "list-decimal ml-6 my-4", children: children2() });
|
|
13058
13094
|
case "li":
|
|
13059
|
-
return /* @__PURE__ */ jsx("li", { className: hasClass(node, "task-list-item") ? "flex items-start gap-2 my-1" : "my-1", children: children2() });
|
|
13095
|
+
return /* @__PURE__ */ jsx("li", { ...author, className: hasClass(node, "task-list-item") ? "flex items-start gap-2 my-1" : "my-1", children: children2() });
|
|
13060
13096
|
case "blockquote":
|
|
13061
|
-
return /* @__PURE__ */ jsx(
|
|
13097
|
+
return /* @__PURE__ */ jsx(
|
|
13098
|
+
"blockquote",
|
|
13099
|
+
{
|
|
13100
|
+
...author,
|
|
13101
|
+
className: "border-l-4 border-primary/50 pl-6 italic my-6 text-muted-foreground",
|
|
13102
|
+
children: children2()
|
|
13103
|
+
}
|
|
13104
|
+
);
|
|
13062
13105
|
case "pre":
|
|
13063
|
-
return /* @__PURE__ */ jsx(
|
|
13106
|
+
return /* @__PURE__ */ jsx(
|
|
13107
|
+
"pre",
|
|
13108
|
+
{
|
|
13109
|
+
...author,
|
|
13110
|
+
className: "rounded-lg border border-input bg-muted p-4 my-6 overflow-x-auto font-mono text-sm",
|
|
13111
|
+
children: children2()
|
|
13112
|
+
}
|
|
13113
|
+
);
|
|
13064
13114
|
case "code": {
|
|
13065
13115
|
const isBlock = node.parent instanceof Element && node.parent.name === "pre";
|
|
13066
|
-
if (isBlock)
|
|
13067
|
-
|
|
13116
|
+
if (isBlock) {
|
|
13117
|
+
return /* @__PURE__ */ jsx("code", { ...author, className: "block", children: children2() });
|
|
13118
|
+
}
|
|
13119
|
+
return /* @__PURE__ */ jsx("code", { ...author, className: "rounded bg-muted px-1.5 py-0.5 font-mono text-sm", children: children2() });
|
|
13068
13120
|
}
|
|
13069
13121
|
case "a": {
|
|
13070
13122
|
const href = attribs.href;
|
|
@@ -13072,6 +13124,7 @@ function buildOptions(headingOffset) {
|
|
|
13072
13124
|
return /* @__PURE__ */ jsx(
|
|
13073
13125
|
"a",
|
|
13074
13126
|
{
|
|
13127
|
+
...author,
|
|
13075
13128
|
href,
|
|
13076
13129
|
className: "text-primary underline underline-offset-4 hover:text-primary/80",
|
|
13077
13130
|
...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
@@ -13088,6 +13141,7 @@ function buildOptions(headingOffset) {
|
|
|
13088
13141
|
/* @__PURE__ */ jsx(
|
|
13089
13142
|
"img",
|
|
13090
13143
|
{
|
|
13144
|
+
...author,
|
|
13091
13145
|
src: attribs.src,
|
|
13092
13146
|
alt: attribs.alt ?? "",
|
|
13093
13147
|
loading: "lazy",
|
|
@@ -13099,6 +13153,7 @@ function buildOptions(headingOffset) {
|
|
|
13099
13153
|
return /* @__PURE__ */ jsx("div", { className: "relative my-6 aspect-video w-full overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx(
|
|
13100
13154
|
"iframe",
|
|
13101
13155
|
{
|
|
13156
|
+
...author,
|
|
13102
13157
|
src: attribs.src,
|
|
13103
13158
|
title: attribs.title ?? "Embedded video",
|
|
13104
13159
|
allow: attribs.allow ?? "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
|
|
@@ -13107,13 +13162,13 @@ function buildOptions(headingOffset) {
|
|
|
13107
13162
|
}
|
|
13108
13163
|
) });
|
|
13109
13164
|
case "hr":
|
|
13110
|
-
return /* @__PURE__ */ jsx("hr", { className: "my-8 border-muted-foreground/30" });
|
|
13165
|
+
return /* @__PURE__ */ jsx("hr", { ...author, className: "my-8 border-muted-foreground/30" });
|
|
13111
13166
|
case "strong":
|
|
13112
|
-
return /* @__PURE__ */ jsx("strong", { className: "font-bold text-foreground", children: children2() });
|
|
13167
|
+
return /* @__PURE__ */ jsx("strong", { ...author, className: "font-bold text-foreground", children: children2() });
|
|
13113
13168
|
case "em":
|
|
13114
|
-
return /* @__PURE__ */ jsx("em", { className: "italic", children: children2() });
|
|
13169
|
+
return /* @__PURE__ */ jsx("em", { ...author, className: "italic", children: children2() });
|
|
13115
13170
|
case "del":
|
|
13116
|
-
return /* @__PURE__ */ jsx("del", { className: "line-through", children: children2() });
|
|
13171
|
+
return /* @__PURE__ */ jsx("del", { ...author, className: "line-through", children: children2() });
|
|
13117
13172
|
default:
|
|
13118
13173
|
return void 0;
|
|
13119
13174
|
}
|