@reblu/site-blocks 0.17.1 → 0.18.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 +6 -0
- package/README.md +28 -0
- package/dist/index.cjs +29 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -227,6 +227,14 @@ interface MarkdownRendererProps {
|
|
|
227
227
|
* the page keeps a single h1.
|
|
228
228
|
*/
|
|
229
229
|
headingOffset?: number;
|
|
230
|
+
/**
|
|
231
|
+
* Land the body's SHALLOWEST heading at `1 + headingOffset` instead of shifting every
|
|
232
|
+
* heading by a fixed amount, so standard Markdown (`##` sections) renders `<h2>` under
|
|
233
|
+
* the page `<h1>` just like the convention (`#` sections) does. Relative depth is kept
|
|
234
|
+
* and levels clamp at h6. Use it where the body sits directly under the page `<h1>`;
|
|
235
|
+
* leave it off where the body sits under its own section heading. Default `false`.
|
|
236
|
+
*/
|
|
237
|
+
normalizeHeadings?: boolean;
|
|
230
238
|
/**
|
|
231
239
|
* Restrict and render images (REB-1075). Absent: every image the sanitiser keeps is
|
|
232
240
|
* rendered as a lazy `<img>` inside its paragraph (the historical behaviour).
|
|
@@ -247,7 +255,7 @@ interface MarkdownImageOptions {
|
|
|
247
255
|
alt: string;
|
|
248
256
|
}) => React$1.ReactNode;
|
|
249
257
|
}
|
|
250
|
-
declare function MarkdownRenderer({ content, className, headingOffset, images, }: MarkdownRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
258
|
+
declare function MarkdownRenderer({ content, className, headingOffset, normalizeHeadings, images, }: MarkdownRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
251
259
|
/**
|
|
252
260
|
* Render an **already-sanitised** HTML string through the same token-driven
|
|
253
261
|
* component map as {@link MarkdownRenderer}. Consumers pass HTML that has been run
|
|
@@ -258,8 +266,10 @@ interface SafeHtmlProps {
|
|
|
258
266
|
html: string | null | undefined;
|
|
259
267
|
className?: string;
|
|
260
268
|
headingOffset?: number;
|
|
269
|
+
/** See {@link MarkdownRendererProps.normalizeHeadings}. Default `false`. */
|
|
270
|
+
normalizeHeadings?: boolean;
|
|
261
271
|
}
|
|
262
|
-
declare function SafeHtml({ html, className, headingOffset }: SafeHtmlProps): react_jsx_runtime.JSX.Element | null;
|
|
272
|
+
declare function SafeHtml({ html, className, headingOffset, normalizeHeadings, }: SafeHtmlProps): react_jsx_runtime.JSX.Element | null;
|
|
263
273
|
|
|
264
274
|
/** A heading level a caller can configure — `h1`…`h6`. */
|
|
265
275
|
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
package/dist/index.d.ts
CHANGED
|
@@ -227,6 +227,14 @@ interface MarkdownRendererProps {
|
|
|
227
227
|
* the page keeps a single h1.
|
|
228
228
|
*/
|
|
229
229
|
headingOffset?: number;
|
|
230
|
+
/**
|
|
231
|
+
* Land the body's SHALLOWEST heading at `1 + headingOffset` instead of shifting every
|
|
232
|
+
* heading by a fixed amount, so standard Markdown (`##` sections) renders `<h2>` under
|
|
233
|
+
* the page `<h1>` just like the convention (`#` sections) does. Relative depth is kept
|
|
234
|
+
* and levels clamp at h6. Use it where the body sits directly under the page `<h1>`;
|
|
235
|
+
* leave it off where the body sits under its own section heading. Default `false`.
|
|
236
|
+
*/
|
|
237
|
+
normalizeHeadings?: boolean;
|
|
230
238
|
/**
|
|
231
239
|
* Restrict and render images (REB-1075). Absent: every image the sanitiser keeps is
|
|
232
240
|
* rendered as a lazy `<img>` inside its paragraph (the historical behaviour).
|
|
@@ -247,7 +255,7 @@ interface MarkdownImageOptions {
|
|
|
247
255
|
alt: string;
|
|
248
256
|
}) => React$1.ReactNode;
|
|
249
257
|
}
|
|
250
|
-
declare function MarkdownRenderer({ content, className, headingOffset, images, }: MarkdownRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
258
|
+
declare function MarkdownRenderer({ content, className, headingOffset, normalizeHeadings, images, }: MarkdownRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
251
259
|
/**
|
|
252
260
|
* Render an **already-sanitised** HTML string through the same token-driven
|
|
253
261
|
* component map as {@link MarkdownRenderer}. Consumers pass HTML that has been run
|
|
@@ -258,8 +266,10 @@ interface SafeHtmlProps {
|
|
|
258
266
|
html: string | null | undefined;
|
|
259
267
|
className?: string;
|
|
260
268
|
headingOffset?: number;
|
|
269
|
+
/** See {@link MarkdownRendererProps.normalizeHeadings}. Default `false`. */
|
|
270
|
+
normalizeHeadings?: boolean;
|
|
261
271
|
}
|
|
262
|
-
declare function SafeHtml({ html, className, headingOffset }: SafeHtmlProps): react_jsx_runtime.JSX.Element | null;
|
|
272
|
+
declare function SafeHtml({ html, className, headingOffset, normalizeHeadings, }: SafeHtmlProps): react_jsx_runtime.JSX.Element | null;
|
|
263
273
|
|
|
264
274
|
/** A heading level a caller can configure — `h1`…`h6`. */
|
|
265
275
|
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
package/dist/index.js
CHANGED
|
@@ -13131,8 +13131,25 @@ function slotClassName(structural, defaults, consumer) {
|
|
|
13131
13131
|
// src/components/markdown-renderer.tsx
|
|
13132
13132
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
13133
13133
|
var HTML_TO_DOM_OPTIONS = { lowerCaseAttributeNames: false };
|
|
13134
|
-
function
|
|
13135
|
-
|
|
13134
|
+
function shallowestHeadingLevel(nodes) {
|
|
13135
|
+
let shallowest = null;
|
|
13136
|
+
for (const node of nodes) {
|
|
13137
|
+
if (!(node instanceof Element)) continue;
|
|
13138
|
+
const match = /^h([1-6])$/.exec(node.name);
|
|
13139
|
+
const level = match ? Number(match[1]) : shallowestHeadingLevel(node.children);
|
|
13140
|
+
if (level !== null && (shallowest === null || level < shallowest)) shallowest = level;
|
|
13141
|
+
}
|
|
13142
|
+
return shallowest;
|
|
13143
|
+
}
|
|
13144
|
+
function headingShift(nodes, headingOffset, normalize2) {
|
|
13145
|
+
if (!normalize2) return headingOffset;
|
|
13146
|
+
const shallowest = shallowestHeadingLevel(nodes);
|
|
13147
|
+
return shallowest === null ? headingOffset : 1 + headingOffset - shallowest;
|
|
13148
|
+
}
|
|
13149
|
+
function parse3(html5, headingOffset, normalizeHeadings, images) {
|
|
13150
|
+
const nodes = htmlToDOM(html5, HTML_TO_DOM_OPTIONS);
|
|
13151
|
+
const shift = headingShift(nodes, headingOffset, normalizeHeadings);
|
|
13152
|
+
return domToReact(nodes, buildOptions(shift, images));
|
|
13136
13153
|
}
|
|
13137
13154
|
function isAllowedImage(src, prefixes) {
|
|
13138
13155
|
if (!src) return false;
|
|
@@ -13249,7 +13266,7 @@ function buildOptions(headingOffset, images) {
|
|
|
13249
13266
|
const author = authorAttributes(node);
|
|
13250
13267
|
const headingMatch = /^h([1-6])$/.exec(name);
|
|
13251
13268
|
if (headingMatch) {
|
|
13252
|
-
const rendered = Math.min(6, Number(headingMatch[1]) + headingOffset);
|
|
13269
|
+
const rendered = Math.max(1, Math.min(6, Number(headingMatch[1]) + headingOffset));
|
|
13253
13270
|
const Tag = `h${rendered}`;
|
|
13254
13271
|
return /* @__PURE__ */ jsx(Tag, { ...author, className: HEADING_CLASSES[rendered], children: children2() });
|
|
13255
13272
|
}
|
|
@@ -13380,15 +13397,21 @@ function MarkdownRenderer({
|
|
|
13380
13397
|
content,
|
|
13381
13398
|
className,
|
|
13382
13399
|
headingOffset = 0,
|
|
13400
|
+
normalizeHeadings = false,
|
|
13383
13401
|
images
|
|
13384
13402
|
}) {
|
|
13385
13403
|
const html5 = markdownToSafeHtml(content);
|
|
13386
13404
|
if (!html5) return null;
|
|
13387
|
-
return /* @__PURE__ */ jsx("div", { className: slotClassName("max-w-none", "", className), "data-slot": "markdown", children: parse3(html5,
|
|
13405
|
+
return /* @__PURE__ */ jsx("div", { className: slotClassName("max-w-none", "", className), "data-slot": "markdown", children: parse3(html5, headingOffset, normalizeHeadings, images) });
|
|
13388
13406
|
}
|
|
13389
|
-
function SafeHtml({
|
|
13407
|
+
function SafeHtml({
|
|
13408
|
+
html: html5,
|
|
13409
|
+
className,
|
|
13410
|
+
headingOffset = 0,
|
|
13411
|
+
normalizeHeadings = false
|
|
13412
|
+
}) {
|
|
13390
13413
|
if (!html5) return null;
|
|
13391
|
-
return /* @__PURE__ */ jsx("div", { className: slotClassName("max-w-none", "", className), "data-slot": "safe-html", children: parse3(html5,
|
|
13414
|
+
return /* @__PURE__ */ jsx("div", { className: slotClassName("max-w-none", "", className), "data-slot": "safe-html", children: parse3(html5, headingOffset, normalizeHeadings) });
|
|
13392
13415
|
}
|
|
13393
13416
|
|
|
13394
13417
|
// src/components/course-description.tsx
|