feat(nuxt): nuxt3 -> nuxt4
This commit is contained in:
10
shared/utils/formatting.ts
Normal file
10
shared/utils/formatting.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export const capitalize = (str: string) =>
|
||||
str.charAt(0).toUpperCase() + str.slice(1);
|
||||
|
||||
export const upperCase = (str: string) => str.toUpperCase();
|
||||
|
||||
export const arrayToUnion = (array: string[] | readonly string[]) =>
|
||||
array.map((x) => `"${x}"`).join(" | ");
|
||||
|
||||
export const unreadonly = <T extends string>(arr: readonly T[]): string[] =>
|
||||
[...arr] as string[];
|
||||
53
shared/utils/renderer.ts
Normal file
53
shared/utils/renderer.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Canvas, loadImage } from "skia-canvas";
|
||||
import QRCode from "qrcode";
|
||||
|
||||
const CANVAS_SIZE = 1000;
|
||||
const LOGO_PADDING = 1;
|
||||
|
||||
export const renderQRCodeToCanvas = async (
|
||||
content: string,
|
||||
logoUrl: string | undefined,
|
||||
) => {
|
||||
const canvas = new Canvas(CANVAS_SIZE, CANVAS_SIZE);
|
||||
const errorCorrectionLevel: QRCode.QRCodeErrorCorrectionLevel = logoUrl
|
||||
? "H"
|
||||
: "M";
|
||||
|
||||
await QRCode.toCanvas(canvas, content, {
|
||||
errorCorrectionLevel,
|
||||
width: CANVAS_SIZE,
|
||||
margin: 1,
|
||||
});
|
||||
|
||||
if (!logoUrl) return canvas;
|
||||
|
||||
const qrCode = QRCode.create(content, { errorCorrectionLevel });
|
||||
const moduleCount = qrCode.modules.size + 2;
|
||||
|
||||
const logoImage = await loadImage(logoUrl);
|
||||
|
||||
const moduleSize = CANVAS_SIZE / moduleCount;
|
||||
|
||||
let logoModules = Math.floor(moduleCount * 0.3);
|
||||
if (logoModules % 2 !== moduleCount % 2) {
|
||||
logoModules += 1;
|
||||
}
|
||||
|
||||
const backgroundSize = logoModules * moduleSize + 1;
|
||||
const backgroundPosition = (moduleSize * (moduleCount - logoModules)) / 2;
|
||||
|
||||
const logoSize = backgroundSize - LOGO_PADDING * 2;
|
||||
const logoPosition = backgroundPosition + LOGO_PADDING;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillRect(
|
||||
backgroundPosition,
|
||||
backgroundPosition,
|
||||
backgroundSize,
|
||||
backgroundSize,
|
||||
);
|
||||
ctx.drawImage(logoImage, logoPosition, logoPosition, logoSize, logoSize);
|
||||
|
||||
return canvas;
|
||||
};
|
||||
61
shared/utils/settings.ts
Normal file
61
shared/utils/settings.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { z } from "zod";
|
||||
|
||||
// TODO: might be better to load these dynamically lol
|
||||
export const LOGOS = [
|
||||
"bereal",
|
||||
"bitcoin",
|
||||
"buymeacoffee",
|
||||
"diaspora",
|
||||
"discord",
|
||||
"dropbox",
|
||||
"ello",
|
||||
"facebook",
|
||||
"flickr",
|
||||
"github",
|
||||
"googlemaps",
|
||||
"googlemeet",
|
||||
"googlemessages",
|
||||
"imessage",
|
||||
"instagram",
|
||||
"kik",
|
||||
"line",
|
||||
"linkedin",
|
||||
"litecoin",
|
||||
"mastodon",
|
||||
"medium",
|
||||
"messenger",
|
||||
"monero",
|
||||
"onlyfans",
|
||||
"patreon",
|
||||
"paypal",
|
||||
"peertube",
|
||||
"pinterest",
|
||||
"reddit",
|
||||
"session",
|
||||
"signal",
|
||||
"snapchat",
|
||||
"spotify",
|
||||
"substack",
|
||||
"telegram",
|
||||
"threema",
|
||||
"twitch",
|
||||
"venmo",
|
||||
"viber",
|
||||
"wechat",
|
||||
"whatsapp",
|
||||
"x",
|
||||
"youtube",
|
||||
"zoom",
|
||||
] as const;
|
||||
|
||||
export const IMAGE_FORMATS = ["png", "jpeg", "webp"] as const;
|
||||
|
||||
export type ImageFormat = (typeof IMAGE_FORMATS)[number];
|
||||
|
||||
export const settingsSchema = z.object({
|
||||
format: z.enum(IMAGE_FORMATS).default("png"),
|
||||
logo: z.enum(LOGOS).optional(),
|
||||
content: z.string().min(1, "Required"),
|
||||
});
|
||||
|
||||
export type Settings = z.infer<typeof settingsSchema>;
|
||||
Reference in New Issue
Block a user