UNPKG

@maizzle/framework

Version:

Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.

80 lines (79 loc) 3.46 kB
//#region src/components/utils.ts function normalizeToPixels(value) { if (typeof value === "number" || Number.isFinite(Number(value))) return `${value}px`; return value; } const counters = {}; /** * Module-scoped sequential ID generator. Used by components to mint * unique marker ids (e.g. `c1`, `c2`) for the post-render transformer. * * Must live here (not inside `<script setup>`) because Vue compiles * `<script setup>` into the component's `setup()` function — any * `let counter = 0` there resets per instance, causing id collisions. */ function nextId(prefix) { counters[prefix] = (counters[prefix] ?? 0) + 1; return `${prefix}${counters[prefix]}`; } function hasWidthUtility(classStr) { return classStr.split(/\s+/).some((c) => { const clean = (c.split(":").pop() ?? "").replace(/^!/, ""); return /^(w-|max-w-|min-w-)/.test(clean); }); } function hasWidthInStyle(styleStr) { return /(?:^|;\s*)(?:max-width|width)\s*:/i.test(styleStr); } function hasHeightUtility(classStr) { return classStr.split(/\s+/).some((c) => { const clean = (c.split(":").pop() ?? "").replace(/^!/, ""); return /^(h-|max-h-|min-h-)/.test(clean); }); } function hasHeightInStyle(styleStr) { return /(?:^|;\s*)(?:max-height|height)\s*:/i.test(styleStr); } /** * Shared prop for components that emit MSO/VML fallback markup. The * `null` default acts as the "unset" sentinel — `useOutlookFallback` * treats `null` as inherit-from-ancestor (root default `true`), * letting users override per-component without losing inheritance. */ const outlookFallbackProp = { type: Boolean, default: null }; /** * Default utility classes for a code-block `<pre>`. `whitespace-pre!` is * forced important so Gmail's stylesheet can't reset it to `normal`, and * `m-0` strips the browser's default `<pre>` margins so it isn't spaced * away from its wrapper. */ function codeBlockPreClass(bg) { return `font-mono bg-[${bg}] p-4 m-0 overflow-auto whitespace-pre! [word-wrap:normal] [word-break:normal] [word-spacing:normal]`; } /** * Build the email-safe table wrapper around highlighted code. Shared by the * `<CodeBlock>` component and the Markdown fenced/indented code-block * rules so both render identical markup: a full-width table whose * cell carries the theme background, wrapping a `<pre>` styled * with utility classes (not Shiki's raw inline styles). */ function buildCodeBlock(codeContent, bg, options = {}) { const preClass = options.preClass ?? codeBlockPreClass(bg); return `<table class="w-full"><tr><td class="${options.tdClass ?? `bg-[${bg}] max-w-0 mso-padding-alt-4`}"><pre class="${preClass}"${options.styleAttr ?? ""} data-juice-important><code>${codeContent}</code></pre></td></tr></table>`; } /** * Re-wrap a Shiki (or plain markdown-it) `<pre><code>` block as a CodeBlock, * pulling the inner code and the theme background out of the highlighted * HTML. Falls back to a white background for unhighlighted blocks. */ function shikiToCodeBlock(highlighted) { const trimmed = highlighted.trim(); const bg = (trimmed.match(/^<pre[^>]*>/)?.[0] ?? "").match(/background-color:\s*(#[0-9a-fA-F]+)/)?.[1] ?? "#fff"; return buildCodeBlock(trimmed.replace(/^<pre[^>]*><code[^>]*>/, "").replace(/<\/code><\/pre>$/, ""), bg); } //#endregion export { buildCodeBlock, codeBlockPreClass, hasHeightInStyle, hasHeightUtility, hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels, outlookFallbackProp, shikiToCodeBlock }; //# sourceMappingURL=utils.js.map