@vercel/og 0.8.0 → 0.8.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.edge.d.ts +1 -2
- package/dist/index.edge.js +1 -203
- package/dist/index.edge.js.map +1 -1
- package/dist/index.node.d.ts +1 -2
- package/dist/index.node.js +0 -202
- package/dist/index.node.js.map +1 -1
- package/package.json +1 -1
- package/dist/figma/index.d.ts +0 -7
package/dist/index.node.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { ReactElement } from 'react';
|
|
3
|
-
import type { ImageResponseNodeOptions, ImageResponseOptions
|
|
3
|
+
import type { ImageResponseNodeOptions, ImageResponseOptions } from './types';
|
|
4
4
|
import { Readable } from 'stream';
|
|
5
5
|
export declare class ImageResponse extends Response {
|
|
6
6
|
constructor(element: ReactElement, options?: ImageResponseOptions);
|
|
@@ -23,5 +23,4 @@ export declare class ImageResponse extends Response {
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
export declare function unstable_createNodejsStream(element: ReactElement, options?: Omit<ImageResponseNodeOptions, 'status' | 'statusText' | 'headers'>): Promise<Readable>;
|
|
26
|
-
export declare const experimental_FigmaImageResponse: (props: FigmaImageResponseProps) => Promise<import("./index.edge").ImageResponse>;
|
|
27
26
|
export type NodeImageResponse = typeof ImageResponse;
|
package/dist/index.node.js
CHANGED
|
@@ -20528,204 +20528,6 @@ async function render(satori2, resvg, opts, defaultFonts, element) {
|
|
|
20528
20528
|
return pngBuffer;
|
|
20529
20529
|
}
|
|
20530
20530
|
|
|
20531
|
-
// src/figma/index.tsx
|
|
20532
|
-
var FigmaImageResponse = async ({
|
|
20533
|
-
url,
|
|
20534
|
-
template,
|
|
20535
|
-
fonts,
|
|
20536
|
-
imageResponseOptions,
|
|
20537
|
-
Response: Response2
|
|
20538
|
-
}) => {
|
|
20539
|
-
const { fileId, nodeId } = parseFigmaUrl(url);
|
|
20540
|
-
const figmaAPIToken = assertValue(
|
|
20541
|
-
process.env.FIGMA_PERSONAL_ACCESS_TOKEN,
|
|
20542
|
-
"Missing environment variable: `FIGMA_PERSONAL_ACCESS_TOKEN`. You can get one at https://www.figma.com/developers/api#authentication"
|
|
20543
|
-
);
|
|
20544
|
-
const figmaResponse = await fetch(
|
|
20545
|
-
`https://api.figma.com/v1/images/${fileId}?ids=${nodeId}&svg_outline_text=false&format=svg&svg_include_id=true`,
|
|
20546
|
-
{
|
|
20547
|
-
method: "GET",
|
|
20548
|
-
headers: {
|
|
20549
|
-
"X-FIGMA-TOKEN": figmaAPIToken
|
|
20550
|
-
},
|
|
20551
|
-
cache: "no-store"
|
|
20552
|
-
}
|
|
20553
|
-
);
|
|
20554
|
-
const figmaResponseJson = await figmaResponse.json();
|
|
20555
|
-
const svgDownloadPath = figmaResponseJson.images[nodeId.replace("-", ":")];
|
|
20556
|
-
const svgResponse = await fetch(svgDownloadPath, { cache: "no-store" });
|
|
20557
|
-
const svg = await svgResponse.text();
|
|
20558
|
-
const { width, height } = getSvgDimensions(svg);
|
|
20559
|
-
const textNodes = getTextNodes(svg);
|
|
20560
|
-
const textNodeAttributes = textNodes.map(parseSvgText);
|
|
20561
|
-
return new Response2(
|
|
20562
|
-
{
|
|
20563
|
-
key: "0",
|
|
20564
|
-
type: "div",
|
|
20565
|
-
props: {
|
|
20566
|
-
style: { display: "flex" },
|
|
20567
|
-
children: [
|
|
20568
|
-
{
|
|
20569
|
-
type: "img",
|
|
20570
|
-
props: {
|
|
20571
|
-
style: { position: "absolute" },
|
|
20572
|
-
alt: "",
|
|
20573
|
-
width,
|
|
20574
|
-
height,
|
|
20575
|
-
src: svgToBase64(svg)
|
|
20576
|
-
}
|
|
20577
|
-
},
|
|
20578
|
-
{
|
|
20579
|
-
type: "div",
|
|
20580
|
-
props: {
|
|
20581
|
-
style: { display: "flex", position: "relative", width: "100%" },
|
|
20582
|
-
children: textNodeAttributes.map((textNode) => {
|
|
20583
|
-
const t = template[textNode.id];
|
|
20584
|
-
let value = "";
|
|
20585
|
-
if (t === void 0) {
|
|
20586
|
-
value = textNode.content;
|
|
20587
|
-
} else if (isComplexTemplate(t)) {
|
|
20588
|
-
value = t.value;
|
|
20589
|
-
} else {
|
|
20590
|
-
value = t;
|
|
20591
|
-
}
|
|
20592
|
-
let cssProps = {};
|
|
20593
|
-
let centerHorizontally = false;
|
|
20594
|
-
if (isComplexTemplate(t) && t.props) {
|
|
20595
|
-
const {
|
|
20596
|
-
centerHorizontally: centerHorizontallyProp,
|
|
20597
|
-
...otherCSSProps
|
|
20598
|
-
} = t.props;
|
|
20599
|
-
cssProps = otherCSSProps;
|
|
20600
|
-
centerHorizontally = centerHorizontallyProp || false;
|
|
20601
|
-
}
|
|
20602
|
-
if (centerHorizontally) {
|
|
20603
|
-
const templateStyles = {
|
|
20604
|
-
color: textNode.fill,
|
|
20605
|
-
marginTop: `${parseInt(textNode.y) - parseInt(textNode.fontSize)}px`,
|
|
20606
|
-
fontWeight: textNode.fontWeight || "400",
|
|
20607
|
-
fontSize: textNode.fontSize,
|
|
20608
|
-
fontFamily: textNode.fontFamily,
|
|
20609
|
-
letterSpacing: textNode.letterSpacing,
|
|
20610
|
-
textAlign: "center",
|
|
20611
|
-
...cssProps
|
|
20612
|
-
};
|
|
20613
|
-
return {
|
|
20614
|
-
type: "div",
|
|
20615
|
-
props: {
|
|
20616
|
-
style: {
|
|
20617
|
-
display: "flex",
|
|
20618
|
-
justifyContent: "center",
|
|
20619
|
-
position: "absolute",
|
|
20620
|
-
width: "100%"
|
|
20621
|
-
},
|
|
20622
|
-
children: {
|
|
20623
|
-
type: "div",
|
|
20624
|
-
props: {
|
|
20625
|
-
style: templateStyles,
|
|
20626
|
-
children: value
|
|
20627
|
-
}
|
|
20628
|
-
}
|
|
20629
|
-
}
|
|
20630
|
-
};
|
|
20631
|
-
}
|
|
20632
|
-
return {
|
|
20633
|
-
type: "div",
|
|
20634
|
-
props: {
|
|
20635
|
-
style: {
|
|
20636
|
-
position: "absolute",
|
|
20637
|
-
color: textNode.fill,
|
|
20638
|
-
left: `${textNode.x}px`,
|
|
20639
|
-
top: `${parseInt(textNode.y) - parseInt(textNode.fontSize)}px`,
|
|
20640
|
-
fontWeight: textNode.fontWeight || "400",
|
|
20641
|
-
fontSize: textNode.fontSize,
|
|
20642
|
-
fontFamily: textNode.fontFamily,
|
|
20643
|
-
letterSpacing: textNode.letterSpacing,
|
|
20644
|
-
...cssProps
|
|
20645
|
-
},
|
|
20646
|
-
children: value
|
|
20647
|
-
}
|
|
20648
|
-
};
|
|
20649
|
-
})
|
|
20650
|
-
}
|
|
20651
|
-
}
|
|
20652
|
-
]
|
|
20653
|
-
}
|
|
20654
|
-
},
|
|
20655
|
-
{
|
|
20656
|
-
width,
|
|
20657
|
-
height,
|
|
20658
|
-
fonts,
|
|
20659
|
-
...imageResponseOptions
|
|
20660
|
-
}
|
|
20661
|
-
);
|
|
20662
|
-
};
|
|
20663
|
-
var isComplexTemplate = (template) => {
|
|
20664
|
-
return typeof template !== "string" && template !== void 0 && "value" in template;
|
|
20665
|
-
};
|
|
20666
|
-
function svgToBase64(svg) {
|
|
20667
|
-
const base64 = Buffer.from(svg).toString("base64");
|
|
20668
|
-
return "data:image/svg+xml;base64," + base64;
|
|
20669
|
-
}
|
|
20670
|
-
function getSvgDimensions(svg) {
|
|
20671
|
-
const widthMatch = svg.match(/width="(\d+)/);
|
|
20672
|
-
const heightMatch = svg.match(/height="(\d+)/);
|
|
20673
|
-
if (widthMatch && heightMatch) {
|
|
20674
|
-
const width = parseInt(widthMatch[1], 10);
|
|
20675
|
-
const height = parseInt(heightMatch[1], 10);
|
|
20676
|
-
return { width, height };
|
|
20677
|
-
}
|
|
20678
|
-
return { width: 0, height: 0 };
|
|
20679
|
-
}
|
|
20680
|
-
function getTextNodes(svg) {
|
|
20681
|
-
const regex = /<text[^>]*>(.*?)<\/text>/g;
|
|
20682
|
-
let match;
|
|
20683
|
-
const matches = [];
|
|
20684
|
-
while ((match = regex.exec(svg)) !== null) {
|
|
20685
|
-
matches.push(match[0]);
|
|
20686
|
-
}
|
|
20687
|
-
return matches;
|
|
20688
|
-
}
|
|
20689
|
-
function parseSvgText(svgText) {
|
|
20690
|
-
const id = svgText.match(/id="([^"]*)"/)?.[1] || "";
|
|
20691
|
-
const fill = svgText.match(/fill="([^"]*)"/)?.[1] || "";
|
|
20692
|
-
const fontFamily = svgText.match(/font-family="([^"]*)"/)?.[1] || "";
|
|
20693
|
-
const fontSize = svgText.match(/font-size="([^"]*)"/)?.[1] || "";
|
|
20694
|
-
const fontWeight = svgText.match(/font-weight="([^"]*)"/)?.[1] || "";
|
|
20695
|
-
const letterSpacing = svgText.match(/letter-spacing="([^"]*)"/)?.[1] || "";
|
|
20696
|
-
const x2 = svgText.match(/<tspan[^>]*x="([^"]*)"/)?.[1] || "";
|
|
20697
|
-
const y = svgText.match(/<tspan[^>]*y="([^"]*)"/)?.[1] || "";
|
|
20698
|
-
const content = svgText.match(/<tspan[^>]*>([^<]*)<\/tspan>/)?.[1] || "";
|
|
20699
|
-
return {
|
|
20700
|
-
id,
|
|
20701
|
-
fill,
|
|
20702
|
-
fontFamily,
|
|
20703
|
-
fontSize,
|
|
20704
|
-
fontWeight,
|
|
20705
|
-
letterSpacing,
|
|
20706
|
-
x: x2,
|
|
20707
|
-
y,
|
|
20708
|
-
content
|
|
20709
|
-
};
|
|
20710
|
-
}
|
|
20711
|
-
function parseFigmaUrl(figmaUrl) {
|
|
20712
|
-
const regex = /\/file\/([^/]+)\/[^?]+\?[^#]*node-id=([^&#]+)/;
|
|
20713
|
-
const match = figmaUrl.match(regex);
|
|
20714
|
-
let fileId = "";
|
|
20715
|
-
let nodeId = "";
|
|
20716
|
-
if (match) {
|
|
20717
|
-
fileId = match[1] || "";
|
|
20718
|
-
nodeId = match[2] || "";
|
|
20719
|
-
}
|
|
20720
|
-
return { fileId, nodeId };
|
|
20721
|
-
}
|
|
20722
|
-
function assertValue(v2, errorMessage) {
|
|
20723
|
-
if (v2 === void 0) {
|
|
20724
|
-
throw new Error(errorMessage);
|
|
20725
|
-
}
|
|
20726
|
-
return v2;
|
|
20727
|
-
}
|
|
20728
|
-
|
|
20729
20531
|
// src/index.node.ts
|
|
20730
20532
|
var satori = Tl.default || Tl;
|
|
20731
20533
|
var fontData = fs2.readFileSync(
|
|
@@ -20785,12 +20587,8 @@ async function unstable_createNodejsStream(element, options = {}) {
|
|
|
20785
20587
|
const result = await render(satori, resvg_wasm_exports, options, fonts, element);
|
|
20786
20588
|
return Readable.from(Buffer.from(result));
|
|
20787
20589
|
}
|
|
20788
|
-
var experimental_FigmaImageResponse = async (props) => {
|
|
20789
|
-
return FigmaImageResponse({ ...props, Response: ImageResponse });
|
|
20790
|
-
};
|
|
20791
20590
|
export {
|
|
20792
20591
|
ImageResponse,
|
|
20793
|
-
experimental_FigmaImageResponse,
|
|
20794
20592
|
unstable_createNodejsStream
|
|
20795
20593
|
};
|
|
20796
20594
|
/*! Copyright Twitter Inc. and other contributors. Licensed under MIT */
|