@lacspace/og 1.0.0 → 1.0.1
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/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -187,7 +187,7 @@ function ogCard(options) {
|
|
|
187
187
|
);
|
|
188
188
|
}
|
|
189
189
|
function esc(s) {
|
|
190
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
190
|
+
return s.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
191
191
|
}
|
|
192
192
|
function wrap(text, fontSize, maxWidth, maxLines) {
|
|
193
193
|
const charW = fontSize * 0.56;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @lacspace/og\n * Beautiful, dynamic Open Graph images — a design system you configure once and\n * call per page. Produces a `next/og` element tree *and* a zero-dependency SVG\n * from the same options, with auto-fitting titles, presets and palettes.\n *\n * ```tsx\n * // app/og/route.tsx\n * import { ImageResponse } from \"next/og\";\n * import { ogCard } from \"@lacspace/og\";\n *\n * export const runtime = \"edge\";\n * export function GET(req: Request) {\n * const title = new URL(req.url).searchParams.get(\"title\") ?? \"My site\";\n * return new ImageResponse(\n * ogCard({ title, subtitle: \"my-site.com\", from: \"#22d3ee\", to: \"#6366f1\" }) as any,\n * { width: 1200, height: 630 },\n * );\n * }\n * ```\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\n/* ------------------------------------------------------------------ *\n * Options\n * ------------------------------------------------------------------ */\n\nexport type OgPreset = \"gradient\" | \"split\" | \"minimal\" | \"terminal\";\nexport type OgTheme = \"dark\" | \"light\";\n\nexport interface OgOptions {\n /** The headline. Font size auto-fits to length. */\n title: string;\n /** Secondary line under the title (often your domain). */\n subtitle?: string;\n /** Small uppercase label above the title (a section or category). */\n eyebrow?: string;\n /** A pill badge (e.g. \"NEW\", \"Guide\"). */\n badge?: string;\n /** Text/initial/emoji for the corner logo mark. */\n logo?: string;\n /** Footer line, bottom-left (e.g. your URL). */\n footer?: string;\n /** Accent gradient start / end. */\n from?: string;\n to?: string;\n /** \"dark\" (default) or \"light\" ground. */\n theme?: OgTheme;\n /** Layout preset. */\n preset?: OgPreset;\n /** Canvas size. Defaults to the OG standard 1200×630. */\n width?: number;\n height?: number;\n}\n\ninterface Resolved extends Required<Omit<OgOptions, \"subtitle\" | \"eyebrow\" | \"badge\" | \"logo\" | \"footer\">> {\n subtitle?: string;\n eyebrow?: string;\n badge?: string;\n logo?: string;\n footer?: string;\n}\n\nconst DEFAULTS = {\n from: \"#22d3ee\",\n to: \"#6366f1\",\n theme: \"dark\" as OgTheme,\n preset: \"gradient\" as OgPreset,\n width: 1200,\n height: 630,\n};\n\nfunction resolve(o: OgOptions): Resolved {\n return {\n title: o.title,\n subtitle: o.subtitle,\n eyebrow: o.eyebrow,\n badge: o.badge,\n logo: o.logo,\n footer: o.footer,\n from: o.from ?? DEFAULTS.from,\n to: o.to ?? DEFAULTS.to,\n theme: o.theme ?? DEFAULTS.theme,\n preset: o.preset ?? DEFAULTS.preset,\n width: o.width ?? DEFAULTS.width,\n height: o.height ?? DEFAULTS.height,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Shared design math\n * ------------------------------------------------------------------ */\n\n/** Pick a title font size that keeps long headlines readable and short ones bold. */\nexport function fitFontSize(\n title: string,\n opts: { max?: number; min?: number } = {},\n): number {\n const max = opts.max ?? 78;\n const min = opts.min ?? 42;\n const len = title.length;\n if (len <= 20) return max;\n if (len >= 90) return min;\n // Linear falloff between the two anchors.\n const t = (len - 20) / (90 - 20);\n return Math.round(max - t * (max - min));\n}\n\ninterface Palette {\n bg: string;\n fg: string;\n muted: string;\n border: string;\n from: string;\n to: string;\n}\n\nfunction palette(r: Resolved): Palette {\n const dark = r.theme === \"dark\";\n return {\n bg: dark ? \"#0a0a0f\" : \"#ffffff\",\n fg: dark ? \"#ffffff\" : \"#0a0a0f\",\n muted: dark ? \"rgba(255,255,255,0.68)\" : \"rgba(10,10,15,0.62)\",\n border: dark ? \"rgba(255,255,255,0.14)\" : \"rgba(10,10,15,0.10)\",\n from: r.from,\n to: r.to,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * next/og element tree\n * ------------------------------------------------------------------ */\n\nexport type OgStyle = Record<string, string | number>;\nexport interface OgNode {\n type: string;\n props: { style?: OgStyle; children?: (OgNode | string)[] | OgNode | string; [k: string]: unknown };\n key?: null;\n}\n\nfunction el(type: string, style: OgStyle, children?: (OgNode | string)[] | OgNode | string): OgNode {\n return { type, key: null, props: { style, ...(children === undefined ? {} : { children }) } };\n}\n\n/**\n * Build a `next/og`-compatible element tree for a share card. Pass it straight\n * to `new ImageResponse(ogCard(opts) as any, { width, height })`.\n *\n * (The `as any` sidesteps a React type mismatch — the object is a valid Satori\n * node, which is what `next/og` renders under the hood.)\n */\nexport function ogCard(options: OgOptions): OgNode {\n const r = resolve(options);\n const p = palette(r);\n const pad = Math.round(r.width * 0.075);\n const titleSize = fitFontSize(r.title);\n\n const accentBar = el(\"div\", {\n position: \"absolute\",\n top: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${Math.round(r.height * 0.02)}px`,\n background: `linear-gradient(90deg, ${p.from}, ${p.to})`,\n });\n\n const glow = el(\"div\", {\n position: \"absolute\",\n top: `-${Math.round(r.height * 0.35)}px`,\n right: `-${Math.round(r.width * 0.18)}px`,\n width: `${Math.round(r.width * 0.55)}px`,\n height: `${Math.round(r.width * 0.55)}px`,\n borderRadius: \"9999px\",\n background: `linear-gradient(135deg, ${p.from}, ${p.to})`,\n opacity: r.theme === \"dark\" ? \"0.22\" : \"0.16\",\n filter: \"blur(20px)\",\n });\n\n const topRow: (OgNode | string)[] = [];\n if (r.eyebrow) {\n topRow.push(\n el(\n \"div\",\n {\n display: \"flex\",\n fontSize: \"26px\",\n fontWeight: 600,\n letterSpacing: \"0.12em\",\n textTransform: \"uppercase\",\n color: p.from,\n },\n r.eyebrow.toUpperCase(),\n ),\n );\n }\n if (r.badge) {\n topRow.push(\n el(\n \"div\",\n {\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px 20px\",\n borderRadius: \"9999px\",\n fontSize: \"24px\",\n fontWeight: 700,\n color: p.fg,\n background: `linear-gradient(90deg, ${p.from}33, ${p.to}33)`,\n border: `1px solid ${p.border}`,\n },\n r.badge,\n ),\n );\n }\n\n const header = el(\n \"div\",\n { display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", width: \"100%\" },\n [\n topRow.length\n ? el(\"div\", { display: \"flex\", gap: \"20px\", alignItems: \"center\" }, topRow)\n : el(\"div\", { display: \"flex\" }, \"\"),\n r.logo\n ? el(\n \"div\",\n {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"76px\",\n height: \"76px\",\n borderRadius: \"20px\",\n fontSize: \"40px\",\n fontWeight: 800,\n color: \"#0a0a0f\",\n background: `linear-gradient(135deg, ${p.from}, ${p.to})`,\n },\n r.logo,\n )\n : el(\"div\", { display: \"flex\" }, \"\"),\n ],\n );\n\n const body: (OgNode | string)[] = [\n el(\n \"div\",\n {\n display: \"flex\",\n fontSize: `${titleSize}px`,\n fontWeight: 800,\n lineHeight: 1.05,\n letterSpacing: \"-0.02em\",\n color: p.fg,\n },\n r.title,\n ),\n ];\n if (r.subtitle) {\n body.push(\n el(\n \"div\",\n { display: \"flex\", marginTop: \"28px\", fontSize: \"34px\", fontWeight: 500, color: p.muted },\n r.subtitle,\n ),\n );\n }\n\n const children: OgNode[] = [\n accentBar,\n glow,\n header,\n el(\"div\", { display: \"flex\", flexDirection: \"column\" }, body),\n ];\n\n if (r.footer) {\n children.push(\n el(\n \"div\",\n { display: \"flex\", fontSize: \"26px\", fontWeight: 500, color: p.muted },\n r.footer,\n ),\n );\n }\n\n return el(\n \"div\",\n {\n position: \"relative\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n padding: `${pad}px`,\n background: r.preset === \"split\" ? `linear-gradient(135deg, ${p.from}, ${p.to})` : p.bg,\n color: p.fg,\n fontFamily: \"sans-serif\",\n },\n children,\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Zero-dependency SVG (previews, emails, icons, guaranteed fallback)\n * ------------------------------------------------------------------ */\n\nfunction esc(s: string): string {\n return s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\").replace(/\"/g, \""\");\n}\n\n/** Greedy word-wrap by estimated glyph width. */\nfunction wrap(text: string, fontSize: number, maxWidth: number, maxLines: number): string[] {\n const charW = fontSize * 0.56;\n const perLine = Math.max(1, Math.floor(maxWidth / charW));\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let cur = \"\";\n for (const w of words) {\n const next = cur ? `${cur} ${w}` : w;\n if (next.length > perLine && cur) {\n lines.push(cur);\n cur = w;\n if (lines.length === maxLines - 1) break;\n } else {\n cur = next;\n }\n }\n if (cur && lines.length < maxLines) lines.push(cur);\n const used = lines.join(\" \").length;\n if (used < text.length && lines.length) {\n lines[lines.length - 1] = `${lines[lines.length - 1]!.replace(/\\.*$/, \"\")}…`;\n }\n return lines;\n}\n\n/**\n * Render a share card as a standalone SVG string — no browser, no runtime deps.\n * Perfect for previews, email headers, README banners and icons.\n */\nexport function ogSvg(options: OgOptions): string {\n const r = resolve(options);\n const p = palette(r);\n const W = r.width;\n const H = r.height;\n const pad = Math.round(W * 0.075);\n const titleSize = fitFontSize(r.title);\n const contentW = W - pad * 2;\n const split = r.preset === \"split\";\n\n const titleLines = wrap(r.title, titleSize, contentW, 3);\n const titleBlockH = titleLines.length * titleSize * 1.08;\n const titleTop = H / 2 - titleBlockH / 2 + titleSize * 0.8;\n\n const parts: string[] = [];\n parts.push(\n `<svg width=\"${W}\" height=\"${H}\" viewBox=\"0 0 ${W} ${H}\" xmlns=\"http://www.w3.org/2000/svg\" font-family=\"Inter, ui-sans-serif, system-ui, sans-serif\">`,\n );\n parts.push(`<defs>\n <linearGradient id=\"accent\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0\" stop-color=\"${esc(p.from)}\"/><stop offset=\"1\" stop-color=\"${esc(p.to)}\"/>\n </linearGradient>\n <radialGradient id=\"glow\" cx=\"0.85\" cy=\"0.1\" r=\"0.7\">\n <stop offset=\"0\" stop-color=\"${esc(p.from)}\" stop-opacity=\"${r.theme === \"dark\" ? 0.28 : 0.2}\"/>\n <stop offset=\"1\" stop-color=\"${esc(p.to)}\" stop-opacity=\"0\"/>\n </radialGradient>\n </defs>`);\n\n // background\n parts.push(`<rect width=\"${W}\" height=\"${H}\" fill=\"${split ? \"url(#accent)\" : esc(p.bg)}\"/>`);\n if (!split) parts.push(`<rect width=\"${W}\" height=\"${H}\" fill=\"url(#glow)\"/>`);\n // accent bar\n parts.push(`<rect width=\"${W}\" height=\"${Math.round(H * 0.02)}\" fill=\"url(#accent)\"/>`);\n\n // eyebrow\n let topY = pad + 34;\n if (r.eyebrow) {\n parts.push(\n `<text x=\"${pad}\" y=\"${topY}\" font-size=\"26\" font-weight=\"600\" letter-spacing=\"3\" fill=\"${esc(p.from)}\">${esc(\n r.eyebrow.toUpperCase(),\n )}</text>`,\n );\n }\n // logo mark (top-right)\n if (r.logo) {\n const s = 76;\n const lx = W - pad - s;\n const ly = pad;\n parts.push(`<rect x=\"${lx}\" y=\"${ly}\" width=\"${s}\" height=\"${s}\" rx=\"20\" fill=\"url(#accent)\"/>`);\n parts.push(\n `<text x=\"${lx + s / 2}\" y=\"${ly + s / 2 + 14}\" font-size=\"40\" font-weight=\"800\" text-anchor=\"middle\" fill=\"#0a0a0f\">${esc(\n r.logo,\n )}</text>`,\n );\n }\n // badge\n if (r.badge) {\n const bx = pad + (r.eyebrow ? 0 : 0);\n parts.push(\n `<rect x=\"${bx}\" y=\"${topY + 14}\" width=\"${r.badge.length * 16 + 40}\" height=\"44\" rx=\"22\" fill=\"${esc(\n p.from,\n )}\" opacity=\"0.18\"/>`,\n );\n parts.push(\n `<text x=\"${bx + 20}\" y=\"${topY + 43}\" font-size=\"24\" font-weight=\"700\" fill=\"${esc(p.fg)}\">${esc(\n r.badge,\n )}</text>`,\n );\n topY += 60;\n }\n\n // title (wrapped)\n titleLines.forEach((line, i) => {\n parts.push(\n `<text x=\"${pad}\" y=\"${titleTop + i * titleSize * 1.08}\" font-size=\"${titleSize}\" font-weight=\"800\" letter-spacing=\"-1\" fill=\"${esc(\n p.fg,\n )}\">${esc(line)}</text>`,\n );\n });\n // subtitle\n if (r.subtitle) {\n parts.push(\n `<text x=\"${pad}\" y=\"${titleTop + titleLines.length * titleSize * 1.08 + 46}\" font-size=\"34\" font-weight=\"500\" fill=\"${esc(\n p.muted,\n )}\">${esc(r.subtitle)}</text>`,\n );\n }\n // footer\n if (r.footer) {\n parts.push(\n `<text x=\"${pad}\" y=\"${H - pad}\" font-size=\"26\" font-weight=\"500\" fill=\"${esc(p.muted)}\">${esc(\n r.footer,\n )}</text>`,\n );\n }\n\n parts.push(`</svg>`);\n return parts.join(\"\");\n}\n\n/** SVG as a `data:` URI — drop straight into `src` / `background-image`. */\nexport function ogSvgDataUri(options: OgOptions): string {\n return `data:image/svg+xml;utf8,${encodeURIComponent(ogSvg(options))}`;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @lacspace/og\n * Beautiful, dynamic Open Graph images — a design system you configure once and\n * call per page. Produces a `next/og` element tree *and* a zero-dependency SVG\n * from the same options, with auto-fitting titles, presets and palettes.\n *\n * ```tsx\n * // app/og/route.tsx\n * import { ImageResponse } from \"next/og\";\n * import { ogCard } from \"@lacspace/og\";\n *\n * export const runtime = \"edge\";\n * export function GET(req: Request) {\n * const title = new URL(req.url).searchParams.get(\"title\") ?? \"My site\";\n * return new ImageResponse(\n * ogCard({ title, subtitle: \"my-site.com\", from: \"#22d3ee\", to: \"#6366f1\" }) as any,\n * { width: 1200, height: 630 },\n * );\n * }\n * ```\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\n/* ------------------------------------------------------------------ *\n * Options\n * ------------------------------------------------------------------ */\n\nexport type OgPreset = \"gradient\" | \"split\" | \"minimal\" | \"terminal\";\nexport type OgTheme = \"dark\" | \"light\";\n\nexport interface OgOptions {\n /** The headline. Font size auto-fits to length. */\n title: string;\n /** Secondary line under the title (often your domain). */\n subtitle?: string;\n /** Small uppercase label above the title (a section or category). */\n eyebrow?: string;\n /** A pill badge (e.g. \"NEW\", \"Guide\"). */\n badge?: string;\n /** Text/initial/emoji for the corner logo mark. */\n logo?: string;\n /** Footer line, bottom-left (e.g. your URL). */\n footer?: string;\n /** Accent gradient start / end. */\n from?: string;\n to?: string;\n /** \"dark\" (default) or \"light\" ground. */\n theme?: OgTheme;\n /** Layout preset. */\n preset?: OgPreset;\n /** Canvas size. Defaults to the OG standard 1200×630. */\n width?: number;\n height?: number;\n}\n\ninterface Resolved extends Required<Omit<OgOptions, \"subtitle\" | \"eyebrow\" | \"badge\" | \"logo\" | \"footer\">> {\n subtitle?: string;\n eyebrow?: string;\n badge?: string;\n logo?: string;\n footer?: string;\n}\n\nconst DEFAULTS = {\n from: \"#22d3ee\",\n to: \"#6366f1\",\n theme: \"dark\" as OgTheme,\n preset: \"gradient\" as OgPreset,\n width: 1200,\n height: 630,\n};\n\nfunction resolve(o: OgOptions): Resolved {\n return {\n title: o.title,\n subtitle: o.subtitle,\n eyebrow: o.eyebrow,\n badge: o.badge,\n logo: o.logo,\n footer: o.footer,\n from: o.from ?? DEFAULTS.from,\n to: o.to ?? DEFAULTS.to,\n theme: o.theme ?? DEFAULTS.theme,\n preset: o.preset ?? DEFAULTS.preset,\n width: o.width ?? DEFAULTS.width,\n height: o.height ?? DEFAULTS.height,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Shared design math\n * ------------------------------------------------------------------ */\n\n/** Pick a title font size that keeps long headlines readable and short ones bold. */\nexport function fitFontSize(\n title: string,\n opts: { max?: number; min?: number } = {},\n): number {\n const max = opts.max ?? 78;\n const min = opts.min ?? 42;\n const len = title.length;\n if (len <= 20) return max;\n if (len >= 90) return min;\n // Linear falloff between the two anchors.\n const t = (len - 20) / (90 - 20);\n return Math.round(max - t * (max - min));\n}\n\ninterface Palette {\n bg: string;\n fg: string;\n muted: string;\n border: string;\n from: string;\n to: string;\n}\n\nfunction palette(r: Resolved): Palette {\n const dark = r.theme === \"dark\";\n return {\n bg: dark ? \"#0a0a0f\" : \"#ffffff\",\n fg: dark ? \"#ffffff\" : \"#0a0a0f\",\n muted: dark ? \"rgba(255,255,255,0.68)\" : \"rgba(10,10,15,0.62)\",\n border: dark ? \"rgba(255,255,255,0.14)\" : \"rgba(10,10,15,0.10)\",\n from: r.from,\n to: r.to,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * next/og element tree\n * ------------------------------------------------------------------ */\n\nexport type OgStyle = Record<string, string | number>;\nexport interface OgNode {\n type: string;\n props: { style?: OgStyle; children?: (OgNode | string)[] | OgNode | string; [k: string]: unknown };\n key?: null;\n}\n\nfunction el(type: string, style: OgStyle, children?: (OgNode | string)[] | OgNode | string): OgNode {\n return { type, key: null, props: { style, ...(children === undefined ? {} : { children }) } };\n}\n\n/**\n * Build a `next/og`-compatible element tree for a share card. Pass it straight\n * to `new ImageResponse(ogCard(opts) as any, { width, height })`.\n *\n * (The `as any` sidesteps a React type mismatch — the object is a valid Satori\n * node, which is what `next/og` renders under the hood.)\n */\nexport function ogCard(options: OgOptions): OgNode {\n const r = resolve(options);\n const p = palette(r);\n const pad = Math.round(r.width * 0.075);\n const titleSize = fitFontSize(r.title);\n\n const accentBar = el(\"div\", {\n position: \"absolute\",\n top: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${Math.round(r.height * 0.02)}px`,\n background: `linear-gradient(90deg, ${p.from}, ${p.to})`,\n });\n\n const glow = el(\"div\", {\n position: \"absolute\",\n top: `-${Math.round(r.height * 0.35)}px`,\n right: `-${Math.round(r.width * 0.18)}px`,\n width: `${Math.round(r.width * 0.55)}px`,\n height: `${Math.round(r.width * 0.55)}px`,\n borderRadius: \"9999px\",\n background: `linear-gradient(135deg, ${p.from}, ${p.to})`,\n opacity: r.theme === \"dark\" ? \"0.22\" : \"0.16\",\n filter: \"blur(20px)\",\n });\n\n const topRow: (OgNode | string)[] = [];\n if (r.eyebrow) {\n topRow.push(\n el(\n \"div\",\n {\n display: \"flex\",\n fontSize: \"26px\",\n fontWeight: 600,\n letterSpacing: \"0.12em\",\n textTransform: \"uppercase\",\n color: p.from,\n },\n r.eyebrow.toUpperCase(),\n ),\n );\n }\n if (r.badge) {\n topRow.push(\n el(\n \"div\",\n {\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px 20px\",\n borderRadius: \"9999px\",\n fontSize: \"24px\",\n fontWeight: 700,\n color: p.fg,\n background: `linear-gradient(90deg, ${p.from}33, ${p.to}33)`,\n border: `1px solid ${p.border}`,\n },\n r.badge,\n ),\n );\n }\n\n const header = el(\n \"div\",\n { display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", width: \"100%\" },\n [\n topRow.length\n ? el(\"div\", { display: \"flex\", gap: \"20px\", alignItems: \"center\" }, topRow)\n : el(\"div\", { display: \"flex\" }, \"\"),\n r.logo\n ? el(\n \"div\",\n {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"76px\",\n height: \"76px\",\n borderRadius: \"20px\",\n fontSize: \"40px\",\n fontWeight: 800,\n color: \"#0a0a0f\",\n background: `linear-gradient(135deg, ${p.from}, ${p.to})`,\n },\n r.logo,\n )\n : el(\"div\", { display: \"flex\" }, \"\"),\n ],\n );\n\n const body: (OgNode | string)[] = [\n el(\n \"div\",\n {\n display: \"flex\",\n fontSize: `${titleSize}px`,\n fontWeight: 800,\n lineHeight: 1.05,\n letterSpacing: \"-0.02em\",\n color: p.fg,\n },\n r.title,\n ),\n ];\n if (r.subtitle) {\n body.push(\n el(\n \"div\",\n { display: \"flex\", marginTop: \"28px\", fontSize: \"34px\", fontWeight: 500, color: p.muted },\n r.subtitle,\n ),\n );\n }\n\n const children: OgNode[] = [\n accentBar,\n glow,\n header,\n el(\"div\", { display: \"flex\", flexDirection: \"column\" }, body),\n ];\n\n if (r.footer) {\n children.push(\n el(\n \"div\",\n { display: \"flex\", fontSize: \"26px\", fontWeight: 500, color: p.muted },\n r.footer,\n ),\n );\n }\n\n return el(\n \"div\",\n {\n position: \"relative\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n padding: `${pad}px`,\n background: r.preset === \"split\" ? `linear-gradient(135deg, ${p.from}, ${p.to})` : p.bg,\n color: p.fg,\n fontFamily: \"sans-serif\",\n },\n children,\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Zero-dependency SVG (previews, emails, icons, guaranteed fallback)\n * ------------------------------------------------------------------ */\n\nfunction esc(s: string): string {\n return s\n .replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n}\n\n/** Greedy word-wrap by estimated glyph width. */\nfunction wrap(text: string, fontSize: number, maxWidth: number, maxLines: number): string[] {\n const charW = fontSize * 0.56;\n const perLine = Math.max(1, Math.floor(maxWidth / charW));\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let cur = \"\";\n for (const w of words) {\n const next = cur ? `${cur} ${w}` : w;\n if (next.length > perLine && cur) {\n lines.push(cur);\n cur = w;\n if (lines.length === maxLines - 1) break;\n } else {\n cur = next;\n }\n }\n if (cur && lines.length < maxLines) lines.push(cur);\n const used = lines.join(\" \").length;\n if (used < text.length && lines.length) {\n lines[lines.length - 1] = `${lines[lines.length - 1]!.replace(/\\.*$/, \"\")}…`;\n }\n return lines;\n}\n\n/**\n * Render a share card as a standalone SVG string — no browser, no runtime deps.\n * Perfect for previews, email headers, README banners and icons.\n */\nexport function ogSvg(options: OgOptions): string {\n const r = resolve(options);\n const p = palette(r);\n const W = r.width;\n const H = r.height;\n const pad = Math.round(W * 0.075);\n const titleSize = fitFontSize(r.title);\n const contentW = W - pad * 2;\n const split = r.preset === \"split\";\n\n const titleLines = wrap(r.title, titleSize, contentW, 3);\n const titleBlockH = titleLines.length * titleSize * 1.08;\n const titleTop = H / 2 - titleBlockH / 2 + titleSize * 0.8;\n\n const parts: string[] = [];\n parts.push(\n `<svg width=\"${W}\" height=\"${H}\" viewBox=\"0 0 ${W} ${H}\" xmlns=\"http://www.w3.org/2000/svg\" font-family=\"Inter, ui-sans-serif, system-ui, sans-serif\">`,\n );\n parts.push(`<defs>\n <linearGradient id=\"accent\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0\" stop-color=\"${esc(p.from)}\"/><stop offset=\"1\" stop-color=\"${esc(p.to)}\"/>\n </linearGradient>\n <radialGradient id=\"glow\" cx=\"0.85\" cy=\"0.1\" r=\"0.7\">\n <stop offset=\"0\" stop-color=\"${esc(p.from)}\" stop-opacity=\"${r.theme === \"dark\" ? 0.28 : 0.2}\"/>\n <stop offset=\"1\" stop-color=\"${esc(p.to)}\" stop-opacity=\"0\"/>\n </radialGradient>\n </defs>`);\n\n // background\n parts.push(`<rect width=\"${W}\" height=\"${H}\" fill=\"${split ? \"url(#accent)\" : esc(p.bg)}\"/>`);\n if (!split) parts.push(`<rect width=\"${W}\" height=\"${H}\" fill=\"url(#glow)\"/>`);\n // accent bar\n parts.push(`<rect width=\"${W}\" height=\"${Math.round(H * 0.02)}\" fill=\"url(#accent)\"/>`);\n\n // eyebrow\n let topY = pad + 34;\n if (r.eyebrow) {\n parts.push(\n `<text x=\"${pad}\" y=\"${topY}\" font-size=\"26\" font-weight=\"600\" letter-spacing=\"3\" fill=\"${esc(p.from)}\">${esc(\n r.eyebrow.toUpperCase(),\n )}</text>`,\n );\n }\n // logo mark (top-right)\n if (r.logo) {\n const s = 76;\n const lx = W - pad - s;\n const ly = pad;\n parts.push(`<rect x=\"${lx}\" y=\"${ly}\" width=\"${s}\" height=\"${s}\" rx=\"20\" fill=\"url(#accent)\"/>`);\n parts.push(\n `<text x=\"${lx + s / 2}\" y=\"${ly + s / 2 + 14}\" font-size=\"40\" font-weight=\"800\" text-anchor=\"middle\" fill=\"#0a0a0f\">${esc(\n r.logo,\n )}</text>`,\n );\n }\n // badge\n if (r.badge) {\n const bx = pad + (r.eyebrow ? 0 : 0);\n parts.push(\n `<rect x=\"${bx}\" y=\"${topY + 14}\" width=\"${r.badge.length * 16 + 40}\" height=\"44\" rx=\"22\" fill=\"${esc(\n p.from,\n )}\" opacity=\"0.18\"/>`,\n );\n parts.push(\n `<text x=\"${bx + 20}\" y=\"${topY + 43}\" font-size=\"24\" font-weight=\"700\" fill=\"${esc(p.fg)}\">${esc(\n r.badge,\n )}</text>`,\n );\n topY += 60;\n }\n\n // title (wrapped)\n titleLines.forEach((line, i) => {\n parts.push(\n `<text x=\"${pad}\" y=\"${titleTop + i * titleSize * 1.08}\" font-size=\"${titleSize}\" font-weight=\"800\" letter-spacing=\"-1\" fill=\"${esc(\n p.fg,\n )}\">${esc(line)}</text>`,\n );\n });\n // subtitle\n if (r.subtitle) {\n parts.push(\n `<text x=\"${pad}\" y=\"${titleTop + titleLines.length * titleSize * 1.08 + 46}\" font-size=\"34\" font-weight=\"500\" fill=\"${esc(\n p.muted,\n )}\">${esc(r.subtitle)}</text>`,\n );\n }\n // footer\n if (r.footer) {\n parts.push(\n `<text x=\"${pad}\" y=\"${H - pad}\" font-size=\"26\" font-weight=\"500\" fill=\"${esc(p.muted)}\">${esc(\n r.footer,\n )}</text>`,\n );\n }\n\n parts.push(`</svg>`);\n return parts.join(\"\");\n}\n\n/** SVG as a `data:` URI — drop straight into `src` / `background-image`. */\nexport function ogSvgDataUri(options: OgOptions): string {\n return `data:image/svg+xml;utf8,${encodeURIComponent(ogSvg(options))}`;\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -185,7 +185,7 @@ function ogCard(options) {
|
|
|
185
185
|
);
|
|
186
186
|
}
|
|
187
187
|
function esc(s) {
|
|
188
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
188
|
+
return s.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
189
189
|
}
|
|
190
190
|
function wrap(text, fontSize, maxWidth, maxLines) {
|
|
191
191
|
const charW = fontSize * 0.56;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @lacspace/og\n * Beautiful, dynamic Open Graph images — a design system you configure once and\n * call per page. Produces a `next/og` element tree *and* a zero-dependency SVG\n * from the same options, with auto-fitting titles, presets and palettes.\n *\n * ```tsx\n * // app/og/route.tsx\n * import { ImageResponse } from \"next/og\";\n * import { ogCard } from \"@lacspace/og\";\n *\n * export const runtime = \"edge\";\n * export function GET(req: Request) {\n * const title = new URL(req.url).searchParams.get(\"title\") ?? \"My site\";\n * return new ImageResponse(\n * ogCard({ title, subtitle: \"my-site.com\", from: \"#22d3ee\", to: \"#6366f1\" }) as any,\n * { width: 1200, height: 630 },\n * );\n * }\n * ```\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\n/* ------------------------------------------------------------------ *\n * Options\n * ------------------------------------------------------------------ */\n\nexport type OgPreset = \"gradient\" | \"split\" | \"minimal\" | \"terminal\";\nexport type OgTheme = \"dark\" | \"light\";\n\nexport interface OgOptions {\n /** The headline. Font size auto-fits to length. */\n title: string;\n /** Secondary line under the title (often your domain). */\n subtitle?: string;\n /** Small uppercase label above the title (a section or category). */\n eyebrow?: string;\n /** A pill badge (e.g. \"NEW\", \"Guide\"). */\n badge?: string;\n /** Text/initial/emoji for the corner logo mark. */\n logo?: string;\n /** Footer line, bottom-left (e.g. your URL). */\n footer?: string;\n /** Accent gradient start / end. */\n from?: string;\n to?: string;\n /** \"dark\" (default) or \"light\" ground. */\n theme?: OgTheme;\n /** Layout preset. */\n preset?: OgPreset;\n /** Canvas size. Defaults to the OG standard 1200×630. */\n width?: number;\n height?: number;\n}\n\ninterface Resolved extends Required<Omit<OgOptions, \"subtitle\" | \"eyebrow\" | \"badge\" | \"logo\" | \"footer\">> {\n subtitle?: string;\n eyebrow?: string;\n badge?: string;\n logo?: string;\n footer?: string;\n}\n\nconst DEFAULTS = {\n from: \"#22d3ee\",\n to: \"#6366f1\",\n theme: \"dark\" as OgTheme,\n preset: \"gradient\" as OgPreset,\n width: 1200,\n height: 630,\n};\n\nfunction resolve(o: OgOptions): Resolved {\n return {\n title: o.title,\n subtitle: o.subtitle,\n eyebrow: o.eyebrow,\n badge: o.badge,\n logo: o.logo,\n footer: o.footer,\n from: o.from ?? DEFAULTS.from,\n to: o.to ?? DEFAULTS.to,\n theme: o.theme ?? DEFAULTS.theme,\n preset: o.preset ?? DEFAULTS.preset,\n width: o.width ?? DEFAULTS.width,\n height: o.height ?? DEFAULTS.height,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Shared design math\n * ------------------------------------------------------------------ */\n\n/** Pick a title font size that keeps long headlines readable and short ones bold. */\nexport function fitFontSize(\n title: string,\n opts: { max?: number; min?: number } = {},\n): number {\n const max = opts.max ?? 78;\n const min = opts.min ?? 42;\n const len = title.length;\n if (len <= 20) return max;\n if (len >= 90) return min;\n // Linear falloff between the two anchors.\n const t = (len - 20) / (90 - 20);\n return Math.round(max - t * (max - min));\n}\n\ninterface Palette {\n bg: string;\n fg: string;\n muted: string;\n border: string;\n from: string;\n to: string;\n}\n\nfunction palette(r: Resolved): Palette {\n const dark = r.theme === \"dark\";\n return {\n bg: dark ? \"#0a0a0f\" : \"#ffffff\",\n fg: dark ? \"#ffffff\" : \"#0a0a0f\",\n muted: dark ? \"rgba(255,255,255,0.68)\" : \"rgba(10,10,15,0.62)\",\n border: dark ? \"rgba(255,255,255,0.14)\" : \"rgba(10,10,15,0.10)\",\n from: r.from,\n to: r.to,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * next/og element tree\n * ------------------------------------------------------------------ */\n\nexport type OgStyle = Record<string, string | number>;\nexport interface OgNode {\n type: string;\n props: { style?: OgStyle; children?: (OgNode | string)[] | OgNode | string; [k: string]: unknown };\n key?: null;\n}\n\nfunction el(type: string, style: OgStyle, children?: (OgNode | string)[] | OgNode | string): OgNode {\n return { type, key: null, props: { style, ...(children === undefined ? {} : { children }) } };\n}\n\n/**\n * Build a `next/og`-compatible element tree for a share card. Pass it straight\n * to `new ImageResponse(ogCard(opts) as any, { width, height })`.\n *\n * (The `as any` sidesteps a React type mismatch — the object is a valid Satori\n * node, which is what `next/og` renders under the hood.)\n */\nexport function ogCard(options: OgOptions): OgNode {\n const r = resolve(options);\n const p = palette(r);\n const pad = Math.round(r.width * 0.075);\n const titleSize = fitFontSize(r.title);\n\n const accentBar = el(\"div\", {\n position: \"absolute\",\n top: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${Math.round(r.height * 0.02)}px`,\n background: `linear-gradient(90deg, ${p.from}, ${p.to})`,\n });\n\n const glow = el(\"div\", {\n position: \"absolute\",\n top: `-${Math.round(r.height * 0.35)}px`,\n right: `-${Math.round(r.width * 0.18)}px`,\n width: `${Math.round(r.width * 0.55)}px`,\n height: `${Math.round(r.width * 0.55)}px`,\n borderRadius: \"9999px\",\n background: `linear-gradient(135deg, ${p.from}, ${p.to})`,\n opacity: r.theme === \"dark\" ? \"0.22\" : \"0.16\",\n filter: \"blur(20px)\",\n });\n\n const topRow: (OgNode | string)[] = [];\n if (r.eyebrow) {\n topRow.push(\n el(\n \"div\",\n {\n display: \"flex\",\n fontSize: \"26px\",\n fontWeight: 600,\n letterSpacing: \"0.12em\",\n textTransform: \"uppercase\",\n color: p.from,\n },\n r.eyebrow.toUpperCase(),\n ),\n );\n }\n if (r.badge) {\n topRow.push(\n el(\n \"div\",\n {\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px 20px\",\n borderRadius: \"9999px\",\n fontSize: \"24px\",\n fontWeight: 700,\n color: p.fg,\n background: `linear-gradient(90deg, ${p.from}33, ${p.to}33)`,\n border: `1px solid ${p.border}`,\n },\n r.badge,\n ),\n );\n }\n\n const header = el(\n \"div\",\n { display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", width: \"100%\" },\n [\n topRow.length\n ? el(\"div\", { display: \"flex\", gap: \"20px\", alignItems: \"center\" }, topRow)\n : el(\"div\", { display: \"flex\" }, \"\"),\n r.logo\n ? el(\n \"div\",\n {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"76px\",\n height: \"76px\",\n borderRadius: \"20px\",\n fontSize: \"40px\",\n fontWeight: 800,\n color: \"#0a0a0f\",\n background: `linear-gradient(135deg, ${p.from}, ${p.to})`,\n },\n r.logo,\n )\n : el(\"div\", { display: \"flex\" }, \"\"),\n ],\n );\n\n const body: (OgNode | string)[] = [\n el(\n \"div\",\n {\n display: \"flex\",\n fontSize: `${titleSize}px`,\n fontWeight: 800,\n lineHeight: 1.05,\n letterSpacing: \"-0.02em\",\n color: p.fg,\n },\n r.title,\n ),\n ];\n if (r.subtitle) {\n body.push(\n el(\n \"div\",\n { display: \"flex\", marginTop: \"28px\", fontSize: \"34px\", fontWeight: 500, color: p.muted },\n r.subtitle,\n ),\n );\n }\n\n const children: OgNode[] = [\n accentBar,\n glow,\n header,\n el(\"div\", { display: \"flex\", flexDirection: \"column\" }, body),\n ];\n\n if (r.footer) {\n children.push(\n el(\n \"div\",\n { display: \"flex\", fontSize: \"26px\", fontWeight: 500, color: p.muted },\n r.footer,\n ),\n );\n }\n\n return el(\n \"div\",\n {\n position: \"relative\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n padding: `${pad}px`,\n background: r.preset === \"split\" ? `linear-gradient(135deg, ${p.from}, ${p.to})` : p.bg,\n color: p.fg,\n fontFamily: \"sans-serif\",\n },\n children,\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Zero-dependency SVG (previews, emails, icons, guaranteed fallback)\n * ------------------------------------------------------------------ */\n\nfunction esc(s: string): string {\n return s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\").replace(/\"/g, \""\");\n}\n\n/** Greedy word-wrap by estimated glyph width. */\nfunction wrap(text: string, fontSize: number, maxWidth: number, maxLines: number): string[] {\n const charW = fontSize * 0.56;\n const perLine = Math.max(1, Math.floor(maxWidth / charW));\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let cur = \"\";\n for (const w of words) {\n const next = cur ? `${cur} ${w}` : w;\n if (next.length > perLine && cur) {\n lines.push(cur);\n cur = w;\n if (lines.length === maxLines - 1) break;\n } else {\n cur = next;\n }\n }\n if (cur && lines.length < maxLines) lines.push(cur);\n const used = lines.join(\" \").length;\n if (used < text.length && lines.length) {\n lines[lines.length - 1] = `${lines[lines.length - 1]!.replace(/\\.*$/, \"\")}…`;\n }\n return lines;\n}\n\n/**\n * Render a share card as a standalone SVG string — no browser, no runtime deps.\n * Perfect for previews, email headers, README banners and icons.\n */\nexport function ogSvg(options: OgOptions): string {\n const r = resolve(options);\n const p = palette(r);\n const W = r.width;\n const H = r.height;\n const pad = Math.round(W * 0.075);\n const titleSize = fitFontSize(r.title);\n const contentW = W - pad * 2;\n const split = r.preset === \"split\";\n\n const titleLines = wrap(r.title, titleSize, contentW, 3);\n const titleBlockH = titleLines.length * titleSize * 1.08;\n const titleTop = H / 2 - titleBlockH / 2 + titleSize * 0.8;\n\n const parts: string[] = [];\n parts.push(\n `<svg width=\"${W}\" height=\"${H}\" viewBox=\"0 0 ${W} ${H}\" xmlns=\"http://www.w3.org/2000/svg\" font-family=\"Inter, ui-sans-serif, system-ui, sans-serif\">`,\n );\n parts.push(`<defs>\n <linearGradient id=\"accent\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0\" stop-color=\"${esc(p.from)}\"/><stop offset=\"1\" stop-color=\"${esc(p.to)}\"/>\n </linearGradient>\n <radialGradient id=\"glow\" cx=\"0.85\" cy=\"0.1\" r=\"0.7\">\n <stop offset=\"0\" stop-color=\"${esc(p.from)}\" stop-opacity=\"${r.theme === \"dark\" ? 0.28 : 0.2}\"/>\n <stop offset=\"1\" stop-color=\"${esc(p.to)}\" stop-opacity=\"0\"/>\n </radialGradient>\n </defs>`);\n\n // background\n parts.push(`<rect width=\"${W}\" height=\"${H}\" fill=\"${split ? \"url(#accent)\" : esc(p.bg)}\"/>`);\n if (!split) parts.push(`<rect width=\"${W}\" height=\"${H}\" fill=\"url(#glow)\"/>`);\n // accent bar\n parts.push(`<rect width=\"${W}\" height=\"${Math.round(H * 0.02)}\" fill=\"url(#accent)\"/>`);\n\n // eyebrow\n let topY = pad + 34;\n if (r.eyebrow) {\n parts.push(\n `<text x=\"${pad}\" y=\"${topY}\" font-size=\"26\" font-weight=\"600\" letter-spacing=\"3\" fill=\"${esc(p.from)}\">${esc(\n r.eyebrow.toUpperCase(),\n )}</text>`,\n );\n }\n // logo mark (top-right)\n if (r.logo) {\n const s = 76;\n const lx = W - pad - s;\n const ly = pad;\n parts.push(`<rect x=\"${lx}\" y=\"${ly}\" width=\"${s}\" height=\"${s}\" rx=\"20\" fill=\"url(#accent)\"/>`);\n parts.push(\n `<text x=\"${lx + s / 2}\" y=\"${ly + s / 2 + 14}\" font-size=\"40\" font-weight=\"800\" text-anchor=\"middle\" fill=\"#0a0a0f\">${esc(\n r.logo,\n )}</text>`,\n );\n }\n // badge\n if (r.badge) {\n const bx = pad + (r.eyebrow ? 0 : 0);\n parts.push(\n `<rect x=\"${bx}\" y=\"${topY + 14}\" width=\"${r.badge.length * 16 + 40}\" height=\"44\" rx=\"22\" fill=\"${esc(\n p.from,\n )}\" opacity=\"0.18\"/>`,\n );\n parts.push(\n `<text x=\"${bx + 20}\" y=\"${topY + 43}\" font-size=\"24\" font-weight=\"700\" fill=\"${esc(p.fg)}\">${esc(\n r.badge,\n )}</text>`,\n );\n topY += 60;\n }\n\n // title (wrapped)\n titleLines.forEach((line, i) => {\n parts.push(\n `<text x=\"${pad}\" y=\"${titleTop + i * titleSize * 1.08}\" font-size=\"${titleSize}\" font-weight=\"800\" letter-spacing=\"-1\" fill=\"${esc(\n p.fg,\n )}\">${esc(line)}</text>`,\n );\n });\n // subtitle\n if (r.subtitle) {\n parts.push(\n `<text x=\"${pad}\" y=\"${titleTop + titleLines.length * titleSize * 1.08 + 46}\" font-size=\"34\" font-weight=\"500\" fill=\"${esc(\n p.muted,\n )}\">${esc(r.subtitle)}</text>`,\n );\n }\n // footer\n if (r.footer) {\n parts.push(\n `<text x=\"${pad}\" y=\"${H - pad}\" font-size=\"26\" font-weight=\"500\" fill=\"${esc(p.muted)}\">${esc(\n r.footer,\n )}</text>`,\n );\n }\n\n parts.push(`</svg>`);\n return parts.join(\"\");\n}\n\n/** SVG as a `data:` URI — drop straight into `src` / `background-image`. */\nexport function ogSvgDataUri(options: OgOptions): string {\n return `data:image/svg+xml;utf8,${encodeURIComponent(ogSvg(options))}`;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @lacspace/og\n * Beautiful, dynamic Open Graph images — a design system you configure once and\n * call per page. Produces a `next/og` element tree *and* a zero-dependency SVG\n * from the same options, with auto-fitting titles, presets and palettes.\n *\n * ```tsx\n * // app/og/route.tsx\n * import { ImageResponse } from \"next/og\";\n * import { ogCard } from \"@lacspace/og\";\n *\n * export const runtime = \"edge\";\n * export function GET(req: Request) {\n * const title = new URL(req.url).searchParams.get(\"title\") ?? \"My site\";\n * return new ImageResponse(\n * ogCard({ title, subtitle: \"my-site.com\", from: \"#22d3ee\", to: \"#6366f1\" }) as any,\n * { width: 1200, height: 630 },\n * );\n * }\n * ```\n *\n * Zero dependencies · isomorphic · fully typed.\n */\n\n/* ------------------------------------------------------------------ *\n * Options\n * ------------------------------------------------------------------ */\n\nexport type OgPreset = \"gradient\" | \"split\" | \"minimal\" | \"terminal\";\nexport type OgTheme = \"dark\" | \"light\";\n\nexport interface OgOptions {\n /** The headline. Font size auto-fits to length. */\n title: string;\n /** Secondary line under the title (often your domain). */\n subtitle?: string;\n /** Small uppercase label above the title (a section or category). */\n eyebrow?: string;\n /** A pill badge (e.g. \"NEW\", \"Guide\"). */\n badge?: string;\n /** Text/initial/emoji for the corner logo mark. */\n logo?: string;\n /** Footer line, bottom-left (e.g. your URL). */\n footer?: string;\n /** Accent gradient start / end. */\n from?: string;\n to?: string;\n /** \"dark\" (default) or \"light\" ground. */\n theme?: OgTheme;\n /** Layout preset. */\n preset?: OgPreset;\n /** Canvas size. Defaults to the OG standard 1200×630. */\n width?: number;\n height?: number;\n}\n\ninterface Resolved extends Required<Omit<OgOptions, \"subtitle\" | \"eyebrow\" | \"badge\" | \"logo\" | \"footer\">> {\n subtitle?: string;\n eyebrow?: string;\n badge?: string;\n logo?: string;\n footer?: string;\n}\n\nconst DEFAULTS = {\n from: \"#22d3ee\",\n to: \"#6366f1\",\n theme: \"dark\" as OgTheme,\n preset: \"gradient\" as OgPreset,\n width: 1200,\n height: 630,\n};\n\nfunction resolve(o: OgOptions): Resolved {\n return {\n title: o.title,\n subtitle: o.subtitle,\n eyebrow: o.eyebrow,\n badge: o.badge,\n logo: o.logo,\n footer: o.footer,\n from: o.from ?? DEFAULTS.from,\n to: o.to ?? DEFAULTS.to,\n theme: o.theme ?? DEFAULTS.theme,\n preset: o.preset ?? DEFAULTS.preset,\n width: o.width ?? DEFAULTS.width,\n height: o.height ?? DEFAULTS.height,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Shared design math\n * ------------------------------------------------------------------ */\n\n/** Pick a title font size that keeps long headlines readable and short ones bold. */\nexport function fitFontSize(\n title: string,\n opts: { max?: number; min?: number } = {},\n): number {\n const max = opts.max ?? 78;\n const min = opts.min ?? 42;\n const len = title.length;\n if (len <= 20) return max;\n if (len >= 90) return min;\n // Linear falloff between the two anchors.\n const t = (len - 20) / (90 - 20);\n return Math.round(max - t * (max - min));\n}\n\ninterface Palette {\n bg: string;\n fg: string;\n muted: string;\n border: string;\n from: string;\n to: string;\n}\n\nfunction palette(r: Resolved): Palette {\n const dark = r.theme === \"dark\";\n return {\n bg: dark ? \"#0a0a0f\" : \"#ffffff\",\n fg: dark ? \"#ffffff\" : \"#0a0a0f\",\n muted: dark ? \"rgba(255,255,255,0.68)\" : \"rgba(10,10,15,0.62)\",\n border: dark ? \"rgba(255,255,255,0.14)\" : \"rgba(10,10,15,0.10)\",\n from: r.from,\n to: r.to,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * next/og element tree\n * ------------------------------------------------------------------ */\n\nexport type OgStyle = Record<string, string | number>;\nexport interface OgNode {\n type: string;\n props: { style?: OgStyle; children?: (OgNode | string)[] | OgNode | string; [k: string]: unknown };\n key?: null;\n}\n\nfunction el(type: string, style: OgStyle, children?: (OgNode | string)[] | OgNode | string): OgNode {\n return { type, key: null, props: { style, ...(children === undefined ? {} : { children }) } };\n}\n\n/**\n * Build a `next/og`-compatible element tree for a share card. Pass it straight\n * to `new ImageResponse(ogCard(opts) as any, { width, height })`.\n *\n * (The `as any` sidesteps a React type mismatch — the object is a valid Satori\n * node, which is what `next/og` renders under the hood.)\n */\nexport function ogCard(options: OgOptions): OgNode {\n const r = resolve(options);\n const p = palette(r);\n const pad = Math.round(r.width * 0.075);\n const titleSize = fitFontSize(r.title);\n\n const accentBar = el(\"div\", {\n position: \"absolute\",\n top: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${Math.round(r.height * 0.02)}px`,\n background: `linear-gradient(90deg, ${p.from}, ${p.to})`,\n });\n\n const glow = el(\"div\", {\n position: \"absolute\",\n top: `-${Math.round(r.height * 0.35)}px`,\n right: `-${Math.round(r.width * 0.18)}px`,\n width: `${Math.round(r.width * 0.55)}px`,\n height: `${Math.round(r.width * 0.55)}px`,\n borderRadius: \"9999px\",\n background: `linear-gradient(135deg, ${p.from}, ${p.to})`,\n opacity: r.theme === \"dark\" ? \"0.22\" : \"0.16\",\n filter: \"blur(20px)\",\n });\n\n const topRow: (OgNode | string)[] = [];\n if (r.eyebrow) {\n topRow.push(\n el(\n \"div\",\n {\n display: \"flex\",\n fontSize: \"26px\",\n fontWeight: 600,\n letterSpacing: \"0.12em\",\n textTransform: \"uppercase\",\n color: p.from,\n },\n r.eyebrow.toUpperCase(),\n ),\n );\n }\n if (r.badge) {\n topRow.push(\n el(\n \"div\",\n {\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px 20px\",\n borderRadius: \"9999px\",\n fontSize: \"24px\",\n fontWeight: 700,\n color: p.fg,\n background: `linear-gradient(90deg, ${p.from}33, ${p.to}33)`,\n border: `1px solid ${p.border}`,\n },\n r.badge,\n ),\n );\n }\n\n const header = el(\n \"div\",\n { display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", width: \"100%\" },\n [\n topRow.length\n ? el(\"div\", { display: \"flex\", gap: \"20px\", alignItems: \"center\" }, topRow)\n : el(\"div\", { display: \"flex\" }, \"\"),\n r.logo\n ? el(\n \"div\",\n {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"76px\",\n height: \"76px\",\n borderRadius: \"20px\",\n fontSize: \"40px\",\n fontWeight: 800,\n color: \"#0a0a0f\",\n background: `linear-gradient(135deg, ${p.from}, ${p.to})`,\n },\n r.logo,\n )\n : el(\"div\", { display: \"flex\" }, \"\"),\n ],\n );\n\n const body: (OgNode | string)[] = [\n el(\n \"div\",\n {\n display: \"flex\",\n fontSize: `${titleSize}px`,\n fontWeight: 800,\n lineHeight: 1.05,\n letterSpacing: \"-0.02em\",\n color: p.fg,\n },\n r.title,\n ),\n ];\n if (r.subtitle) {\n body.push(\n el(\n \"div\",\n { display: \"flex\", marginTop: \"28px\", fontSize: \"34px\", fontWeight: 500, color: p.muted },\n r.subtitle,\n ),\n );\n }\n\n const children: OgNode[] = [\n accentBar,\n glow,\n header,\n el(\"div\", { display: \"flex\", flexDirection: \"column\" }, body),\n ];\n\n if (r.footer) {\n children.push(\n el(\n \"div\",\n { display: \"flex\", fontSize: \"26px\", fontWeight: 500, color: p.muted },\n r.footer,\n ),\n );\n }\n\n return el(\n \"div\",\n {\n position: \"relative\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n padding: `${pad}px`,\n background: r.preset === \"split\" ? `linear-gradient(135deg, ${p.from}, ${p.to})` : p.bg,\n color: p.fg,\n fontFamily: \"sans-serif\",\n },\n children,\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Zero-dependency SVG (previews, emails, icons, guaranteed fallback)\n * ------------------------------------------------------------------ */\n\nfunction esc(s: string): string {\n return s\n .replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n}\n\n/** Greedy word-wrap by estimated glyph width. */\nfunction wrap(text: string, fontSize: number, maxWidth: number, maxLines: number): string[] {\n const charW = fontSize * 0.56;\n const perLine = Math.max(1, Math.floor(maxWidth / charW));\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let cur = \"\";\n for (const w of words) {\n const next = cur ? `${cur} ${w}` : w;\n if (next.length > perLine && cur) {\n lines.push(cur);\n cur = w;\n if (lines.length === maxLines - 1) break;\n } else {\n cur = next;\n }\n }\n if (cur && lines.length < maxLines) lines.push(cur);\n const used = lines.join(\" \").length;\n if (used < text.length && lines.length) {\n lines[lines.length - 1] = `${lines[lines.length - 1]!.replace(/\\.*$/, \"\")}…`;\n }\n return lines;\n}\n\n/**\n * Render a share card as a standalone SVG string — no browser, no runtime deps.\n * Perfect for previews, email headers, README banners and icons.\n */\nexport function ogSvg(options: OgOptions): string {\n const r = resolve(options);\n const p = palette(r);\n const W = r.width;\n const H = r.height;\n const pad = Math.round(W * 0.075);\n const titleSize = fitFontSize(r.title);\n const contentW = W - pad * 2;\n const split = r.preset === \"split\";\n\n const titleLines = wrap(r.title, titleSize, contentW, 3);\n const titleBlockH = titleLines.length * titleSize * 1.08;\n const titleTop = H / 2 - titleBlockH / 2 + titleSize * 0.8;\n\n const parts: string[] = [];\n parts.push(\n `<svg width=\"${W}\" height=\"${H}\" viewBox=\"0 0 ${W} ${H}\" xmlns=\"http://www.w3.org/2000/svg\" font-family=\"Inter, ui-sans-serif, system-ui, sans-serif\">`,\n );\n parts.push(`<defs>\n <linearGradient id=\"accent\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0\" stop-color=\"${esc(p.from)}\"/><stop offset=\"1\" stop-color=\"${esc(p.to)}\"/>\n </linearGradient>\n <radialGradient id=\"glow\" cx=\"0.85\" cy=\"0.1\" r=\"0.7\">\n <stop offset=\"0\" stop-color=\"${esc(p.from)}\" stop-opacity=\"${r.theme === \"dark\" ? 0.28 : 0.2}\"/>\n <stop offset=\"1\" stop-color=\"${esc(p.to)}\" stop-opacity=\"0\"/>\n </radialGradient>\n </defs>`);\n\n // background\n parts.push(`<rect width=\"${W}\" height=\"${H}\" fill=\"${split ? \"url(#accent)\" : esc(p.bg)}\"/>`);\n if (!split) parts.push(`<rect width=\"${W}\" height=\"${H}\" fill=\"url(#glow)\"/>`);\n // accent bar\n parts.push(`<rect width=\"${W}\" height=\"${Math.round(H * 0.02)}\" fill=\"url(#accent)\"/>`);\n\n // eyebrow\n let topY = pad + 34;\n if (r.eyebrow) {\n parts.push(\n `<text x=\"${pad}\" y=\"${topY}\" font-size=\"26\" font-weight=\"600\" letter-spacing=\"3\" fill=\"${esc(p.from)}\">${esc(\n r.eyebrow.toUpperCase(),\n )}</text>`,\n );\n }\n // logo mark (top-right)\n if (r.logo) {\n const s = 76;\n const lx = W - pad - s;\n const ly = pad;\n parts.push(`<rect x=\"${lx}\" y=\"${ly}\" width=\"${s}\" height=\"${s}\" rx=\"20\" fill=\"url(#accent)\"/>`);\n parts.push(\n `<text x=\"${lx + s / 2}\" y=\"${ly + s / 2 + 14}\" font-size=\"40\" font-weight=\"800\" text-anchor=\"middle\" fill=\"#0a0a0f\">${esc(\n r.logo,\n )}</text>`,\n );\n }\n // badge\n if (r.badge) {\n const bx = pad + (r.eyebrow ? 0 : 0);\n parts.push(\n `<rect x=\"${bx}\" y=\"${topY + 14}\" width=\"${r.badge.length * 16 + 40}\" height=\"44\" rx=\"22\" fill=\"${esc(\n p.from,\n )}\" opacity=\"0.18\"/>`,\n );\n parts.push(\n `<text x=\"${bx + 20}\" y=\"${topY + 43}\" font-size=\"24\" font-weight=\"700\" fill=\"${esc(p.fg)}\">${esc(\n r.badge,\n )}</text>`,\n );\n topY += 60;\n }\n\n // title (wrapped)\n titleLines.forEach((line, i) => {\n parts.push(\n `<text x=\"${pad}\" y=\"${titleTop + i * titleSize * 1.08}\" font-size=\"${titleSize}\" font-weight=\"800\" letter-spacing=\"-1\" fill=\"${esc(\n p.fg,\n )}\">${esc(line)}</text>`,\n );\n });\n // subtitle\n if (r.subtitle) {\n parts.push(\n `<text x=\"${pad}\" y=\"${titleTop + titleLines.length * titleSize * 1.08 + 46}\" font-size=\"34\" font-weight=\"500\" fill=\"${esc(\n p.muted,\n )}\">${esc(r.subtitle)}</text>`,\n );\n }\n // footer\n if (r.footer) {\n parts.push(\n `<text x=\"${pad}\" y=\"${H - pad}\" font-size=\"26\" font-weight=\"500\" fill=\"${esc(p.muted)}\">${esc(\n r.footer,\n )}</text>`,\n );\n }\n\n parts.push(`</svg>`);\n return parts.join(\"\");\n}\n\n/** SVG as a `data:` URI — drop straight into `src` / `background-image`. */\nexport function ogSvgDataUri(options: OgOptions): string {\n return `data:image/svg+xml;utf8,${encodeURIComponent(ogSvg(options))}`;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lacspace/og",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Dynamic Open Graph images — a share-card design system you configure once and call per page. Produces a next/og element tree AND a zero-dependency SVG from the same options, with auto-fitting titles, presets, badges and gradients. Zero-dependency, isomorphic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|