@reblu/site-blocks 0.16.0 → 0.17.0
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/CHANGELOG.md +11 -0
- package/dist/index.cjs +58 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +170 -115
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @reblu/site-blocks
|
|
2
2
|
|
|
3
|
+
## 0.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a42846c: `MarkdownRenderer` gains an optional `images` prop (`MarkdownImageOptions`): `allowedUrlPrefixes` keeps only images whose normalised URL starts with one of the given prefixes (any other image is dropped), a paragraph holding only an image renders as `<figure>` with the image title as `<figcaption>`, and `render` lets a Next.js consumer render allowed images with `next/image`. Without the prop, images render exactly as before.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [7a6f8c1]
|
|
12
|
+
- @reblu/site-contracts@1.18.0
|
|
13
|
+
|
|
3
14
|
## 0.16.0
|
|
4
15
|
|
|
5
16
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -13196,6 +13196,16 @@ var HTML_TO_DOM_OPTIONS = { lowerCaseAttributeNames: false };
|
|
|
13196
13196
|
function parse3(html5, options) {
|
|
13197
13197
|
return (0, import_html_react_parser.domToReact)((0, import_html_react_parser.htmlToDOM)(html5, HTML_TO_DOM_OPTIONS), options);
|
|
13198
13198
|
}
|
|
13199
|
+
function isAllowedImage(src, prefixes) {
|
|
13200
|
+
if (!src) return false;
|
|
13201
|
+
let url;
|
|
13202
|
+
try {
|
|
13203
|
+
url = new URL(src);
|
|
13204
|
+
} catch {
|
|
13205
|
+
return false;
|
|
13206
|
+
}
|
|
13207
|
+
return prefixes.some((prefix) => url.href.startsWith(prefix));
|
|
13208
|
+
}
|
|
13199
13209
|
var HEADING_CLASSES = {
|
|
13200
13210
|
1: "text-3xl font-bold mt-8 mb-4 first:mt-0",
|
|
13201
13211
|
2: "text-2xl font-bold mt-7 mb-3 first:mt-0",
|
|
@@ -13245,10 +13255,49 @@ function authorAttributes(el) {
|
|
|
13245
13255
|
function isExternalHref(href) {
|
|
13246
13256
|
return !!href && /^(https?:)?\/\//.test(href);
|
|
13247
13257
|
}
|
|
13248
|
-
function
|
|
13258
|
+
function soleImage(p2) {
|
|
13259
|
+
let image = null;
|
|
13260
|
+
for (const child of p2.children) {
|
|
13261
|
+
if (child instanceof import_html_react_parser.Element) {
|
|
13262
|
+
if (child.name !== "img" || image) return null;
|
|
13263
|
+
image = child;
|
|
13264
|
+
} else if (child.type !== "text" || child.data?.trim()) {
|
|
13265
|
+
return null;
|
|
13266
|
+
}
|
|
13267
|
+
}
|
|
13268
|
+
return image;
|
|
13269
|
+
}
|
|
13270
|
+
function buildOptions(headingOffset, images) {
|
|
13271
|
+
const renderImage = (img) => {
|
|
13272
|
+
if (!images || !isAllowedImage(img.attribs.src, images.allowedUrlPrefixes)) return null;
|
|
13273
|
+
const image = { src: img.attribs.src, alt: img.attribs.alt ?? "" };
|
|
13274
|
+
if (images.render) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: images.render(image) });
|
|
13275
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
13276
|
+
"img",
|
|
13277
|
+
{
|
|
13278
|
+
src: image.src,
|
|
13279
|
+
alt: image.alt,
|
|
13280
|
+
loading: "lazy",
|
|
13281
|
+
decoding: "async",
|
|
13282
|
+
className: "rounded-lg w-full h-auto"
|
|
13283
|
+
}
|
|
13284
|
+
);
|
|
13285
|
+
};
|
|
13249
13286
|
const options = {
|
|
13250
13287
|
replace: (node) => {
|
|
13251
13288
|
if (!(node instanceof import_html_react_parser.Element)) return void 0;
|
|
13289
|
+
if (images && node.name === "p") {
|
|
13290
|
+
const img = soleImage(node);
|
|
13291
|
+
if (img) {
|
|
13292
|
+
const rendered = renderImage(img);
|
|
13293
|
+
if (rendered === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {});
|
|
13294
|
+
const caption = img.attribs.title?.trim();
|
|
13295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figure", { className: "my-8", children: [
|
|
13296
|
+
rendered,
|
|
13297
|
+
caption ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("figcaption", { className: "mt-2 text-center text-sm text-muted-foreground", children: caption }) : null
|
|
13298
|
+
] });
|
|
13299
|
+
}
|
|
13300
|
+
}
|
|
13252
13301
|
const children2 = () => (0, import_html_react_parser.domToReact)(node.children, options);
|
|
13253
13302
|
const { name, attribs } = node;
|
|
13254
13303
|
const author = authorAttributes(node);
|
|
@@ -13307,6 +13356,7 @@ function buildOptions(headingOffset) {
|
|
|
13307
13356
|
);
|
|
13308
13357
|
}
|
|
13309
13358
|
case "img":
|
|
13359
|
+
if (images) return renderImage(node) ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {});
|
|
13310
13360
|
if (!attribs.src) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {});
|
|
13311
13361
|
return (
|
|
13312
13362
|
// Plain <img> keeps the block portable — a distributable can't assume a
|
|
@@ -13350,10 +13400,15 @@ function buildOptions(headingOffset) {
|
|
|
13350
13400
|
};
|
|
13351
13401
|
return options;
|
|
13352
13402
|
}
|
|
13353
|
-
function MarkdownRenderer({
|
|
13403
|
+
function MarkdownRenderer({
|
|
13404
|
+
content,
|
|
13405
|
+
className,
|
|
13406
|
+
headingOffset = 0,
|
|
13407
|
+
images
|
|
13408
|
+
}) {
|
|
13354
13409
|
const html5 = markdownToSafeHtml(content);
|
|
13355
13410
|
if (!html5) return null;
|
|
13356
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: slotClassName("max-w-none", "", className), "data-slot": "markdown", children: parse3(html5, buildOptions(headingOffset)) });
|
|
13411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: slotClassName("max-w-none", "", className), "data-slot": "markdown", children: parse3(html5, buildOptions(headingOffset, images)) });
|
|
13357
13412
|
}
|
|
13358
13413
|
function SafeHtml({ html: html5, className, headingOffset = 0 }) {
|
|
13359
13414
|
if (!html5) return null;
|