Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 15x 8x 10x 10x 10x 10x 1x 74x 10x 10x 4x 3x 4x 4x 4x 1x 4x 1x | /**
* Content formats carried over from the Zeroheight / CMS export that aren't
* remark directives, so they're handled as a string pass after the unified
* pipeline:
*
* <div data-directive-type="hero-banner|video-embed" expanded into the
* data-directive-attrs="{json}" ...></div> class-based markup the CSS expects
*/
function escapeHtml(s: string): string {
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}
const DATA_DIRECTIVE_RE =
/<div\s+data-directive-type="([^"]+)"\s+data-directive-attrs="([^"]*)"\s+data-directive-children="([^"]*)"[^>]*>\s*<\/div>/g;
function parseJsonAttr(type: string, encoded: string): Record<string, string> {
Iif (!encoded) return {};
const decoded = encoded
.replace(/"/g, '"')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/'/g, "'")
.replace(/'/g, "'");
try {
return JSON.parse(decoded);
} catch (error) {
// Fail the build: an empty fallback would drop the embed or blank the banner.
throw new Error(`Invalid data-directive-attrs on a "${type}" directive: ${decoded}`, { cause: error });
}
}
/** Expand `data-directive-type` divs in rendered HTML. Unknown types pass through. */
export function renderDataDirectives(html: string): string {
return html.replace(DATA_DIRECTIVE_RE, (match, type: string, attrsEncoded: string) => {
const attrs = parseJsonAttr(type, attrsEncoded);
switch (type) {
case 'video-embed': {
if (!attrs.src) return '';
return `<div class="video-embed"><div class="video-embed__wrapper"><video controls preload="metadata"><source src="${escapeHtml(attrs.src)}" type="video/mp4"></video></div></div>`;
}
case 'hero-banner': {
// Children are only <h1> / <p> (no nested <div>): `extractLeadingHero` relies on it.
const { title, image, gradient, version, updated, tagline } = attrs;
let style = '';
if (image) style = ` style="background-image:url(${escapeHtml(image)})"`;
else Eif (gradient) style = ` style="background-image:${escapeHtml(gradient)}"`;
return (
`<div class="hero-banner"${style}><h1>${escapeHtml(title || '')}</h1>` +
(version ? `<p class="hero-banner__version">${escapeHtml(version)}</p>` : '') +
(updated ? `<p class="hero-banner__updated">${escapeHtml(updated)}</p>` : '') +
(tagline ? `<p class="hero-banner__tagline">${escapeHtml(tagline)}</p>` : '') +
'</div>'
);
}
default:
return match;
}
});
}
|