@ewanc26/og 0.1.5 → 0.1.6

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/src/fonts.ts CHANGED
@@ -1,73 +1,13 @@
1
1
  /**
2
2
  * @ewanc26/og fonts
3
3
  *
4
- * Font loading utilities. Bundles Inter font by default.
4
+ * Font loading utilities. Fonts are inlined as base64 at build time so this
5
+ * works in serverless environments (Vercel, Netlify, etc.) without any
6
+ * filesystem access to node_modules.
5
7
  */
6
8
 
7
- import { readFile } from 'node:fs/promises'
8
- import { existsSync } from 'node:fs'
9
- import { dirname, resolve } from 'node:path'
10
- import { fileURLToPath } from 'node:url'
9
+ import { INTER_BOLD_B64, INTER_REGULAR_B64 } from './fonts-base64.js'
11
10
  import type { OgFontConfig } from './types.js'
12
- import { loadEmbeddedFonts } from './fonts-data.js'
13
-
14
- // Declare __dirname for CJS contexts (injected by bundlers)
15
- declare const __dirname: string | undefined
16
-
17
- // ─── Paths ────────────────────────────────────────────────────────────────────
18
-
19
- /**
20
- * Get the directory of the current module.
21
- * Works in both ESM and bundled contexts.
22
- */
23
- function getModuleDir(): string {
24
- // ESM context
25
- if (typeof import.meta !== 'undefined' && import.meta.url) {
26
- return dirname(fileURLToPath(import.meta.url))
27
- }
28
- // Bundled CJS context - __dirname is injected by bundlers
29
- if (typeof __dirname !== 'undefined') {
30
- return __dirname
31
- }
32
- // Fallback
33
- return resolve(process.cwd(), 'node_modules/@ewanc26/og/dist')
34
- }
35
-
36
- /**
37
- * Resolve the fonts directory relative to the installed package.
38
- * Tries multiple possible locations for serverless compatibility.
39
- */
40
- function getFontsDir(): string {
41
- const candidates = [
42
- // Standard: fonts next to dist
43
- resolve(getModuleDir(), '../fonts'),
44
- // Vercel serverless: fonts inside dist
45
- resolve(getModuleDir(), 'fonts'),
46
- // Fallback: node_modules path
47
- resolve(process.cwd(), 'node_modules/@ewanc26/og/fonts'),
48
- ]
49
-
50
- for (const dir of candidates) {
51
- if (existsSync(dir)) {
52
- return dir
53
- }
54
- }
55
-
56
- // Return first candidate as fallback (will fail gracefully)
57
- return candidates[0]
58
- }
59
-
60
- /**
61
- * Resolve bundled font paths. Uses getters to defer resolution until runtime.
62
- */
63
- export const BUNDLED_FONTS = {
64
- get heading() {
65
- return resolve(getFontsDir(), 'Inter-Bold.ttf')
66
- },
67
- get body() {
68
- return resolve(getFontsDir(), 'Inter-Regular.ttf')
69
- },
70
- } as const
71
11
 
72
12
  // ─── Font Loading ──────────────────────────────────────────────────────────────
73
13
 
@@ -76,43 +16,36 @@ export interface LoadedFonts {
76
16
  body: ArrayBuffer
77
17
  }
78
18
 
79
- /**
80
- * Helper to convert Buffer to ArrayBuffer
81
- */
82
- function toArrayBuffer(buf: Buffer): ArrayBuffer {
19
+ function base64ToArrayBuffer(b64: string): ArrayBuffer {
20
+ const buf = Buffer.from(b64, 'base64')
83
21
  return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer
84
22
  }
85
23
 
86
24
  /**
87
- * Load fonts from config, falling back to bundled fonts.
25
+ * Load fonts from config, falling back to the bundled Inter font.
26
+ * If custom paths are provided they are loaded from disk; otherwise the
27
+ * pre-inlined base64 data is used (safe in any serverless runtime).
88
28
  */
89
29
  export async function loadFonts(config?: OgFontConfig): Promise<LoadedFonts> {
90
- const headingPath = config?.heading ?? BUNDLED_FONTS.heading
91
- const bodyPath = config?.body ?? BUNDLED_FONTS.body
92
-
93
- const [heading, body] = await Promise.all([
94
- loadFontFile(headingPath),
95
- loadFontFile(bodyPath),
96
- ])
97
-
98
- return { heading, body }
99
- }
100
-
101
- /**
102
- * Load a font from file path.
103
- * Falls back to alternative locations if local file not found.
104
- */
105
- async function loadFontFile(source: string): Promise<ArrayBuffer> {
106
- try {
107
- const buffer = await readFile(source)
108
- return toArrayBuffer(buffer)
109
- } catch (error) {
110
- // Try embedded fonts (loaded from alternative locations)
111
- const embedded = await loadEmbeddedFonts()
112
- if (embedded) {
113
- return source.includes('Bold') ? embedded.heading : embedded.body
30
+ if (config?.heading || config?.body) {
31
+ const { readFile } = await import('node:fs/promises')
32
+ const [headingBuf, bodyBuf] = await Promise.all([
33
+ config.heading ? readFile(config.heading) : Buffer.from(INTER_BOLD_B64, 'base64'),
34
+ config.body ? readFile(config.body) : Buffer.from(INTER_REGULAR_B64, 'base64'),
35
+ ])
36
+ return {
37
+ heading: headingBuf instanceof Buffer
38
+ ? (headingBuf.buffer.slice(headingBuf.byteOffset, headingBuf.byteOffset + headingBuf.byteLength) as ArrayBuffer)
39
+ : headingBuf.buffer,
40
+ body: bodyBuf instanceof Buffer
41
+ ? (bodyBuf.buffer.slice(bodyBuf.byteOffset, bodyBuf.byteOffset + bodyBuf.byteLength) as ArrayBuffer)
42
+ : bodyBuf.buffer,
114
43
  }
115
- throw new Error(`Failed to load font from ${source}`)
44
+ }
45
+
46
+ return {
47
+ heading: base64ToArrayBuffer(INTER_BOLD_B64),
48
+ body: base64ToArrayBuffer(INTER_REGULAR_B64),
116
49
  }
117
50
  }
118
51
 
@@ -127,21 +60,10 @@ export type SatoriFontConfig = {
127
60
 
128
61
  /**
129
62
  * Create Satori-compatible font config from loaded fonts.
130
- * Uses Inter font family with weight 700 for headings and 400 for body.
131
63
  */
132
64
  export function createSatoriFonts(fonts: LoadedFonts): SatoriFontConfig[] {
133
65
  return [
134
- {
135
- name: 'Inter',
136
- data: fonts.heading,
137
- weight: 700,
138
- style: 'normal',
139
- },
140
- {
141
- name: 'Inter',
142
- data: fonts.body,
143
- weight: 400,
144
- style: 'normal',
145
- },
66
+ { name: 'Inter', data: fonts.heading, weight: 700, style: 'normal' },
67
+ { name: 'Inter', data: fonts.body, weight: 400, style: 'normal' },
146
68
  ]
147
69
  }
package/src/index.ts CHANGED
@@ -41,7 +41,7 @@ export { defaultColors } from './types.js'
41
41
  export { generateNoiseDataUrl, generateCircleNoiseDataUrl } from './noise.js'
42
42
 
43
43
  // Fonts (for advanced customization)
44
- export { loadFonts, createSatoriFonts, BUNDLED_FONTS } from './fonts.js'
44
+ export { loadFonts, createSatoriFonts } from './fonts.js'
45
45
 
46
46
  // Endpoint helpers
47
47
  export { createOgEndpoint } from './endpoint.js'
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js","../src/templates/blog.ts","../src/templates/profile.ts","../src/templates/default.ts","../src/templates/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","/**\n * Blog OG template.\n * Clean centered layout.\n */\n\nimport type { OgTemplateProps } from '../types.js'\n\nexport function blogTemplate({\n\ttitle,\n\tdescription,\n\tsiteName,\n\tcolors,\n\tnoiseDataUrl,\n\twidth,\n\theight,\n}: OgTemplateProps) {\n\treturn {\n\t\ttype: 'div',\n\t\tprops: {\n\t\t\tstyle: {\n\t\t\t\tposition: 'relative',\n\t\t\t\tdisplay: 'flex',\n\t\t\t\tflexDirection: 'column',\n\t\t\t\talignItems: 'center',\n\t\t\t\tjustifyContent: 'center',\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tbackgroundColor: colors.background,\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\tnoiseDataUrl ? {\n\t\t\t\t\ttype: 'img',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsrc: noiseDataUrl,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\t\tleft: 0,\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t} : null,\n\t\t\t\t{\n\t\t\t\t\ttype: 'div',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tposition: 'relative',\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\tpadding: '0 60px',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'h1',\n\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\tfontSize: 64,\n\t\t\t\t\t\t\t\t\t\tfontWeight: 700,\n\t\t\t\t\t\t\t\t\t\tcolor: colors.text,\n\t\t\t\t\t\t\t\t\t\tletterSpacing: '-0.02em',\n\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t\t\tlineHeight: 1.1,\n\t\t\t\t\t\t\t\t\t\tmaxWidth: 1000,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchildren: title,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdescription ? {\n\t\t\t\t\t\t\t\ttype: 'p',\n\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\tfontSize: 28,\n\t\t\t\t\t\t\t\t\t\tfontWeight: 400,\n\t\t\t\t\t\t\t\t\t\tcolor: colors.accent,\n\t\t\t\t\t\t\t\t\t\tmarginTop: 28,\n\t\t\t\t\t\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t\t\tlineHeight: 1.4,\n\t\t\t\t\t\t\t\t\t\tmaxWidth: 900,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchildren: description,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t} : null,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'p',\n\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\tfontSize: 24,\n\t\t\t\t\t\t\t\t\t\tfontWeight: 400,\n\t\t\t\t\t\t\t\t\t\tcolor: colors.accent,\n\t\t\t\t\t\t\t\t\t\tmarginTop: 56,\n\t\t\t\t\t\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t\t\topacity: 0.7,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchildren: siteName,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t].filter(Boolean),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t].filter(Boolean),\n\t\t},\n\t}\n}\n","/**\n * Profile OG template.\n * Centered layout.\n */\n\nimport type { OgTemplateProps } from '../types.js'\n\nexport function profileTemplate({\n\ttitle,\n\tdescription,\n\tsiteName,\n\timage,\n\tcolors,\n\tnoiseDataUrl,\n\twidth,\n\theight,\n}: OgTemplateProps) {\n\tconst contentChildren: unknown[] = []\n\n\tif (image) {\n\t\tcontentChildren.push({\n\t\t\ttype: 'img',\n\t\t\tprops: {\n\t\t\t\tsrc: image,\n\t\t\t\twidth: 120,\n\t\t\t\theight: 120,\n\t\t\t\tstyle: {\n\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\tmarginBottom: 32,\n\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t}\n\n\tcontentChildren.push({\n\t\ttype: 'h1',\n\t\tprops: {\n\t\t\tstyle: {\n\t\t\t\tfontSize: 56,\n\t\t\t\tfontWeight: 700,\n\t\t\t\tcolor: colors.text,\n\t\t\t\tletterSpacing: '-0.02em',\n\t\t\t\tmargin: 0,\n\t\t\t\ttextAlign: 'center',\n\t\t\t\tlineHeight: 1.1,\n\t\t\t\tmaxWidth: 900,\n\t\t\t},\n\t\t\tchildren: title,\n\t\t},\n\t})\n\n\tif (description) {\n\t\tcontentChildren.push({\n\t\t\ttype: 'p',\n\t\t\tprops: {\n\t\t\t\tstyle: {\n\t\t\t\t\tfontSize: 26,\n\t\t\t\t\tfontWeight: 400,\n\t\t\t\t\tcolor: colors.accent,\n\t\t\t\t\tmarginTop: 20,\n\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\tlineHeight: 1.4,\n\t\t\t\t\tmaxWidth: 700,\n\t\t\t\t},\n\t\t\t\tchildren: description,\n\t\t\t},\n\t\t})\n\t}\n\n\tcontentChildren.push({\n\t\ttype: 'p',\n\t\tprops: {\n\t\t\tstyle: {\n\t\t\t\tfontSize: 24,\n\t\t\t\tfontWeight: 400,\n\t\t\t\tcolor: colors.accent,\n\t\t\t\tmarginTop: 48,\n\t\t\t\tmarginBottom: 0,\n\t\t\t\ttextAlign: 'center',\n\t\t\t\topacity: 0.7,\n\t\t\t},\n\t\t\tchildren: siteName,\n\t\t},\n\t})\n\n\treturn {\n\t\ttype: 'div',\n\t\tprops: {\n\t\t\tstyle: {\n\t\t\t\tposition: 'relative',\n\t\t\t\tdisplay: 'flex',\n\t\t\t\tflexDirection: 'column',\n\t\t\t\talignItems: 'center',\n\t\t\t\tjustifyContent: 'center',\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tbackgroundColor: colors.background,\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\tnoiseDataUrl ? {\n\t\t\t\t\ttype: 'img',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsrc: noiseDataUrl,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\t\tleft: 0,\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t} : null,\n\t\t\t\t{\n\t\t\t\t\ttype: 'div',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tposition: 'relative',\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\tpadding: '0 60px',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tchildren: contentChildren,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t].filter(Boolean),\n\t\t},\n\t}\n}\n","/**\n * Default OG template.\n * Clean, centered layout.\n */\n\nimport type { OgTemplateProps } from '../types.js'\n\nexport function defaultTemplate({\n\ttitle,\n\tdescription,\n\tsiteName,\n\tcolors,\n\tnoiseDataUrl,\n\twidth,\n\theight,\n}: OgTemplateProps) {\n\treturn {\n\t\ttype: 'div',\n\t\tprops: {\n\t\t\tstyle: {\n\t\t\t\tposition: 'relative',\n\t\t\t\tdisplay: 'flex',\n\t\t\t\tflexDirection: 'column',\n\t\t\t\talignItems: 'center',\n\t\t\t\tjustifyContent: 'center',\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tbackgroundColor: colors.background,\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\tnoiseDataUrl ? {\n\t\t\t\t\ttype: 'img',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsrc: noiseDataUrl,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\t\tleft: 0,\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t} : null,\n\t\t\t\t{\n\t\t\t\t\ttype: 'div',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tposition: 'relative',\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\tpadding: '0 60px',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'h1',\n\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\tfontSize: 72,\n\t\t\t\t\t\t\t\t\t\tfontWeight: 700,\n\t\t\t\t\t\t\t\t\t\tcolor: colors.text,\n\t\t\t\t\t\t\t\t\t\tletterSpacing: '-0.02em',\n\t\t\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchildren: title,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdescription ? {\n\t\t\t\t\t\t\t\ttype: 'p',\n\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\tfontSize: 32,\n\t\t\t\t\t\t\t\t\t\tfontWeight: 400,\n\t\t\t\t\t\t\t\t\t\tcolor: colors.accent,\n\t\t\t\t\t\t\t\t\t\tmarginTop: 24,\n\t\t\t\t\t\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t\t\tmaxWidth: 900,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchildren: description,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t} : null,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'p',\n\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\tfontSize: 28,\n\t\t\t\t\t\t\t\t\t\tfontWeight: 400,\n\t\t\t\t\t\t\t\t\t\tcolor: colors.accent,\n\t\t\t\t\t\t\t\t\t\tmarginTop: 64,\n\t\t\t\t\t\t\t\t\t\tmarginBottom: 0,\n\t\t\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\t\t\topacity: 0.7,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchildren: siteName,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t].filter(Boolean),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t].filter(Boolean),\n\t\t},\n\t}\n}\n","/**\n * Built-in OG templates.\n */\n\nexport { blogTemplate } from './blog.js'\nexport { profileTemplate } from './profile.js'\nexport { defaultTemplate } from './default.js'\n\nimport { blogTemplate } from './blog.js'\nimport { profileTemplate } from './profile.js'\nimport { defaultTemplate } from './default.js'\nimport type { OgTemplate } from '../types.js'\n\nexport const templates = {\n\tblog: blogTemplate,\n\tprofile: profileTemplate,\n\tdefault: defaultTemplate,\n} as const\n\nexport type TemplateName = keyof typeof templates\n\nexport function getTemplate(name: TemplateName | OgTemplate): OgTemplate {\n\tif (typeof name === 'function') {\n\t\treturn name\n\t}\n\treturn templates[name]\n}\n"],"mappings":"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","names":[]}
Binary file
Binary file
package/src/fonts-data.ts DELETED
@@ -1,61 +0,0 @@
1
- /**
2
- * Font loading helper for serverless environments
3
- */
4
-
5
- import { readFile } from 'node:fs/promises'
6
- import { dirname, resolve } from 'node:path'
7
- import { fileURLToPath } from 'node:url'
8
-
9
- // Declare __dirname for CJS contexts (injected by bundlers)
10
- declare const __dirname: string | undefined
11
-
12
- function getModuleDir(): string {
13
- if (typeof import.meta !== 'undefined' && import.meta.url) {
14
- return dirname(fileURLToPath(import.meta.url))
15
- }
16
- if (typeof __dirname !== 'undefined') {
17
- return __dirname
18
- }
19
- return resolve(process.cwd(), 'node_modules/@ewanc26/og/dist')
20
- }
21
-
22
- export interface FontData {
23
- heading: ArrayBuffer
24
- body: ArrayBuffer
25
- }
26
-
27
- /**
28
- * Try loading fonts from dist/fonts directory
29
- */
30
- export async function loadEmbeddedFonts(): Promise<FontData | null> {
31
- const moduleDir = getModuleDir()
32
-
33
- const paths = [
34
- {
35
- heading: resolve(moduleDir, 'fonts/Inter-Bold.ttf'),
36
- body: resolve(moduleDir, 'fonts/Inter-Regular.ttf'),
37
- },
38
- {
39
- heading: resolve(moduleDir, '../fonts/Inter-Bold.ttf'),
40
- body: resolve(moduleDir, '../fonts/Inter-Regular.ttf'),
41
- },
42
- ]
43
-
44
- for (const p of paths) {
45
- try {
46
- const [headingBuf, bodyBuf] = await Promise.all([
47
- readFile(p.heading),
48
- readFile(p.body),
49
- ])
50
- // Convert Buffer to ArrayBuffer
51
- return {
52
- heading: headingBuf.buffer.slice(headingBuf.byteOffset, headingBuf.byteOffset + headingBuf.byteLength),
53
- body: bodyBuf.buffer.slice(bodyBuf.byteOffset, bodyBuf.byteOffset + bodyBuf.byteLength),
54
- }
55
- } catch {
56
- continue
57
- }
58
- }
59
-
60
- return null
61
- }